2

我对以下代码感到困惑,

#include<stdio.h>

int main()
{
 char buf[100]={'\0'};
 int data=0;
 scanf("%d",&data);
 read(stdin,buf,4);         //attaching to stdin
 printf("buffer is %s\n",buf);

 return 1;
 }

假设在运行时我提供了输入10abcd,因此根据我的理解应该发生以下情况:

  1. scanf 应该放在10数据中
  2. 并且abcd仍然在标准输入缓冲区
  3. 当 read 尝试读取标准输入(已经abcd存在)时,它应该abcdbuf
  4. 所以 printf 应该打印abcd

但它没有发生,printf 没有显示 o/p

我在这里错过了什么吗?

4

3 回答 3

4

首先read (stdin, ...)应该给出警告(如果您启用了它们),您应该明智地注意。 read()将整数作为第一个参数,指定要从哪个通道读取。 stdin是类型FILE *

即使您将其更改为read(0,...,也不建议这样做。 scanf正在读取从FILE *stdin文件句柄 0 缓冲的文件。 read (0, ...)直接从底层文件句柄读取并忽略任何缓冲的字符。这将导致奇怪的结果,除非stdin设置为无缓冲。

于 2013-04-01T06:09:56.693 回答
3

忽略与函数调用语法相关的机械问题read(),有两种情况需要考虑:

  1. 输入来自终端。
  2. 输入来自文件。

终端

在用户点击返回之前,没有数据可供读取。此时,标准 I/O 库会将所有可用数据读入与之关联的缓冲区stdin(即“10abcd\n”)。然后它将解析数字,将a缓冲区中的数字留给其他标准 I/O 函数稍后读取。

read()发生这种情况时,它也会等待用户提供一些输入。它不知道stdin缓冲区中的数据。它将挂起,直到用户点击返回,然后将读取下一批数据,在缓冲区中返回最多 4 个字节(除非碰巧第四个字符是 ASCII NUL ,否则不会出现空终止'\0')。

文件

实际上,这并没有太大的不同,除了不是将一行数据读入缓冲区,标准 I/O 库可能会读满整个缓冲区(BUFSIZ字节,可能是 512 或更大)。然后它将转换10并留下a供以后使用。(如果文件短于缓冲区大小,则将全部读入stdin缓冲区。)

然后read将从文件中收集接下来的 4 个字节。如果整个文件已经被读取,那么它将什么都不返回——读取了 0 个字节。


您需要记录并检查read(). 您还应该检查返回值,scanf()以确保它确实读取了一个数字。

于 2013-04-01T06:23:03.990 回答
1

试试……man read先。

read 被声明为 ssize_t read(int fd, void *buf, size_t count);

并且标准输入被声明为 FILE *。这就是问题所在。使用 fread() 代替,您将被排序。

int main()
{
 char buf[100]={'\0'};
 int data=0;
 scanf("%d",&data);

 fread(buf, 1, 4, stdin);
 printf("buffer is %s\n",buf);

 return 1;
}

编辑:您的理解几乎是正确的,但并不完全正确。为了正确解决您的问题,我同意 Jonathen Laffer 的观点。

你的代码是如何工作的,

1) scanf 应在数据中放置 10。

2) 当您按下 ENTER 时,abcd 仍将位于标准输入缓冲区中。

3) 然后 read() 将再次等待输入,您必须再次按 ENTER 才能进一步运行程序。

4)现在,如果您在第二次按 ENTER 之前输入了任何内容, printf 应该打印它,否则除了您的 printf 语句之外,您将不会得到任何输出。

这就是为什么我让你用 fread 代替。希望能帮助到你。

于 2013-04-01T06:14:51.680 回答