关于scanf的一些思考

来源:互联网 发布:如何评价我爱我家 知乎 编辑:程序博客网 时间:2024/05/19 16:28

 

      最近一直在学习C语言,业务需要嘛,呵呵,没办法。学习的过程中也遇到了很多的问题,自己也稍微研究了一下,有了一些解答。现在就对目前遇到的记录一下,以便以后用到。其实这些问题对高手来说都是挺简单的,只是作为新手可能会容易犯错的。

      晚上研究了一下scanf的一些用法,也是遇到了一个陷阱。

      程序:

     

      运行程序的时候会发现在printf("继续查询请输入Y或y,退出系统请按任意键···/n");处并没有停留下来,而是直接跳出了循环,刚开始的时候我也是百思不得其解,按道理说我的第一个scanf已经结束了,可为什么第二个scanf没有执行呢,那用作比较的flag又是从哪得到了数据呢。

       经过一番查证,终于明白了,原来是scanf输入缓存的问题。scanf根据第一个参数的指定有不同的接收数据的方式,在这里指定的是%d,也就是有符十进制整数,scanf会从stdin中获得对应的数据,其中stdin属于标准输入缓存,通常连接到键盘缓存,是从键盘缓存输入字符,然后将其送到控制台。如果我们输入120并且回车,此时缓存中应该是‘120/n’,当函数检测到第四个字符为‘/n’即非数字非小数点时,便停止接受,将120作为数据存入到相应的参数中。程序继续向下运行,当遇到第二个scanf时,函数又会到缓存中获取相应的数据,此时我们指定的类型为字符型,而'/n'恰巧为一个字符,于是scanf便将回车当做数据存入到flag中,程序继续运行走if-else语句,然后跳出循环。这样肯定不会出现第二次输入数据的状况。很多人会误以为回车是第一个scanf的结束标志,其实不然,scanf在接收整形数据时并不需要特定的结束符,当它检测到非数字非小数点时会自动停止接收数据。即使我们在输入完120时,不敲击回车,打一个空格的话,程序一样会继续往下执行,有的时候控制台不打印信息并不是说明程序没有继续运行,而是把要打印的信息存入了缓冲区。缓冲区的内容会不断的送往屏幕,缓冲区只有在下面三种情况下才会刷新:1.缓冲区满时 2.遇到换行符 3.需要输入时。scanf在接收数据输入时,遇到以下三种情况结束一个数据输入:1.遇到空格,回车,或tab键 2.遇到宽度结束 3.遇到非法输入(即前面所说的那一种)。 

如果我们把程序中的flag换成字符数组,即将第二个scanf的第一个参数换成%s的话程序就会继续往下执行。回车会作为字符串接受的开始,下一个回车作为结束。

      那上面的程序可以做如下修改,在每个scanf函数的下一行或者下一个scanf之前刷新缓冲区,可以采用getchar函数或者是fflush函数。当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符,也就是说getchar函数是以回车作为输入结束标志的,而此时缓存中刚好有'/n',结束getchar,同时stdin也清空了。fflush函数的参数是stdin,其作用就是刷新stdin,那'/n'也就没了。

原创粉丝点击