1

我已经坚持了几天,这真的很令人沮丧。

popen()用来调用命令行进程并获取其输出并将其存储在 C 字符串中。我正在使用fgets(),但似乎在换行后会中断,所以我正在使用fread(). 唯一的问题是返回的 C 字符串有时会搞砸。

这是我的代码:

const char *cmd = "date";//This the shell command
char buf[BUFSIZ];//Output of the command
FILE *ptr;
int c;

if ((ptr = popen(cmd, "r")) != NULL)
     while(fread(buf, sizeof(buf),1, ptr))
          while ((c = getchar()) != EOF)
               printf("output = %s", buf);

(void) pclose(ptr);

最终的 C 字符串有时包含不应该存在的奇怪字符,或者有时甚至没有可用的字符串。有人可以帮忙吗?):

编辑:这是我在使用 fgets() 时所做的事情 Shell 命令可以是任何输出文本的命令。不仅仅是“约会”。


if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFSIZ, ptr) != NULL)
printf("output = %s", buf);
(void) pclose(ptr);

4

4 回答 4

3

fread doesn't insert a NUL terminator after what it reads. You need to check the return value to know how much it read, and only print that much. If you read with fread, you typically want to write the data with fwrite, something on this order:

long bytes;
while ((bytes=fread(buf, sizeof(buf), 1, ptr))>0)
    fwrite(buf, bytes, 1, stdout);
于 2011-07-14T21:17:14.127 回答
3

Well, fgets is the right way to do it.

FILE *ptr;

if (NULL == (ptr = popen(cmd, "r"))) {
    /* ... */
}

while(fgets(buf, sizeof(buf), ptr) != NULL) {
    /* There is stuff in 'buf' */
}

I think the reason fgets wasn't working for you is that you were doing something wrong.

Now, here's why I think you are running into trouble with your current code:

  • You are not checking how much fread actually returned
  • You are reading with getchar and discarding stuff
  • You don't have a NUL terminator in the buffer

Get this right and it will all be better: fread might legally read less than you told it to.

于 2011-07-14T21:17:49.743 回答
2

The output from date doesn't include the '\0' (NUL) character you need to properly terminate the string. Keep track of the number of characters read and put in the NUL yourself.

Though really, you should be using fgets, getline or similar text-oriented functions to read from a program such as date. getline is especially easy (and safe since it does some memory management for you):

FILE *fp = popen("date", "r");
char *ln = NULL;
size_t len = 0;

while (getline(&ln, &len, fp) != -1)
    fputs(ln, stdout);
free(ln);
pclose(fp);
于 2011-07-14T21:16:51.223 回答
1

以下是fread用于处理输出的正确方法popen

const char *cmd = "date";
char buf[BUFSIZ];
FILE *ptr;

if ((ptr = popen(cmd, "r")) != NULL) {
    /* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
    size_t byte_count = fread(buf, 1, BUFSIZ - 1, ptr);
    /* Apply null termination so that the read bytes can be treated as a string. */
    buf[byte_count] = 0;
    printf("%s\n", buf);
}

(void) pclose(ptr);

如您所见,主要问题是正确处理空终止。的两个大小参数fread也很重要,你必须让它逐个字符地读取。请注意,在 的情况下popenfread仅当进程退出且未提供任何输出时才会返回 0。如果该过程需要很长时间才能打印任何内容,它将不会返回 0。

如果输出大于BUFSIZ,可以freadwhile循环换行。

于 2015-08-26T03:37:16.747 回答