目录
- 前言
- getchar困惑的点
- 缓冲区
- 缓冲区带来的问题
- getchar工作原理
- 解决缓冲区带来的问题之清空缓存区
- 解决最初的困惑
- 总结
前言
近期我在重新学习c语言时候,我发现了一个严重的问题,getchar我居然不会用了….也不是说不会用,我发现了一个非常让我困惑想不明白的问题。可能我在第一次接触c语言时候,就没有把这个概念弄清楚吧,以至于现在会不明白。
getchar困惑的点
我利用getchar函数输入了一串字符abcd,然后把这串字符给到ch,然后紧接着我打印这个ch,然后我得到了一个字符a,看到这里大家没有感觉有什么问题对吧,当然没有问题,因为getchar只会读一个字符,自然就只读到了a,然后打印时候也自然而然就只打印了这个a出来。
好的我们接着往下看
看到这个我不知道大家有没有想到一个问题,反正我当时就是因为这个问题所困惑很久的。
首先通过第一个例子,我们知道了,getchar是只会读取一个字符
可是这个例子呢,我输入了一串字符abcde,按理说他也只是读取到一个字符,那就是这串字符中的第一个字符a,然后读取到了之后把它给了变量ch, 然后来判断这个ch等不等于eof。
eof是文件结束标志,在键盘上也就是ctrl+z 大家可以自己打印一下然后对照ascii码看一下
很显然,当前这个里面根本就没有ctrl+z,所以条件为真,然后执行打印语句。
根据上面我们那段分析,然后应该打印一个字符a对吗,疑惑的事情发生了,它打印了abcde!!!是的,完完整整打印出来了。
可能大家经常见到这个类似程序,然后习以为常了,都觉得是应该完完整整打印出来
好的,讲到这里大家是不是就觉得很困惑了,为什么会这样呢?
那我现在就好好给大家讲一下了,原来这里面还涉及到了一个概念
缓冲区
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
那么这个和我们的getchar又有什么联系呢?
当然有联系,当我们调用了getchar函数时候,这个函数内部其实是这样做的:
他此时会先从缓存区中读一遍,此时读完之后发现,缓存区中没有数据,他就会等待外部输入,光标此时就会一闪一闪的~
当我们外部输入了字符之后,然后我们就会敲回车结束,这时候我们输入的字符其实就直接全部存在了缓存区中。
假设我此时输入了字符abcd,然后回车结束,然后此时缓存区中就有了abcdn
注意,有意思的事情来了,还有n ???哈哈哈哈接着往下看
缓冲区带来的问题
大家仔细看一下有没有发现,为什么我getchar没有输入字符呢 ?
其实不是我没有输入字符,只是在我输入完scanf的字符之后,回车结束这个scanf的输入,然后奇怪的事情发生了,程序就直接结束了,是的,跳过了getchar输入字符这个过程。
大家有没有觉得奇怪?
这就是我刚才上面给大家提到的 n
是这样的,当我此时调用了scanf函数之后,我外部输入了 abcd,然后输入完abcd之后呢我要结束输入,然后我们就会去敲回车,注意!!这个回车其实也是一个字符,然后他也会连同我前面输入的abcd一起放到缓存区,也就是说此时缓存区中就有了abcdn
我们做一个小小的测试就知道了
看到这个打印的结果,大家明白了吧
getchar工作原理
原来调用getchar函数的时候,它其实是直接从缓存区中读,如果缓存区中有数据,他就会直接拿走第一个,然后他的使命也就结束了。其实这里呢就是上面scanf在缓存区中拿走了abcd,然后还剩下一个 10,这个10其实是n ,是它在ascii码中的表示。于是这个剩下的n就在缓存区中存下去了,然后他此时遇到了getchar函数,然后getchar在缓存区中读,发现:诶,还剩一个n,那么我就直接拿走,然后他的使命也就便结束了,所以就出现了不会等待我们外部输入的那种情况了。
那么我们可以解决这个问题吗?
解决缓冲区带来的问题之清空缓存区
明白了缓冲区和getchar的联系之后,其实我们想解决就很好办了
我们只需要在getchar读取之前在插入一个getchar函数,也就是说让他在下一次真正getchar读取之前,我们先再用一个getchar函数读一下那个缓存区剩下的n,这样下一次我们真正的getchar读取时候,缓存区就空了。
好了getchar的工作原理我们彻底明白了,那么我们在回到最初的那个疑惑上面。
解决最初的困惑
第一次循环:首先缓存区为空,光标闪烁,然后等待我的输入
我输入了一个字符a,然后我继续输入了回车结束,那么我此时其实输入了两个字符,一个字符a,一个字符 n,此时他们都被存放在了缓存区。然后缓存区有了数据之后,光标此时不在闪烁,getchar函数便开始直接读取,然后在这一次循环中,getchar函数读取到了一个字符a,然后将它给到ch,然后条件表达式为真(不等于ctrl+z),所以执行打印ch,然后打印出了一个字符a。
第二次循环:这时候缓存区还残留了一个n,光标不闪烁,getchar也不会等待外部输入
那么此时getchar直接读取到这个缓存区中的n,继续给到ch,然后表达式还是为真,所以继续打印这个ch,此时因为ch已经是被换掉了n,所以打印换行,光标位置发生改变。
第三次循环:缓存区为空,getchar读取不到数据,光标闪烁,getchar等待外部输入数据。
至此我们在接着往下看
第一次循环:缓存区为空,getchar读取不到缓存区的数据,于是光标闪烁,getchar等待外部输入数据。
此时我输入了一串abc,然后回车结束输入。此时缓存区中便有了字符abcdn,然后getchar读取第一个字符a,然后将它给到ch,然后条件表达式为真,打印了ch,于是第一个a就出来了。
第二次循环:缓存区还剩余bcn,getchar直接读取
此时getchar读取到字符b,然后给到ch,条件表达式为真,继续打印ch,此时便得到了ab。
第三次循环:缓存区还剩余cn,getchar直接读取
然后还是一样getchar读取到c,然后给到ch,之后表达式为真,打印出来了ch,然后经过这一次循环就得到了abc
第四次循环:缓存区还剩余一个n,最后打印这个n,于是光标下一行。
最终结果就得到了abc
然后我再次输入 ctrl+z
于是缓存区存在了ctrl+z(eof),然后getchar去读取,然后给到ch,然后表达式判断,条件为假,ch==eof,所以循环跳出,程序结束。
总结
getchar函数是直接从缓存区中读取数据,如果缓存区中有数据,则直接读取第一个数据,如果没有数据,那么就光标闪烁,等待外部输入数据。
要非常注意的是,我们其他地方输入的回车也会被存在缓存区当成一个字符,然后后面getchar也会将其直接读出,在这个地方很容易出错!!
到此这篇关于c语言中的getchar()使用详解的文章就介绍到这了,更多相关c语言getchar()内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!
需要了解更多c/c++开发分享C语言中的getchar()使用详解,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/1038023.html