scanf不靠谱?scanf又很重要?

    当我们在玩游戏时我们可以设置自己的游戏昵称,当我们在使用微信发信息给你的亲朋好友时我们都用到了一个至关重要的动作,那就是输入。
    在C语言中,scanf隶属于库函数,是使用程度较高的函数之一。当我们创建了变量,需要给函数输入值的时候就是使用scanf函数,而需要把变量的值输出到屏幕则是使用printf函数,基本使用C语言创建的代码程序都会使用scanf这个库函数,所以scnaf的意义重大,研究价值极高,那就让我们一起来研究学习并使用scanf吧。
在这里插入图片描述

scanf的使用方式

    

  • 1.scanf的语法是:scanf(格式字符串,地址)
        scanf的使用和printf的使用极其相似,两者的第一个参数都是格式字符串,也可以称呼为占位符,用于告诉编译器如何解读用户的输入,需要提取的数据是什么类型。scanf第二个参数就与printf有一定的出入了,scanf的第二个参数是一个地址,用户输入的内容就是存储到这个地址之中。

  • 2.什么是占位符,什么是地址呢?
        占位符的标志是“%”符号,只要是%开头的基本都是占位符。

    地址和我们日常生活中的地址含义相同,但有一定的出入,C语言中的地址是存储在内存中的地址,简单来说就是内存里面的某个地方,某个位置,地址的标志是“&”符号,使用scanf时的第二个参数必须要使用“&”,在变量的前面加上“&”符号就代表是该变量在内存中的地址。

    如果第二个参数不加“&”则会出现错误,但是你在输入的时候编译器不回报错,并且还能让你输入内容,但是输入内容敲回车之后,好了程序崩了,有兴趣的可以去试一试。
    所以scanf除占位符以外的其他参数,都应是地址而非函数。

  • 3.到底什么是“&”?
        “&”也是操作符是一种,叫做取地址操作符,&num———取出num变量在内存中的地址。

scanf的使用前提

    大家在使用csanf的时候,是不是都发现明明代码没有出现错误,但是编译器却报错,这是为什么呢?在这里插入图片描述
在这里插入图片描述
    相信大家都很疑惑,很憋屈,明明代码没有错误但是却给我报错,报错信息还看不懂是什么意思,破编译器哈哈哈,小编来给大家解释一下吧。

    得益于vs的严格性,在使用scanf时,编译器会觉得scanf这个函数不安全,会建议用户使用scanf_t进行替换,但实际上scanf_t和scanf的使用方式用一定的出入,并不完全一致,那这个时候还有什么解决办法吗?大家看小编的代码会发现,小编的代码也没有使用scanf_t但是却运行成功了,这是为什么呢。

    大家再看代码的报错信息,后面提示" To disable deprecation, use _CRT_SECURE_NO_WARNINGS."可以理解为如果让错误信息失效,请定义 _CRT_SECURE_NO_WARNINGS ,大家看小编的代码是不是第一行都有这个定义,那是不是每次敲代码我们都要手动把这么一大串英文输入进去啊,当然有别的办法,大家可以去看看小破站比特鹏哥的视频,里面有讲解(不是打广告哈)。

    scanf的头文件的stdio.h

scanf的运行

    代码运行到scanf的时候,会自动停下来,等待用户的输入,用户输入数据后,按回车键,scanf会处理用户输入的信息,将其存入变量。

    scanf在处理占位符时,会自动过滤空的字符,空格,制表符,换行符等。在这里插入图片描述
    用户输入时使用回车键,将输入分成几行也不影响编译器解读。
在这里插入图片描述
    当输入的数据不足以匹配相应的地址时,是不会进行数据读取的,编译器会一直让用户输入,按回车键也没有用,直到输入的数据符合相应的占位符,才能够停止输入,编译器进行读取存入地址。(一般出现在占位符相同的情况下)在这里插入图片描述
    按照占位符应该输入两个int数值,当小编只输入一个int数值然后按回车键,编译器还是一直处于输入状态,没办法进行读取。
    为什么会出现这样的情况呢,原因是:用户的输入先放入缓存,等到按下回车键后,编译器安装占位符进行解读,解读用户输入时,会从上一次解读遗留的第一个字符开始重新解读,直到读完缓存,或者遇到第一个不符合占位符的字符为止。在这里插入图片描述
    看只输出了数值,@qq.com没有被输入打印

int main()
{
	int x = 0;
	int y = 0;
	scanf("%d_%d",&x, &y);
	printf("%d %d\n",x,y);
	return 0;
}

    大家想一想这个代码如果输入“1 2”,打印结果是什么呢?可能大家都会觉得是1 2,那是如此吗?我们来ctrl+f5试一试
