在scanf之后使用read系统调用

时间:2013-04-01 06:04:23

标签: c scanf

我对以下代码感到困惑,

#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仍将在stdin缓冲区
  3. 当读取尝试读取标准输入时(已abcd已存在),应将abcd放入buf
  4. 所以printf应该打印abcd
  5. 但它没有发生,printf显示没有o / p

    我在这里错过了什么吗?

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

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

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

    在用户返回之前,没有数据可供阅读。此时,标准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()的返回值,以确保它确实读取了一个数字。

答案 2 :(得分:1)

首先尝试... man read

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

和stdin被声明为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仍然在stdin缓冲区上。

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

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

这就是为什么我要求你使用fread。希望它有所帮助。