2016-10-28 81 views
1

我有一个bash脚本,它打印一个巨大的变量输出行。 我见过的所有示例都使用1024字节左右的固定缓冲区,以便逐行阅读。我怎样才能分配一个可变长度的命令输出?

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) { 

    FILE *fp; 
    char path[1024]; 

    /* Open the command for reading. */ 
    fp = popen("bash /home/ouhma/myscript.sh", "r"); 
    if (fp == NULL) { 
    printf("Failed to run command\n"); 
    exit(1); 
    } 

    /* Read the output a line at a time - output it. */ 
    while (fgets(path, sizeof(path)-1, fp) != NULL) { 
    printf("%s", path); 
    } 

    /* close */ 
    pclose(fp); 

    return 0; 
} 

链接参考:C: Run a System Command and Get Output?

但是,如果我不知道是什么,如果输出线的长度更大的1024个字节? 如何通过使用popen()命令阅读来处理它?

+0

你可以使用POSIX ['getline()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html)来阅读尽可能长的一行,但只限于内存限制,或者你可以当你还没有收到换行符时,反复调用fgets(),添加一个你根据需要动态分配的缓冲区。这两者都不是很复杂,尽管使用getline()比使用getline()更容易。 –

+2

请注意,如果一行超过1024行,您当前的代码将继续在下一个fgets()调用中读取该行的其余部分。因此,只需打印出文本的当前代码就可以毫无问题地工作。 (然而,如果你想在你的程序中存储一整行并且在一段时间内操作该行 - 你需要看看alk的答案) – nos

回答

2

但如果我不知道,如果输出线的长度更大的1024个字节

然后您需要处理传入的数据动态存储。

要做到这一点,你会额外地显示你添加一个动态分配的“字符串”,如果通过重新分配来提供更多空间而被充分使用,它将会增长。

代码这样做可能是这样的:

#include <stdlib.h> 
#include <stdio.h> 


#define BUFFER_SIZE (1024) 
#define START_SIZE (1) /* Has to be > 0 */ 


int main(void) 
{ 
    size_t s = START_SIZE; 
    char * path = malloc(s); 
    if (NULL == path) 
    { 
    perror("malloc() failed"); 
    return EXIT_FAILURE); 
    } 

    path[0] = '\0'; 

    { 
    /* Open the command for reading. */ 
    FILE * fp = popen("bash /home/ouhma/myscript.sh", "r"); 
    if (NULL == fp) 
    { 
     perror("popen() failed"); 
     return EXIT_FAILURE); /* By returning here the code leaks the memory 
           already allocated to path as well as fp. */ 
    } 

    { 
     char buffer[BUFFER_SIZE]; 

     /* Read the output a line at a time - output it. */ 
     while (NULL != fgets(buffer, sizeof buffer, fp)) 
     { 
     fprintf(stderr, "partly read: '%s'\n", buffer); 

     while ((s - 1) < strlen(buffer)) 
     { 
      void * p = realloc(path, s *= 2); /* Grow s exponentially. */ 
      if (NULL == p) 
      { 
      perror("realloc() failed"); 
      return EXIT_FAILURE; /* By returning here the code leaks the memory 
            already allocated to path as well as fp. */ 
      } 

      path = p; 
     } 

     /* Concatenate what just had been read to final "string". */ 
     strcat(path, buffer); 
     } 
    } 

    if (!feof(fp)) 
    { 
     perror("fgets() failed"); 
    } 

    /* Close file. */ 
    if (-1 == pclose(fp)) 
    { 
     perror("pclose() failed"); 
    } 
    } 

    /* Print result. */ 
    printf("read: '%s'\n", path); 

    /* Clean up. */ 
    free(path); 

    return EXIT_SUCCESS; 
} 

清理打开的文件描述符和动态分配的内存中的任何故障的情况下作为练习留给读者...... ;-)

+0

作品就像一个魅力!谢谢@alk! – harrison4

相关问题