繁体   English   中英

如何将数据传递给在Linux中调用scanf()和read()的程序

[英]How to pipe data to a program which calls scanf() and read() in Linux

我有一个C程序,看起来像这样:

#include <stdio.h>
#include <unistd.h>

int main()
{
    int n;
    char str[16];
    scanf("%d", &n);
    printf("n: %d\n", n);

    int count = read(STDIN_FILENO, str, 16);
    printf("str: %s\n", str);
    printf("read %d bytes\n", count);
}

如果我使用类似命令将数据传输到此程序中

(echo -en '45\n'; echo -en 'text\n') | ./program

只有scanf()实际读取数据。 read()只读取0个字节。

换句话说,程序输出

n: 45
str:
read 0 bytes

如何将数据传输到scanf()read()

编辑:对不起,我应该澄清:我正在寻找一种方法来做到这一点,而无需修改源代码。 感谢那些回答和评论的人。

根本不建议对同一文件描述符使用文件描述符函数(读取)和流函数(scanf)。 使用FILE * (即fread / fprintf / scanf / ...)的函数是缓冲数据,而使用文件描述符(即read/write/... )的函数不使用这些缓冲区。 在您的情况下,修复程序的最简单方法是使用fread而不是read 该计划可能如下所示:

#include <stdio.h>
#include <unistd.h>

int main() {
  int n;
  char str[16];
  scanf("%d", &n);
  printf("n: %d\n", n);

  int count = fread(str, 16, 1, stdin);
  printf("str: %s\n", str);
  printf("read %d bytes\n", count);
}

在您的原始示例中, scanf已经读取了前面的输入并将其存储在其缓冲区中。 因为输入很短并且可以立即使用,所以它完全被读取到缓冲区并且您的read调用没有更多要阅读。

直接从终端输入输入时不会发生这种情况,因为从终端设备读取时, scanf不会将数据缓冲超过一行。 如果您通过命令在管道输入中创建时间暂停,也不会发生这种情况:

(echo -en '45\n'; sleep 1; echo -en 'text\n') | ./program
#include <stdio.h>
#include <unistd.h>

int main()
{
    int n;
    char str[16];
    setbuf(stdin, NULL); // Ensure that there's no buffering for stdin
    scanf("%d", &n);
    printf("n: %d\n", n);

    int count = read(STDIN_FILENO, str, 16);
    printf("str: %s\n", str);
    printf("read %d bytes\n", count);
}

正如前面的答案所说,scanf引起了你的问题,因为它使用缓冲区。 因此,您可以通过调用setbuf(stdin,NULL)来确保它不会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM