你怎么看待scanf()中%d的“吃空白”行为?

简介: 你怎么看待scanf()中%d的“吃空白”行为?

前言

上一期小编介绍了printf()scanf(),但是通过各位读者的反馈以及我近几天刷题中遇到的问题我觉得上期对scanf()的介绍还不够完善,需要对scanf()进行必要的补充说明。


一、scanf本质上是如何输入数据的?

上期介绍了输入缓冲区的概念,当我们通过输入数据后必须敲(回车),这样数据才会成功来到输入缓冲区(包括回车\n),接下来就是scanf()在缓冲区中按照指定格式提取所需数据。

二、scanf()提取%d数据的潜规则

1、%d前的“吃空白”行为

我们先看下面这个例子:

#include<stdio.h>
int main()
{
  int a = 0;
  int b = 0;
  scanf("%d%d",&a,&b);
  printf("a=%d\n",a);
  printf("b=%d\n",b);
  return 0;
}

像%d%d这种格式说明符挨着的,中间没有任何分隔符,我们应该怎么输入?

如果两个整形符紧挨着的话,默认在输入数据时中间可以以任何空白字符作为分隔标志(包括-空格、回车符-\n、水平制表符-\t)并且不限数量。因此在我们输入紧挨着的整形数据时常常使用这种方法,使我们输入更加灵活。

那么这其中的原理又是什么呢?

原理:像%d这种输入,默认会把缓冲区中数字之前的空格和回车全部丢弃掉

也就是说:当我们输入%d这类整形数据时,当我们键入数据后,scanf()在提取整形数据时会自动 “吃掉“%d前所有的空白字符(包括-空格、回车符-\n、水平制表符-\t)直到提取到%d类型的整形数据。例如上述代码,我按照下图输入,依旧可以正常给变量赋值,能正确输出:👇

笔者在输入时,在数字1前敲了多个空格和制表符以及1个回车,在数字2前也是如此:

2、%d后追加(空白字符)产生的“吃空白”行为

原理:当参数为"%d "的时候,此时没有处理到结尾,scanf()会认为你要继续进行输入。然而你输入了空格或者回车,scanf()认为他们是分隔符,于是“吃空白”吃掉了。换句话来说,scanf()依旧在等待你的输入, 只有当你输入不是空白的字符以后,scanf()才会用它与参数字符串里面的空格比较。

也就是说:如果%d后面加上空格,在%d的匹配工作结束后,%d后面的空白字符开始工作,空白字符表示会“吃掉”所有%d之后的空白字符,也就是会丢弃缓冲区中%d后的所有空格、水平制表符和换行符,因此无论我们输入多少次回车都会被%d后的空白字符“吃掉”。如果此时想要停下来,这时候就需要输入一个非空白字符就能使空格吃空白的工作停下来。

但是这样做的话,很可能会产生bug,就是第二个非空白字符会被留在缓冲区中,下次输入时就会被读取,比如下面这种情况:(输入错位,产生bug)

因此不建议大家在%d后面追加(空白字符)容易产生bug,这些会产生歧义的代码尽量不要再工程中出现

总结

以上就是我对上期scanf()的一些补充,由于笔者学识尚浅,加之篇幅有限,如有不当之处,欢迎诸位指点。


相关文章
|
算法 搜索推荐 程序员
C语言第十四练——请输入一个数的逆序数
C语言第十四练——请输入一个数的逆序数
126 0
|
7月前
小明同学学习了不同的进制之后,拿起了一些数字做起了游戏。小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中,二进制数也很常用。现在对于一个数字x,小明同学定义出了两个函数f(x)和g(x)
小明同学学习了不同的进制之后,拿起了一些数字做起了游戏。小明同学知道,在日常生活中我们最常用的是十进制数,而在计算机中,二进制数也很常用。现在对于一个数字x,小明同学定义出了两个函数f(x)和g(x)
124 1
|
6月前
|
C#
技术经验分享:C#之打印乘法表
技术经验分享:C#之打印乘法表
45 0
技术经验分享:C#之打印乘法表
|
7月前
|
Windows
函数解剖——深挖printf()与scanf()
函数解剖——深挖printf()与scanf()
函数解剖——深挖printf()与scanf()
|
6月前
【洛谷 P2669】[NOIP2015 普及组] 金币 题解(循环)
`NOIP2015`普及组题目,骑士按周期领金币:第一天1枚,随后$n$天每天$n$枚,然后$n+1$天每天$n+1$枚。给定天数$k$,求总金币数。输入$k$,输出金币总数。样例输入6,输出14;输入1000,输出29820。代码使用循环和变量控制周期,累计金币数。
135 0
|
存储
一招教你scanf什么时候要加&,什么时候不用加&
一招教你scanf什么时候要加&,什么时候不用加&
435 0
倒置字符串、猜名次、猜凶手、杨辉三角(下)
倒置字符串、猜名次、猜凶手、杨辉三角(下)
倒置字符串、猜名次、猜凶手、杨辉三角(上)
倒置字符串、猜名次、猜凶手、杨辉三角(上)
Leecode 面试题62. 圆圈中最后剩下的数字
Leecode 面试题62. 圆圈中最后剩下的数字
70 0
|
Java Python
leetcode每日一题.面试题62:圆圈中最后剩下的数字
leetcode每日一题.面试题62:圆圈中最后剩下的数字
68 0