在输入字符串的时候,我们经常会用到 getchar()这个函数。比如下面这个经典的用法:
int main() {
int ch;
while ((ch = getchar()) != EOF) {
putchar(ch);
}
return 0;
}
第一行输入:ccc (换行)
第二行输出:ccc
并且光标会出现在第三行。
接下来,我们用比较通俗的语言来解释一下这个过程计算机内部发生了什么。
当我们从键盘输入字符的时候,字符在一个名叫做缓冲区的地方暂时存起来,这个时候还没有getchar什么事情,我们的字符并没有传输给他,当我们输入了换行(\n),这个换行符同时也储存在了输入缓冲区,并且触发了getchar()的操作条件,这个时候,循环开始,缓冲区里面的东西开始一个一个进行了getchar操作,并在循环里面执行了putchar操作,显示在了我们的显示屏上,还记得我上面强调的换行符本身也储存在了缓冲区里面,当然这个换行符也会进行输出,这也就解释了为什么光标会出现在第三行。这个时候缓冲区已经清空,在这个过程中,没有EOF,所以我们继续输入,在下一次按下换行键之后依然会照上面的流程进行再次输出。
在这个过程中,涉及到了几个术语,遇到换行符缓冲区就开始向函数传递字符这个机制叫做行缓冲,而把字符传给getchar,putchar输出这个过程叫做标准I/O操作。
emmm,我想这个基本的机制我已经解释清楚了。当然在探索这个机理的过程中也遇到了许多有趣的事情和问题 ,下面我简单分享一下我的收获。
首先,缓冲区是分为输入缓冲区和输出缓冲区的,我们键盘输入的字符,其实是以ASCII码的形式储存在了出入缓冲区,在调用getchar()的时候,其实也一直是输入缓冲区的字符在”发射“。但他们并不是直接发射到我们的显示屏上面的,这个中间还有一个输出缓冲区,这些字符在经过putchar()之后,进入了输出缓冲区,到达显示屏的字符,上一个停留的区域其实是输出缓冲区。
还有一个有意思的事情,什么叫做标准I/O操作呢,其实I就是input,O就是output。当然规范的解释还有一个流的概念,小编暂时还没有完全搞明白(流汗)。
在涉及输入输出缓冲区的时候,有两个函数也是比较关键的,那就是fflush()刷新缓冲区函数,他们分别是fflush(stdin)和fflush(stdout),前者对应刷新输入缓冲区,作用是输入缓冲区的东西没有了,但是并没有到屏幕上,而后者的作用是输出缓冲区的东西没有了,里面的东西强制到了屏幕上,仔细想想是一个很严谨有趣的事情。
getchar()的应用有输入缓冲区的参与,其他的输入性函数也有这样的机制,比如scanf(),gets(),但是和getchar有一个巨大的区别就是,这两个会把空格,制表符,换行符,作为分割标志,遇到这些符号,就停止向函数传入值了,但是!这些分隔符并不会传入到函数中,而且他们会保留在输入缓冲区里面,我们来看一个例子:
int main() {
char x[100];
scanf("%s", x);
char y[1000];
gets(y);
printf("%s", y);
return 0;
}
我的想法是先进行一个输入abc然后换行在输入def,输出y的时候能理所当然的输出def,但是运行结果是这样的:
abc
--------------------------------
Process exited after 1.442 seconds with return value 0
请按任意键继续. . .
abc后面有一个空行,这是因为当我们输入abc之后按下了换行,由于换行起到了分割的作用,所以scanf只读入了abc,换行符还留在输入缓冲区里面,当遇到gets的时候,自然给到了y,输出y的时候也便只有一个换行符。
胡思乱想,多问一个为什么总是能发现新世界。
|