【问题标题】:How to print multiple lines in C, with popen?如何用popen在C中打印多行?
【发布时间】:2021-05-12 12:12:58
【问题描述】:

如何在 C 中使用popen 打印多行? 所以我不知道如何打印其余的行 这是一个学校项目,我不知道该怎么做。输入文件只包含一个单词。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
    
int main() {
    FILE *f, *fp;
    int MAX=256;
    char buf[MAX];
    
    f=fopen("input", "r");
    
    if(!f){
        fprintf (stderr,"no input \n");
        exit(1);
    }
    
    fgets(buf,MAX,f);
    char cmd[MAX];
    sprintf(cmd, "find ~ -name %s 2>/dev/null", buf);
    
    if ((fp=popen(cmd, "r"))==NULL){
        perror("perror hiba");
        exit(1);
    }
    if (pclose(fp)==-1) perror("pclose error");
    
    close(f);
    return 0;
}

输出只有一行

【问题讨论】:

  • 欢迎来到 Stack Overflow!您对待来自popen 的文件指针(fp)与对待来自fopen 的文件指针f 完全相同;你可以用fgets()读一行,然后用printf打印出来
  • 您的意思可能是fclose(f); 而不是close(f)。根据输入和前提条件,我要么没有得到任何输出,要么收到来自find 的错误消息。这是我所期望的,因为 1. 代码不处理可以从 fp 读取的数据和 2. fgets 读取的数据可能包含换行符。请edit您的问题并显示您使用的输入、现有文件和目录等先决条件以及实际和预期的输出。确保您运行的代码与问题中显示的代码完全相同。使用复制和粘贴。
  • 比 fclose() pclose() 更好...... pclose() 执行 waitpid(),而 fclose() 没有。
  • 欢迎来到 Stack Overflow!请不要将解决方案公告编辑到问题中。接受(即单击旁边的“勾选”)现有答案之一,如果有的话。如果现有答案尚未涵盖您的解决方案,您还可以创建自己的答案,甚至接受它。

标签: c popen


【解决方案1】:

解决 OP 的实际问题很简单,但我想添加一些他们没有询问的额外注释。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
    
int main() {
    FILE *f, *fp;
    int MAX=256;
    char findpath[MAX];
    
    f=fopen("input", "r");
    
    if(!f){
        fprintf (stderr,"no input \n");
        exit(1);
    }
    
    fgets(findpath,MAX,f);
    char cmd[MAX];
    sprintf(cmd, "find ~ -name %s 2>/dev/null", findpath);
    
    if ((fp=popen(cmd, "r"))==NULL){
        perror("perror hiba");
        exit(1);
    }

    char copybuf[MAX];
    // do the copy from the process to the output place
    while (fgets(copybuf, sizeof buf, fp) != NULL)  // read from popen
    {
        // maybe do some other processing on each line
        fputs(copybuf, stdout);
    }

    if (pclose(fp)==-1) perror("pclose error");

    fclose(f);  // not close(f) -- hat tip to Bodo
    return 0;
}

一个小的变化是第一个缓冲区现在是 findpath 而不是 buf - 很容易将缓冲区与通用名称混淆,因此获得一个好的名称可以帮助避免其中一些。使用 cmd 是该缓冲区的绝佳选择。

另外:如果从input 文件中读取的文件名中包含空格(此处假设为“我的文件”),则当前代码将无法正常运行:

    find ~ -name my file 2>/dev/null

这不会如您所愿,尽管空格在 Linux 平台上并不常见,但需要注意。

部分修复将是

sprintf(cmd, "find ~ -name '%s' 2>/dev/null", findpath)

它可以防止空格,但是如果文件名上有单引号怎么办?

在实践中,这真的很难做到。

但最后,我将把这个作为练习留给读者,如果您的输入文件包含以下内容会发生什么:

some_directory; rm -rf ~

注意分号!会发生什么?

如果 input 文件来自不受信任的来源,您必须非常小心。

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多