在这里插入图片描述
    哦豁结果不一样呢,这是为什么呢?
    我们仔细看代码scanf,两个%d之间是一个_,而我们输入的两个数值之间是空格,当第一个%d把1读取了,编译器就开始查找_,但是没有找到,%d也就没有办法正常读取2,所以里面放的还是我们初始化的数字。在这里插入图片描述
    看,初始化变成8,得到的结果就是8,符号不匹配,出现偏差。
    所以我们总结一下:两个占位符之间写什么格式,输入的时候就写什么格式,要严格匹配。
    如果我就不按照格式输入,当然也是有办法正常读取的,scanf提供了一个赋值忽略符*,只要把*放在如何占位符的百分号后面,该占位符就不会有返回值,解析后会被丢弃。在这里插入图片描述
    看起来还是挺好用的,不过小编不太常用,小编感觉这样写看的很难受哈哈。
    还有一个非常重要的,还有一个非常重要的,还有一个非常重要的,重要的事情说三遍,如果只需要输入一个值,那占位符后面不能加空格。在这里插入图片描述
    看当scanf占位符后面加了空格,需要输入两次才可以进行读取,这就是一个错误的操作。

scanf的返回值

在这里插入图片描述
    不知道大家有没有注意到过这个,scanf的返回值被忽略,有没有发现我们没有使用scanf的返回值只是警告,并没有影响我们代码的运行,那scnaf的返回值到底是什么呢?
    事实上,scanf的返回值是一个整数,表示编译器成功读取的变量个数,也可以理解为编译器成功把输入的值存入变量,成功存入多少个就返回多少。

  • 如果没有读取任何项,或者匹配失败,则返回0;
  • 如果在成功读取数据之前,发生了读取失败或者遇到读取到文件结尾,则返回常量EOF(-1) ;
        EOF(-1)-end of file 文件结束标志
    在这里插入图片描述
        返回3,表示成功读取3个数值并存入变量,完全读取。在这里插入图片描述
        返回2,表示成功读取2个数值并存入变量,不完全读取。在这里插入图片描述
        ^z的输入方法是ctrl+z,作用是停止读取。在这里插入图片描述
        返回值为-1,相当于读取到了文件结尾。
        所以通常那scanf的返回值来判断读取是否成功,如果返回值为EOF,则说明读取失败,返回值不为EOF,则说明读取成功。
        一般EOF作用在多种输入比较多,平时写代码不接受scanf的返回值,vs会报警告,但是可以忽略不计。
        大家知不知道printf的返回值是什么呢?哈哈小编知道哦,有兴趣的可以看小编下一篇文章。我们这里先按下不表。

scanf的占位符

    scanf的占位符和printf的占位符基本相同,但有极个别比较特殊。一个是%c,一个是%s。

  • 1
        所以占位符的可以自动忽略起首的空白字符,但唯独%c不会。%c不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。在这里插入图片描述
        结果并没有打印a出来,而是把空格打印了,有什么解决办法吗,那肯定是有的,我们只需要在%c前面加上一个空格即可。当然了是在scanf里面的%c前面加,别加到printf去了。在这里插入图片描述
        空格+%c,%c会自动跳过前面所有的空白字符,读取到真正有效的字符。
  • 2
        在scanf中,%s从当前第一个非空字符开始读取,直到遇到空白字符(空格,制表符,换行符等)停止读取。%s不会包含空白字符,这也就意味着scanf不适合读取含有空格的字符串,比如书名,歌曲名。这里我们需要用到数组进行验证。在这里插入图片描述
        hallo world只打印了hallo,这说明%s遇到空格之后罢工不干了。

scanf的不靠谱

    看到这里的读者大大们都是非常厉害的了哈哈哈是小编太唠叨了,快结束了快结束了。
    大家知不知道为什么vs要说scanf不安全吗?难道是编译器的问题?难道是两者不对付?
    哈哈小编来给大家讲解:scanf将字符串读入数字符数组时,不会检测字符串中是否超过了数组的长度,所以scanf在存储字符时可能会超过数组的边界,导致预想不到的结果出现。
在这里插入图片描述
    这就是scanf不靠谱的地方,放不下硬放,好好好恋爱脑被你scanf破解了哈哈哈哈,不考虑目标空间是否能够存放,人心不足蛇吞象,结果程序崩了。

    为了防止这种情况使用%s占位符时,应该指定输入字符串的最大宽度,即写成%[m]的形式,其中的[m]代表的是一个整数,表示读取字符串的最大长度,从左往右数,[m]后面的字符串会被自动丢弃。在这里插入图片描述
    大家在使用[m]的时候别把[]也给写进去了,知道小编为什么写的是4而不是5吗?哈哈哈因为字符串结尾还有\0字符串的结束标志存在啊!
    好了,小编肚子没有墨水了,等小编把墨水加满,再来找大家,大家不要跑散了,小编会想念大家的!!!

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值