GetChar缓存机制剖析

 GetChar缓存机制剖析

与缓存区相关最常见的操作就是字符的输入与输出操作getchar,getc,getch,getche,gets系列函数。

第一个例子(getchar有关)

  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     int ch;  
  5.     ch=getchar();  
  6.     ch=getchar();  
  7.     printf("%d\n",ch);  
  8.     return 0;  
  9. }  

代码如上,当输入一个字符按下回车后程序没有等待你二次输入就结束了,而且无论输入什么运行结果均是10,是不是很奇怪(反正我第一次遇到时感觉是很奇怪),更奇怪的是当你一次性输入多个字符如abcd结果又正确的打印出了98,为什么呢?这就是缓冲区的原因。

解释如下:getchar定义在stdio.h文件中,我们在stdio.h中可以找到其相关的定义:

  1. #define getchar()         getc(stdin)//即getchar等同于调用getc(stdin)  

我们又找到getc的定义

  1. #define getc(_stream)     (--(_stream)->_cnt >= 0 \  
  2.                 ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream))  

将其展开即得:

  1. if(--(stdin)->_cnt>=0)  
  2.       return 0xff&*(stdin)->ptr++;  
  1. else  
  2.         return filbuf(stdin);  

代码译如下stdin是标准输入流,查看MSDNstdio.h中可以看到定义如下:

Stdio.h中:

  1. #define stdin  (&_iob[0])  

跟踪即可得:

  1. _CRTIMP extern FILE _iob[];  

从上面代码可得_iobFILE结构类型的,查看stdio.h中可以看到FILE结构体定义如下:

  1. struct _iobuf {  
  2.         char *_ptr;  
  3.         int   _cnt;  
  4.         char *_base;  
  5.         int   _flag;  
  6.         int   _file;  
  7.         int   _charbuf;  
  8.         int   _bufsiz;  
  9.         char *_tmpfname;  
  10.         };  

从FILE结构中我们可以得到了上面getc宏定义中使用的_cnt,_ptr成员,但这些都是次要的,我们应该不难发现有这样几个成员_bufsize,_base分别对应的是缓冲区大小,缓冲区基地址,从这里得到一个显而意见的结论就是getchar函数使用了缓冲机制。(_cnt对应的是缓冲区的输入的字节数目,_ptr对应的是读指针的位置)

getc宏定义详解

  1. --(stdin)->_cnt>=0  

此句判断是否缓冲区内有数据,有的话就减一(表示又读了一个),并读取数据return 0xff&*(stdin)->ptr++,读完成后,将读指针向前移一个位置【重要】

好了,讲了这么多都是铺垫,现在回到正题为什么会出现上述结果:)

出现上述结果追根结底还是由于getchar函数使用了缓冲(看了上面的,我想大家也知道了,确实使用了缓冲)当输入一个字符按下回车后程序没有等待你二次输入就结束了,而且无论输入什么运行结果均是10这是因为当用户输入了一个字符后,并按下回车后,缓冲中会存入用户输入的字符以及换行键的ASCII(10 ~)【略去的回车的ASCII13,可能是为了跨平台,在Linux下,回车后就是换行10Windows下回车是先回车回到首行,再换行,即13 10(执行第一次getchar实际上是执行getcelse语句,填充缓存区后_cnt=2,_prt指向0位置,执行完后_cnt=1,_prt指向1位置),第二次执行getchar时,调用getc不会再执行else语句,执行的是if语句,故第二次不再等待用户输入了,直接执行,执行后cnt=0,prt指向位置2,并返回ptr指向位置1时的结果,即10,由于10为换行键,当执行遇到此时,会在执行完后清空缓存,ptr重新指向了位置0cnt=0

当输入abc的时候分析一样,只不过扫行了第二个getchar后,cnt=2,ptr指向了位置2


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
getchar 是C语言中的一个标准库函数,用于从标准输入缓冲区中读取一个字符。 在理解 getchar 缓存之前,我们首先需要了解标准输入缓冲区(stdin buffer)。当我们使用输入函数时,如 scanf 或 getchar,输入的字符并不会立即被程序读取,而是会先存储在标准输入缓冲区中。 当我们调用 getchar 函数时,它会首先检查标准输入缓冲区是否为空。如果不为空,则直接从缓冲区中读取一个字符并返回;如果为空,则会等待用户输入,直到输入一个字符并按下回车键。 因此,getchar 缓存是指标准输入缓冲区中暂时存储的字符。这意味着,如果在调用 getchar 函数之前用户已经输入了字符,那么在调用 getchar 时会直接读取该字符;如果在调用 getchar 函数之前用户没有输入任何字符,则会阻塞程序等待用户输入。 需要注意的是,getchar 缓存是以字符为单位进行读取的。也就是说,每次调用 getchar 函数只能读取一个字符。 为了清空标准输入缓冲区中的字符,我们可以使用 getchar 函数的一个常见用法,即在需要清空缓冲区时,循环调用 getchar 函数直到缓冲区为空。例如,可以使用下面的代码片段来清空缓冲区: ```c int c; while((c = getchar()) != '\n' && c != EOF); ``` 总之,getchar 缓存是指标准输入缓冲区中临时存储的字符,它可以用来获取用户输入的字符。我们可以通过调用 getchar 函数来读取缓存中的字符,并使用循环来清空缓冲区。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值