我这里有运行 /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。解决这个问题的正确方法是什么?
最佳答案
首先是while(fgets(path,100,fp)!= NULL){
已存储第一个 99
从 path
中的管道读取的字符。没有必要scanf
其他任何东西。
100
是一个严重不足的神奇数字,无法包含在代码中以获得最大路径长度。更好用PATH_MAX
定义于 limits.h
。 (通常 4096
,但由实现定义)。这就引出了另一点,不要在代码中使用魔数(Magic Number),如果你需要系统没有提供的常量,那么 #define
之一,或使用全局 enum
来定义它。
使用fgets
阅读时,您必须检查并删除(或以其他方式说明) '\n'
将包含在 fgets
填充的缓冲区中(和 POSIX getline
)。这还可以验证您确实读取了完整的数据行。否则,如果读取的行长度为 PATH_MAX - 1
并且没有'\n'
最后,该行对于缓冲区来说太长,并且该行的字符在输入流中仍未读取。简单调用strlen (path)
然后检查 if/else if
语句提供验证并允许您覆盖尾随 '\n'
带有nul终止字符。
要处理“我需要提供多少个文件?”的问题,您可以简单地使用指向字符的指针并动态分配指向每一行的指针, realloc
根据需要提供额外的指针。您将分配用于存储每一行的每个内存块的地址分配给您分配的各个指针。保留行数(用于指针计数)和 realloc
当您达到限制时更多指针(这适用于以相同的方式从文本文件中读取)不要忘记在完成后释放您分配的内存。
将所有部分放在一起,您可以执行如下操作:
#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) 始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放。
对于 Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们使用起来都很简单,只需通过它运行您的程序即可。
$ valgrind ./bin/popen_ls_files > /dev/null
==7453== Memcheck, a memory error detector
==7453== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==7453== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==7453== Command: ./bin/popen_ls_files
==7453==
==7453==
==7453== HEAP SUMMARY:
==7453== in use at exit: 0 bytes in 0 blocks
==7453== total heap usage: 1,777 allocs, 1,777 frees, 148,929 bytes allocated
==7453==
==7453== All heap blocks were freed -- no leaks are possible
==7453==
==7453== For counts of detected and suppressed errors, rerun with: -v
==7453== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放分配的所有内存并且不存在内存错误。
仔细检查一下,如果您还有其他问题,请告诉我。
关于c - 从管道保存到字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48480629/