目录
(1)输入5 6此时scanf能正确读入的数据为两个,返回值为2
scanf正确读入概念补充
(2)如果输入5 t此时能正确读入的数据为1个,返回值为1。
(3)如果输入1 2.5
(4)输入t 5,此时能正确读入的数据为0个,返回值为0。
scanf是我们最开始接触的库函数,最开始接触的函数之一,当时就是记住1.在键盘上输入格式和要和代码那scanf中格式字符串(这个就是代码里scanf中双引号内的部分)的格式一样,2.存到变量,数组里要取地址,但是随着使用场景增多,我逐渐对scanf的使用产生了些疑惑,事情的开端是这样的,我们都知道scanf的返回值是正确读取到的数值,还可以利用这个返回值来结束循环,就像下面这样。
while (~scanf("%d",&b))
{
printf("%d", a);
break;
}
当scanf读取文件末尾,会返回-1,这个时候~就可以把(-1)的二进制取反为0,此时条件为假,跳出循环,对于应对多组输入的时候十分有用。但是就在我自己测试这个代码的时候,我却不知道如何输入数据才能让它返回-1,这个时候我就不免反思scanf的返回值规则。
scanf("%d %d", &a, &b)
当我们输入完两个数字,此时敲击换行(enter)表示结束输入,数据进入缓冲区。可如果我们把换行放在输入两个数据前,比如输入第一个数据后换行,此时数据也会进入缓冲区,但是这个时候scanf读取的时候发现不够,你还得给我数据,此时就不会结束输入。如图
scanf还在苦苦等待中。
这个时候有没有同学想问scanf对于空格如何处理?
如上图,我就打一堆空格和换行夹着数据,我看scanf怎么处理,我想此时的scanf面对这个是有点错愕的,说这个前首先要补充的是:此时用%d类型转换时scanf会跳过所有的空白字符(换行,制表符,空格来读数据),没关系,我全都跳过,你该提供的没给够还是得给scanf,scanf跳过空白读取时知道你输入的不够,然后就会继续让你输入,这就是为什么换行在输入完两个数据前没有起到结束输入的作用,而空格却不会干扰scanf对数据处理的原因!
当我们都输入完后,此时我们输入的数据中夹杂的空格都不在缓冲区,应该被丢弃了,我们可以用下面来测试。在2和3之间有两个换行,3结尾还有个换行,如果2和3之间的换行被保留了,那我scanf就不会要求我们读入数据,但实际上我们还要输入个字符,这说明只有3结尾的换行被保留了。
还有就是我们说scanf在要读取整形数据的时候会跳过空白字符,但是如果我们格式里要空格而我们却没有空格,此时scanf会把这两个数字当成一个数据,而要你继续输入一个才够两个数据。
总而言之,只要保证输入的格式字符串一致就能避免上诉问题,不要挑战规则!
scanf("%d %d %d", &a, &b,&e)
正确读入的数据判断我认为看两方面,1.我们输入进缓冲区中正确数据的个数 2.就是看scanf中%d的个数。注:不看要赋值的变量个数(大家可以试试,是不影响的)
为什么是两方面呢?我们可以这样想,scanf中%d的个数是他要的数据个数,但是如果scanf能正确读入就一个,如下面的例子(2),那这个时候返回值肯定看你有多少个数据是有用的嘛,如果你给的数据超过了scanf中%d的个数,这个时候scanf对于多了的数据就不会再读了,所以能正确读入数据分两方面,一方面是我要读多少个,还有一方面就是我有多少个数据是对的
原因:当我们输入完两个数字(或者一个为字符,一个为数字),此时敲击换行(enter)表示结束输入,数据进入缓冲区,此时用%d类型转换时scanf会跳过所有的空白字符(换行,制表符,空格),scanf会判断数据类型,字符t不符合就不会scanf拿去赋值,而是留在缓冲区,此时如果紧接连写多个scanf就会因为这个字符t不合要求多个返回值为零。
如图
同理上一个输入的换行也会留下来,如果你的三个scanf的格式字符串用的为%c,那scanf都会把这个换行记录下来,这个时候你发现我们只要输入一个字符就够了。
这里还要提一点,关于输入数据格式和scanf代码中格式(也就是格式字符串)的问题,其实也就是输入的时候多个换行,空格的事,这个对于%d来说是无需理会的,谁叫%d可以跳过呢,就是这么任性,这个时候想必有读者想问了,标点符号呢?
首先第一%d不会跳过这个标点符号,(标点符号不是空白字符),然后就是如果出现输入格式不符合的情况,要逗号没写逗号,此时scanf读到此处会停止,不符合数据就留在缓冲区。
不要逗号,给了逗号,就和之前的情况要数字却给了字符,scanf用%d读取失败,将逗号字符和其之后的数据都留在了缓冲区。
我写着写着发现有个点一直被我忽略,就是我输入时我的输入法一直都是用中文,而我scanf格式字符串里面却是英文逗号的,居然不会出错,当然如果scanf格式字符串里面是中文,外面输入用英文会读取失败。我可以肯定地说同志们到探究这一步我们已经在沟里了,不用深究,我们在输入的时候眼尖点,可以看到编译器会更新一下我们的输入,我怀疑在这个地方对我们的输入做了处理,这就是为什么上面格式字符串中为英文逗号,而我们输入为中文逗号不会出错,反过来可能编译器就未对输入做处理。因为我们写代码一般都是英文嘛,可能设计编译器的人就默认代码里的都为英文,就帮我们把输入的都转为英文的格式,他可能没想到会有人反过来。
此时scanf用%d读到非整数就停止,但不是读到2.5就不读了,而是在读取2.5的时候读到小数位就放弃读取,我当时看了是有点吃惊的,还有这种操作!所以它就把1和2拿走了,在缓冲区留下.和5,当然此时返回值还是为2。
此时scanf需要一个数字而你却给了个字符,此时返回值为零。
那什么时候返回负一呢?vs中输入^z+换行连续三次才可以时其返回值为-1,此处貌似和文件尾定义和vs2019本身的bug有关,我就留之后解答吧,感觉一般我们也不会连续输入^z加换行。
但对于%c,%s来说这个输入格式则必须要和格式字符串一模一样,因为对于%c来说空格也是字符,输入多了个空格可能scanf就把空格字符拿去赋值了,如果在格式字符串中多输入了个空格意义也不一样
此时格式字符串中没带空格,如果你输入2前多输入了个空格,空格就会被拿去赋值,此时打印出来变量c的内容就是个空格。
但是如果我们在格式字符串加个空格 ,如下图,不管我们在2前输入多少个空格都会被跳过,这就是在格式字符串加了空格的作用!
而空格对于用%s的scanf来说则是直接作为读取结束符号,除非用"%[^\n]"。
这篇时间间隔有点久,如果还有错漏请指正,谢谢大家!