![](/img/trans.png)
[英]Data written on Linux pipe by program 1 is sometimes read twice by program 2
[英]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.