scanf 剖析

        Hello World ,Hello Classmates,小小代码一片天,虚拟机中造世界,让我们往编程世界里迈一小步,来简单地避开scanf的一些小坑。

         Scanf输入函数函数,相信接触过编程的人对这个函数都是很熟悉的,在这里我们不对它进行基础的介绍,我们来讲一下初学者在scanf上容易犯的一些经验小错误

1:scanf的格式

       对于scanf来说,scanf(“x”,&y),x内部的输入内容是必须完全按照自己所限定的格式输入,如scanf(“%d,%d”,&a)在输入时就必须要输入‘%d,%d’(引号内表示输入格式),千万不能丢掉逗号(这种错误本质上可以归于类型不匹配,我们会在下面说到),假如你的scanf是空格,那也最好不要忘了加上空格(虽然空格在scanf中比较特殊,在很多情况下可以忽略,这里我们浅尝辄止即可),而输入数组(字符串时),&符号不必使用,因为数组名则为该数组(字符串)的首元素地址,无须加取地址符号。

2.类型不匹配

       现在我们来说一下scanf的类型不匹配问题

       当scanf输入类型不匹配时,忽略后面所有参数(但会读取前面的有效参数),直接跳出这个scanf语句,而且不匹配的输入内容不会被存储在所需变量中,此时输出变量可能为随机值(因为未初始化)

如此图程序,若输入字符,则该程序无限循环

 

       在第一个scanf中输入一个非int型数后,跳出该scanf循环,卡到第一个字符的错误读取上,后面所有参数被忽略,scanf陷入无限循环,程序崩溃。---(可通过Ctrl+c 来终止程序)

 3:vs中scanf的使用

       这里补充一点,因为vs的高版本编译器比较流行,所以很多初学者都搞不明白为什么scanf函数在这些编译器(以vs2019版本举例)上无法运行,其实,vs2019会对scanf函数进行安全检查,由于scanf函数有安全风险(一种溢出风险),vs2019不允许使用它

3.1

在vs2019的库中有自己的scanf函数,函数名是scanf_s,或者你也可以选择跳过安全检查

3.2

在第一行输入‘#define _CRT_SECURE_NO_WARNINGS’,这行命令会让编译器跳过安全检查,从而使用scanf函数。(下面第二幅图就会报错)

 

3.3

#pragma warning(disable:4996)
//补如上一行即可,意思是禁报4996错误,该错误即为scanf的使用
#include<stdio.h>
int main()
{
	int a;
	scanf("%d", &a);
	return 0;
}

4.scanf_s对字符串的的使用

       这里说一下scanf_s对字符串的操作,scanf_s函数在字符串操作数并不与scanf相同,需要在操作字符串后申请一个访问空间,但申请空间不能小于你的输入空间,也不能大于你的字符串设定空间,如下图申请了11个字节的访问空间,超出字符串初始化空间,出现越界错误。对单个字符操作时虽然可以运行,但也建议如此操作,减少可规避的警告。

5.scanf对字符的读取

     注意一下当使用 %c 来进行scanf操作时,敲下的回车键(用来执行一个scanf的操作)会存储到缓冲区里面,被下一次的%c读取从而跳过下一次的scanf。

     这张图里,我在输入’a’之后敲下回车,第一个scanf执行完毕,同时讲一个’\n’留在了缓冲区,执行下一次scanf时,自动从缓冲区读取回车而结束这个scanf,输出结果可以看出(我先输出的b,再输出的a),b实际上就是个回车。

6.空白字符(scanf的吞白)

         这里谈一下空白字符(制表符  ,换页符,回车,空格)的问题

①       

        当对缓冲区输入时,scanf遇到空白字符就会停止读取,所以说,空白字符在缓冲区里又叫做scanf的分割符(回车还作为最后的执行操作符),就像‘\0’作为字符串的结束符,在下图几行代码中,我们就试着用不同空白字符来作为分割符,结果如图右方,输出结果始终正确符合格式

       总结的说,Scanf在输入缓冲区中遇到 换行符、制表符、空格 等空白字符视为分隔符,会继续向下读取一个非空字符,在中间的空白字符全部跳过,向下读取的非空字符如若缓冲区不存在则需要输入,该字符同样会被存储在缓冲区里并在某刻被读取

②   

        在缓冲区里输入的时候 如“i love you”在读取到第一个分割符后停止一阶段的输入,忽略后面的所有字符并将剩下字符放入缓冲区,在格式串中遇到下一个读取类型时,会继续从缓冲区中读取。

        刚刚讲的都是缓冲区里的问题,现在说一下格式串里的空格吞白问题。当格式串遇到空格时,会跳过所有缓冲区里开始遇到的空白字符,直到遇到一个非空字符,如若没有,则要求你再次输入一个非空字符才会停止这个格式串内空白的读取,在这里简单地讲三种情况

壹:当空格放在格式串前面时,就会吃掉上一次留下的空白字符,防止不理想的读取,我们常常用来解决 %c 时的‘\n’问题(如5中的问题)

跟5中图相比,不过在第二个scanf格式串最前面加了一个空格,这个空格会在执行时吃掉上一次留在缓冲区里的‘\n’,从而避免一些问题.

贰:当空格放在格式串中间时,总体来说,影响并不大,因为无论空格是否吃掉空白符,最后我们总需要输入第二个值,对结果影响不大,但最好遵循格式要求,中间打上空格。

叁:当空格放在格式串最后时,空白跳过空白符后并没有遇到下一个非空字符,要求我们进行一次输出后停止,如此,你会发现可以多进行一次输入。

      上图中,我们给了一个可以进行两次循环的for语句,我们就可以执行两次scanf,输入两次,然后打印两次。但在格式串最后放上空格时,我们会发现我们明明进行了3次输入,却只进行了两次打印,cout值明明也是2。

      我们来分析一下,进入for循环后我首先输入‘a’,敲回车,%c 结束,遇到格式串空格,现在缓冲区  里有‘a’,’\n’,空格要求我再次输入一个非空字符,于是我敲下’b’,然后按下回车,现在缓冲区里是’a’ , ’b’ , ‘\n’(一个\n被吃掉了),然后执行printf打印出scanf读取的’a’,之后进入第二次循环,因为缓冲区里有非空字符,所以scanf首先读取了’b’,然后的空白吃掉了’\n’之后又要求我们输入一个非空字符,我输入’c’,然后敲’\n’,printf打印了读取的’b’,却始终将’c’,留在了缓冲区,因此我们会多做一次输入并且会有一次无效输入

大家看了这么久,一定累了吧,给大家一个好玩的小东西!

 

    编程一途,路阻且长,虽然会有很多挫折,但创造的喜悦感会时刻伴随着我们,小伙伴们一定要坚持下来噢!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲸落之·海

哇塞,我将因此动力加倍!冲冲冲

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值