C 语言:popen() 和 fread()?

发布于 2024-11-23 21:04:34 字数 802 浏览 1 评论 0原文

我已经在这个问题上坚持了几天了,这真的很令人沮丧。

我使用 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);

I've been stuck on this for a few days and it's getting really frustrating.

I'm using popen() to call a command line process and get its output and store it in a C string. I was using fgets() but it seems that breaks after a new line, so I'm using fread(). The only problem is that the returned C string is sometimes messed up.

Here's my code:

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);

The final C string sometimes has weird characters in it that shouldn't be there, or sometimes no string is even available. Can anybody please help? ):

Edit: Here is what I was doing when using fgets() The Shell command can be anything that outputs text though. Not just "date."

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

是伱的 2024-11-30 21:04:34

fread 不会在读取的内容后插入 NUL 终止符。您需要检查返回值以了解读取了多少内容,并且仅打印该内容。如果您使用 fread 读取数据,则通常需要使用 fwrite 写入数据,顺序如下:

long bytes;
while ((bytes=fread(buf, sizeof(buf), 1, ptr))>0)
    fwrite(buf, bytes, 1, stdout);

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);
心如荒岛 2024-11-30 21:04:34

嗯,fgets 是正确的方法。

FILE *ptr;

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

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

我认为 fgets 不适合你的原因是你做错了什么。

现在,这就是为什么我认为您当前的代码遇到了麻烦:

  • 您没有检查实际返回了多少 fread
  • 您正在使用 getchar 读取并丢弃
  • 您不这样做的 东西缓冲区中没有 NUL 终止符

正确处理这一点,一切都会更好:fread 可能会合法地读取比您告诉它的更少的内容

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.

迷迭香的记忆 2024-11-30 21:04:34

下面是使用 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);

如您所见,首要问题是正确处理 null 终止。 fread的两个size参数也很重要,你必须让它一个字符一个字符地读取(意味着fread的第二个参数必须是1 )。

请注意,在 popen 的情况下,如果进程退出且没有给出任何输出,fread 将仅返回 0。如果进程需要很长时间才能打印任何内容,它不会返回 0。

如果输出大于 BUFSIZ,您可以用 while 循环包装 fread

Below is the correct way to use fread for process output with 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);

As you can see, the primary problem is to correctly deal with null termination. The two size parameter of fread is also important, you have to let it read character by character (means that second parameter of fread must be 1).

Note that in the case of popen, fread will only return 0 if the process has exited without giving any output. It will not return 0 if it takes a long time for the process to print anything.

If the output is larger than BUFSIZ, you can wrap fread with a while loop.

但可醉心 2024-11-30 21:04:34

date 的输出不包含正确终止字符串所需的 '\0' (NUL) 字符。跟踪自己读取并放入 NUL 的字符数。

虽然实际上,您应该使用 fgetsgetline 或类似的面向文本的函数,用于从 date 等程序中读取。 getline 特别简单(而且安全,因为它为您做了一些内存管理):

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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文