令博主崩溃的scanf函数-C语言

简介: 令博主崩溃的scanf函数-C语言

前言:


 这篇博客的来源呢,源于一个同学在学习群里发出一段代码,他对代码有疑惑,疑惑的是,为什么只有输出三行,而不是四行?实际上误打误撞的巧合。我在看完那段代码和他的问题之后,和他一起探讨和发挥猜想,更进一步的了解了scanf的使用。


1.了解scanf()、getchar()和putchar


 这段代码相信大家都能懂,如果能让你有点不懂的那就是忘记了getchar()和putchar的一些使用方法 。嗯我们循序渐进,跟着我一起思考!


2.scanf输入的奇怪现象


 其实,我想说的是这个b里的10并不是随机来的,我们还敲了个回车,这时你就问,敲回车不只是为了让scanf确认读取吗?还能有其它作用?


 补充:换行符('\n')的ASCII码值为10,回车('\r')的ASCII码值为13,我们日常说的回车和ASCII码值是不一样,口头说的回车是换行的意思。


 我这补充一说,大家伙可能就知道b里的10怎么来的了吧,没错,就是回车被getchar()读走了。


 输入缓冲区:当我们用在输入的时候,是有这样一块区域存在的,它用来存放你输入的信息,scanf()和getchar()看到这块区域没有内容,就会停下来等你输入。


3.scanf格式对回车的处理


我们看这段,当我们输入5然后回车,第二个scanf并没有让我们等待,而是直接跳过,来到getchar()这等待,因为缓冲区里有回车,并且是scanf("%c", &b);想要的内容,它就直接读取了,而且不需要你回车,这点可以用后面的getchar()等待来证明。


   那这两个连续的输入是怎么实现的呢?当我输入一个5和回车的时候,到第二个scanf("%d", &b);不应该是直接就跳过了吗,因为我缓冲区里有回车在呀,那为什么还要我们输入?


  答案是:缓冲区里面确实是有回车,但是我们要的是"%d",回车不是scanf要的类型,它丢弃掉这个回车后就没有内容了,所以就停下来等我们继续输入。看下面的代码:

 这里是来解释为什么是丢弃的原因,对比看。上面是scanf后,getchar读得到,下面是最后一个getchar要等待,如果我们没有丢弃的话,第二次输入应该是:回车 + 6 + 回车(确认读取),读掉6后还剩两个回车,那我没下面两个getchar没有任何一个需要等待。



 总结一下:scanf输入确实是需要看格式限制的,格式不对,它就不读取,如果还是个回车,那它还会丢弃掉它,如果格式是对的,比如是字符格式,缓冲区里有回车,那它既把回车看成是要读取的内容还看成是结束的标志。



 我们反回去剖析一下,首先输入5回车,等待输入,其实(等待输入前还有一步就是丢弃上次遗留下来的回车),6回车,读取6,此时缓冲区里还有个回车在。

  最后一个10是自己蹦出来的


4.小谈一下:

  到这里你以为就完了吗,不不不,还有的,否则怎么能令博主奔溃呢,博主崩溃的原因是因为在边写的过程中,觉得scanf有好多种情况,边写边觉得有好多种都可以解释。。。ok,继续。


5.格式对scanf的重要性

 这就是同学在群里发的代码,因为输入的情况读者可能不清楚,我来说一下,在输入5后回车,跳到下一行我再输入一个6后回车,来到下一行有整数B:,然后我输入了7后回车,最后就出结果啦。


 大家有疑惑没?如果你把格式里的"%d\n"里的\n看成printf("\n"),那就是你输入5回车,然后换行,再输入6,再换行,也就是4行。我敲出来哈!



 就是他的想法是这样的,但scanf格式里的"%d\n"可不是打印函数里的"\n"噢,可不敢这么想!


 


  这里面也有学问在!那就是,你有没有看到结果是0.833333,很明显是5.0/6的结果,如果我们看向的是整数A:5和整数B:7这两个数字,5.0/7的结果可是0.714286噢。为什么,听我慢慢道来。


  我们最先输入了5和回车('\n'),scanf在缓冲区里只看到5,而回车是我们用来确认的,所以scanf没找到自己格式要的内容,所以要我们继续要输入,但我们回车了,窗口就到下一行了,接着我们在第二行输入6和回车,这下就不一样了,缓冲区里的内容是5'\n'6和一个确认的回车,scanf看到5'\n',那好scanf说:我就读走了,但是存到a里的是5'\n'吗,不是,就是5,%d,其它的只是格式。


  到第二个scanf了,这个时候缓冲区里有6'\n',当我们输入7回车,它就读走了6'\n',也就是把6放进了c。所以结果就是5.0/6啦。


 读完后,希望读者对scanf有更多一点的理解!


 好啦,这就是本节的内容,同以前一样,文章排版,内容分布,或有错误的,都可以在评论中告诉博主,博主也好改正。


 求点赞,求点赞,求点赞!

相关文章
|
10天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
25 3
|
1天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
17 10
|
5天前
|
存储 编译器 C语言
C语言函数的定义与函数的声明的区别
C语言中,函数的定义包含函数的实现,即具体执行的代码块;而函数的声明仅描述函数的名称、返回类型和参数列表,用于告知编译器函数的存在,但不包含实现细节。声明通常放在头文件中,定义则在源文件中。
|
11天前
|
C语言
c语言回顾-函数递归(上)
c语言回顾-函数递归(上)
27 2
|
10天前
|
C语言
C语言函数
C语言函数
10 0
|
11天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
34 0
|
11天前
|
C语言
c语言回顾-函数递归(下)
c语言回顾-函数递归(下)
29 0
|
C语言
C语言学习之 scanf
C语言学习之 scanf
106 0
C语言学习之 scanf
|
13天前
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
16 3
|
16天前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数