从管道保存到字符串

时间:2018-01-27 21:12:46

标签: c scanf popen

我的代码运行/bin/ls -l,然后将输出打印到终端,我想在这里做的是将输出保存到字符串中供以后使用。我不知道怎么做这个,但从我的猜测看起来会像这样

int main (){
    FILE *fp;
    int status;
    char path[100];
    char *s;
    fp = popen("/bin/ls -l", "r");
    if (fp == NULL){
        printf("fp error");
    }
    while(fgets(path,100,fp)!= NULL){
        printf("%s\n", path );
        scanf(path, s);
    }
    status = pclose(fp);
    if (status==-1){
        printf("pclose error");
    }else{
        printf("else on pclose\n");
    }
    return 0;
}

while循环打印出我的目录结果没有问题,但我遇到了一个分段错误:11结束时。解决这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

首先,while(fgets(path,100,fp)!= NULL){已存储从99中的管道中读取的第一个path个字符。没有必要scanf其他任何内容。

100是一个非常不足的幻数,要在代码中包含最大路径长度。最好使用PATH_MAX中定义的limits.h。 (通常是4096,但是是实现定义的)。这提出了另一点,不要在代码中使用幻数,如果你需要系统不提供的常量,那么#define一个,或者使用全局{{1定义它。

使用enum阅读时,您必须检查并删除(或以其他方式说明)将fgets填充的缓冲区'\n'(和POSIX {{ 1}})。这也提供了您实际上读取完整数据行的验证。否则,如果读取的行的长度为fgets并且末尾没有getline,则缓冲区的行太长,并且该行的字符在输入流中保持未读。对PATH_MAX - 1进行简单调用,然后使用'\n'语句进行检查即可提供验证,并允许您使用 nul-terminatedating 字符覆盖尾随strlen (path)

要解决“我需要提供多少文件?”的问题,你可以简单地使用指针指向字符,并动态地为每一行分配指针,根据需要if/else if个附加指针。您将分配用于存储每一行​​的每个内存块的地址分配给您分配的各个指针。当你达到极限时,保持对行的计数(对于指针计数)和'\n'更多的指针(这适用于以相同的方式从文本文件中读取)不要忘记释放你分配的内存完成它。

将所有部分组合在一起,您可以执行以下操作:

realloc

示例使用/输出

realloc

内存使用/错误检查

在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放

对于Linux #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #define NFILES 16 int main (){ size_t i, n = 0, /* number of files in listing */ nfiles = NFILES; /* number of allocated pointers */ char path[PATH_MAX] = "", /* buffer (PATH_MAX in limits.h) */ **files = NULL; /* pointer to pointer to file */ FILE *fp = popen("/bin/ls -l", "r"); if (fp == NULL) { /* validate pipe open for reading */ perror ("popen"); return 1; } /* allocate/validate initial number of pointers */ if (!(files = malloc (nfiles * sizeof *files))) { perror ("malloc - files"); return 1; } while (fgets (path, PATH_MAX, fp)) { /* read each line */ size_t len = strlen (path); /* get length */ if (len && path[len - 1] == '\n') /* validate '\n' */ path[--len] = 0; /* trim '\n' */ else if (len + 1 == PATH_MAX) { /* check path too long */ fprintf (stderr, "error: path too long.\n"); /* handle remaining chars in fp */ } /* allocate/validate storage for line */ if (!(files[n] = malloc (len + 1))) { perror ("malloc - files[n]"); break; } strcpy (files[n++], path); /* copy path */ if (n == nfiles) { /* realloc pointers as required */ void *tmp = realloc (files, nfiles * 2 * sizeof *files); if (!tmp) { perror ("realloc"); break; } files = tmp; nfiles *= 2; /* increment current allocation */ } } if (pclose (fp) == -1) /* validate close */ perror ("pclose"); /* print and free the allocated strings */ for (i = 0; i < n; i++) { printf ("%s\n", files[i]); free (files[i]); /* free individual file storage */ } free (files); /* free pointers */ return 0; } 是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。

$ ./bin/popen_ls_files > dat/filelist.txt

$ wc -l dat/filelist.txt
1768 dat/filelist.txt

$ cat dat/filelist.txt
total 9332
-rw-r--r--  1 david david     376 Sep 23  2014 3darrayaddr.c
-rw-r--r--  1 david david     466 Sep 30 20:13 3darrayalloc.c
-rw-r--r--  1 david david     802 Jan 25 02:55 3darrayfill.c
-rw-r--r--  1 david david     192 Jun 27  2015 BoggleData.txt
-rw-r--r--  1 david david    3565 Jun 26  2014 DoubleLinkedList-old.c
-rw-r--r--  1 david david    3699 Jun 26  2014 DoubleLinkedList.c
-rw-r--r--  1 david david    3041 Jun 26  2014 DoubleLinkedList.diff
<snip>
-rw-r--r--  1 david david    4946 May  7  2015 workers.c
-rw-r--r--  1 david david     206 Jul 11  2017 wshadow.c
-rw-r--r--  1 david david    1283 May 18  2015 wsininput.c
-rw-r--r--  1 david david    5519 Oct 13  2015 xpathfname.c
-rw-r--r--  1 david david     785 Sep 30 02:49 xrealloc2_macro.c
-rw-r--r--  1 david david    2090 Sep  6 02:29 xrealloc_tst.c
-rw-r--r--  1 david david    1527 Sep  6 03:22 xrealloc_tst_str.c
-rwxr-xr--  1 david david     153 Aug  5  2014 xsplit.sh

始终确认已释放已分配的所有内存并且没有内存错误。

仔细看看,如果您有其他问题,请告诉我。

答案 1 :(得分:0)

我假设您要将目录保存到字符串数组中。在这种情况下,Image数组会保留指向所有条目的指针。每个读取条目都将为条目和字符串终止符s[]分配内存。

启动程序可能如下所示:

\0

这样可行,但我们在堆栈上放了10,000个指针。但是,正如David C. Rankin所建议的那样,我们也可以动态地分配数组#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NR_OF_ENTRIES 10000 #define PATH_LEN 256 int main (){ FILE *fp; int status; char path[PATH_LEN]; char *s[MAX_NR_OF_ENTRIES]; int i,j = 0; fp = popen("/bin/ls -l", "r"); if (fp == NULL){ printf("fp error\n"); } while(fgets(path,PATH_LEN,fp) != NULL){ printf("%s\n", path ); s[i] = malloc(strlen(path)+1); strcpy(s[i],path); i++; if(i>=MAX_NR_OF_ENTRIES) { printf("MAX_NR_OF_ENTRIES reached!\n"); break; } } status = pclose(fp); if (status==-1){ printf("pclose error"); }else{ printf("pclose was fine!\n"); } // Print and free the allocated strings for(j=0; j< i; j++){ printf("%s\n", s[j] ); free (s[j]); } return 0; } 。开始工作计划:

s