getchar fflush 的分析笔记
问题描述:
统计从键盘输入的若干个字符中有效字符的个数,以换行符作为输入结束。有效字符是指第一个空格符前面的字符,若输入字符中没有空格符,则有效字符为除了换行符之外的所有字符。
示例代码:
#include<stdio.h> void main() { int count=0,ch; printf("\nPlease input a line char: "); fflush(stdout); while((ch=getchar())!='\n') { if(ch==' ') break; count++; } printf("\n valid char is %d \n",count); }
运行截图:
由于空格而break 由于换行符而退出 while
疑问:getchar() 函数每次只能读入一个字符,但是为什么这里一次就实现了一行字符的输入和处理呢? 简单的说:这是由于缓冲机制而实现的,以下层层分析:
分析字符是如何取的:修改while看看每次循环的 ch
#include<stdio.h> void main() { int count=0,ch; printf("\nPlease input a line char: "); fflush(stdout); while((ch=getchar())!='\n') { putchar(ch); putchar('\n'); fflush(stdout); if(ch==' ') break; count++; } printf("\nvalid char is %d \n",count); }
可见:每次循环确实是依次取一个字符来处理的,最后取的是空格符,打印空格换行后由于碰到 判断而break。
疑问还是存在,运行程序时,明明只输入了一次getchar(),怎么导致一行的字符都输入处理了呢?
缓冲机制示意图:系统在接收输入字符时,首先将字符存在了一段缓冲区域中,直到遇到换行符停止接收。如图,换行符 ‘\n’也会被存储在其中。
由于上述代码,在每次执行 getchar() 取字符时,并没有清掉缓冲区中的内容,所以,程序会一直从缓冲区中取字符数据。因此,while 循环依次取的字符为 ‘v’,’o’,’i’,’d’,’ ’,遇到空格后而break。
同样,在输入nospace时,也是依次从缓冲区中取字符。因此,while 循环依次取的字符为 ‘n’,’o’,’s’,’p’,’a ’,’c’,’e’,’\n’,遇到换行’\n’后而结束while循环。
如何利用fflush清除掉之前的缓冲?
- fflush(stdin) 清除掉 标准输入的缓冲 -- 本次实验对应 键盘
- fflush(stdout) 清除掉 标准输出的缓冲 -- 本次实验对应 终端
#include<stdio.h> void main() { int count=0,ch; printf("\nPlease input a line char: "); fflush(stdout); // fflush(stdin); // while((ch=getchar())!='\n') { putchar(ch); // putchar('\n'); // fflush(stdout); if(ch==' ') break; count++; fflush(stdin); // } printf("\nvalid char is %d \n",count); }
增加清除缓冲后,输入void main的运行截图,可见程序只处理了第一个字符’v’,然后由于不满足结束条件,又正在执行getchar() 取字符,但此时缓冲区中的字符已经被count++后面的fflush(stdin)清理了,故程序在等待用户输入字符。注意:输入语句下一行的’v’和换行是在while内打印出来的。
下面继续输入’o’,’i’,’d’,’ ’,getchar每次取到后,while循环中会打印出来并换行,直到碰到空格而break:
备忘:注意使用与逻辑while((ch!='\n')&&(ch!=' ')),之前由于逻辑错误用的或逻辑,导致程序死循环了:
#include<stdio.h> int main() { int count=0,ch; printf("\nPlease input a line char: "); fflush(stdout); // fflush(stdin); // do { fflush(stdin); ch = getchar(); putchar(ch); putchar('\n'); fflush(stdout); count++; }while((ch!='\n')&&(ch!=' ')); count--; printf("\nvalid char is %d \n",count); return 0; }
WIN运行环境:
Linux运行环境:测试发现、Linux环境下 fflush() 似乎不管用,具体可见参考博客
[root@localhost exp_getch]# uname -a Linux localhost.localdomain 3.11.10-301.fc20.i686+PAE #1 SMP Thu Dec 5 14:12:06 UTC 2013 i686 i686 i386 GNU/Linux
参考:
c primer plus 5th