令博主崩溃的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有更多一点的理解!


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


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

相关文章
|
27天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
56 10
|
27天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
44 9
|
27天前
|
存储 Unix Serverless
【C语言】常用函数汇总表
本文总结了C语言中常用的函数,涵盖输入/输出、字符串操作、内存管理、数学运算、时间处理、文件操作及布尔类型等多个方面。每类函数均以表格形式列出其功能和使用示例,便于快速查阅和学习。通过综合示例代码,展示了这些函数的实际应用,帮助读者更好地理解和掌握C语言的基本功能和标准库函数的使用方法。感谢阅读,希望对你有所帮助!
37 8
|
27天前
|
C语言 开发者
【C语言】数学函数详解
在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
45 6
|
27天前
|
存储 C语言
【C语言】输入/输出函数详解
在C语言中,输入/输出操作是通过标准库函数来实现的。这些函数分为两类:标准输入输出函数和文件输入输出函数。
190 6
|
27天前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
59 6
|
27天前
|
C语言 开发者
【C语言】断言函数 -《深入解析C语言调试利器 !》
断言(assert)是一种调试工具,用于在程序运行时检查某些条件是否成立。如果条件不成立,断言会触发错误,并通常会终止程序的执行。断言有助于在开发和测试阶段捕捉逻辑错误。
37 5
|
7月前
|
存储 C语言
C 语言函数完全指南:创建、调用、参数传递、返回值解析
函数是一段代码块,只有在被调用时才会运行。 您可以将数据(称为参数)传递给函数。 函数用于执行某些操作,它们对于重用代码很重要:定义一次代码,并多次使用。
231 3
|
2月前
|
C语言
C语言函数返回值详解
本文详细解析了C语言中函数返回值的概念与应用。从函数的基本定义入手,深入探讨了不同类型返回值的作用及意义,并提供了实用的编程示例,帮助读者更好地理解和使用函数返回值。通过本文,你将掌握如何有效利用返回值优化代码结构与功能实现。
|
6月前
|
存储 C语言
C语言的函数返回值和指针
C|函数返回值(区分各类值)和指针(区分各类存储空间)的细节