关于对scanf函数的基础了解

本文详细探讨scanf函数在C++中的使用,包括在不同编译器中的兼容性问题,为何在VS中可能报错,以及scanf的占位符、返回值和安全性。还介绍了如何在VS中设置安全选项并处理scanf的特殊行为,如结束标志和空白字符处理。
摘要由CSDN通过智能技术生成

前言:scanf是一个输入函数,但这里面包含的基础概念,知识点却很重要,只有对这块的知识点相对熟悉,未来在遇到相关的代码才会显得比较从容,万丈高楼平地起。

一.关于不同编译器上scanf可能报错的问题。

由于不同编译器的厂商对scanf的要求不同,在某些编译器上使用scanf可能会报错,有些可能不会。例如:devc++上是可以直接使用scanf函数进行输入要求的,但是在vs上却会报错,提示scanf返回值被忽略,所以在vs上想输入时,需使用scanf_s。或者如果在vs就想使用scanf进行输入,且不让scanf报错,则需要在在代码的第一行加上#define _CRT_SECURE_NO_WARNINGS 1

这里需要注意的是define后面有一个空格,以及后面的1前面也有一个空格。但是这样会不会太麻烦,每次打开一个新的.c源文件都需要在第一行加上那句话。那有没有一劳永逸的方法,在我每次创建.c源文件时,代码第一行都加上这句话呢,答案是有的。

因为在vs编译器上,每次创建一个源文件时,这个文件都是拷贝自一份叫newc++file.cpp的文件,这个文件是在下载vs时,自带的文件。那么好,我们需要找到这个文件,在我的电脑搜索这个文件,由于搜索时间较长,我在电脑上安装了一个叫everything的小工具,在上面查找文件异常快捷:

,注意看这里有两个newc++file.cpp的文件,这是因为在我的电脑上安装了vs2019 vs2022,我们只需要找到,我们想要加上那句代码的那个版本的编译器就行。

然后右击鼠标,选择打开路径,以记事本打开,然后将#define _CRT_SECURE_NO_WARNINGS 1这段代码复制上去

然后ctrl+s保存。但是这里可能出现下面这个问题:

,这是电脑的笔记本权限不够,但是我们可以在桌面上打开操作,这样就可以了,因为桌面的权限比较高,如下操作:

右击鼠标,将newc++文件复制一份到桌面,然后在桌面右击这个文件以记事本打开,然后再复制那段代码到记事本。ctrl+s保存。但是我们还要进行最后一步,那就是将桌面的文件最后再复制一份替换掉原来的文件,如下:

,这样就可以了。这里千千万万要注意不要把这个文件弄丢了,拖出去记得拖回来,不然会很麻烦,下次创建源文件就没有cpp类了。

现在,我们创建所有.c类或.cpp类源文件,上面都有这段代码了。

二.关于解释为什么在vs里面scanf不安全

如下代码:

,仔细看这段代码,我定义了一个长度为6的数组,当我在屏幕上输入abcdef这6个字符时,程序崩了,有人可能会好奇,这不就是6个字符嘛,并没有越界访问啊,其实在scanf函数当中,"\0"作为结束的标志会被scanf自动读取,这也就是为什么输入6个字符依旧越界访问。

还有另外一个问题,为什么这里arr没有取地址,因为数组名本来就是地址,不需要再继续取地址了。

接下来说说,为什么scanf不安全?这是因为虽然越界了,但scanf却依旧将这几个字符强塞给地址,并且打印出来,这在工程里面会造成程序的崩溃。

三.scanf的占位操作符

我们依旧以一段代码为例,介绍scanf函数如何读取用户输入的数据:

,注意看这段代码,定义了i,j,x,y,当我们scanf输入值的时候,加了空格,和回车,不影响scanf正常读取,因为scanf在读取时会自动过滤空白符,换行符等。另外,当打印float类型的数时,小数点后默认保存6位。

我们在看一个代码举例:

,仔细观察这段代码,以及输出结果,我们不能得知,在scanf的占位符当中,scanf会自动过滤起首的空白字符,上面这段代码,过滤起首的空白字符,然后读取-13,,因为需要打印%d(整数)遇到.小数点,停止读取。第二个scanf从上一次停止的地方开始读取,这里的e12的意思是乘以12次方,由于小数在内存中无法被精确保存,使用得到的值略有误差。

其实上面这段代码还可以这样写:

,这样得到的结果也是一样的。

如果,第一个输入为符号,那么程序将介绍,如下:

,这是因为scanf第一个读取的是字符,自动结束程序,所以默认什么都没有读取,所以打印的便是00.000000(小数点后默认保存6位小数)。

四.scanf的返回值

有时候我们再写代码时,编译器会报警告,scanf返回值被忽略,那么scanf的返回值是什么呢?

scanf的返回值是一个整数,表示读取到变量的个数。

如果未读取到任何项,或者匹配失败,则返回0。例如下面这段代码:

,因为我们scanf读取的是整数%d,但是我们输入#这个符号,匹配失败,所以返回值为0。

在未读取任何数据之前,发生读取错误,或者遇到了文件的末尾,则返回EOF(值为-1)。

例如下面这段代码:,在这段代码中,我们连续用三次ctrl+z结束进程,让scanf认为读取到了文件末尾,所以返回值为-1,即为EOF。

我们可以在代码里面加入EOF;  右击EOF;转达定义,便可以查看:

介绍完上面的定义,话不多说,我们用下面这段代码,来一起继续具体探讨一下scanf函数的返回值:

,在这里我们定义了一个整形ret用来接收scanf的返回值,因为scanf读取到三个变量,所以返回值为3,所以打印的ret的值也为3。

如果只读取到两个数字,那返回值就是2。

如下:

,因为只输入了两个值,所以ret返回值为2,因为c未输入任何数值,所以c的值为0。这里的ctrl+z是强行结束进程,一次不行,按三次提前结束进程。

刚刚属于一组输入,那能不能多组输入呢,并且计算他们的和,答案也是有的。

如下:

,那如果我们想要让程序结束怎么办,因为是在循环里的,所以,我们得想办法让循环停止下来,依旧看下面的代码:

,循环的条件是scanf读取到两个变量,返回值为2,当我们输入#时,与输入%d整数不匹配,所以返回值为0,循环结束。其实也可以用ctrl+z。也可以将==2改成!=EOF,这些其实本质上是一样的。

下面我们来介绍%c,%s。

首先所有占位符都会忽略起首的空格,但是,%c不会。

,比如说这段代码,输入三个空格+abc,但是打印却是一个空格+xxxxx,这是因为%c不会略过起首的空白字符,%c读取了空格,所以打印的是空格+xxxxx,而非abc。如果想要打印输入的值,可以在scanf的%c前加空格,如下:

,这时候%c读取一个字符,那就是a,打印如上。

接下来介绍最后一个%s。

这个不能等同于其他占位符,它的规则是:从当前第一个非空白字符开始读起,直到遇到空白字符(空白,制表符等)为止。如下:

,如果想全部读取,则需要多个%s连用。

如下:

最后,赋值忽略符。

大概归纳为一句话,scanf与printf里占位符格式需要一样,比如scanf%d %d.那么对应的printf格式中间也应该为空格。

关于scanf的基本概念就探讨到这。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值