我有一个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()?
编辑:对不起,我应该澄清:我正在寻找一种方法来做到这一点,而无需修改源代码.感谢那些回答和评论的人.
完全不建议对同一个文件描述符同时使用文件描述符函数(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