aaaaaa第三篇赶上!
判断scanf输入的是否为整型
# 需求
很多时候我们需要用scanf输入数据,但人为输入的数据可能不符合指定的类型,自然地我们想到了判断输入类型是否正确。
# 实现
那该怎么实现呢?这里我们可以利用scanf的返回值:
scanf返回值:返回成功读入的数据项数
既然这样,那只需要加一个循环,每次检测录入的数据项数是否为全部数据的个数,不是则说明有内容没有录取到(即出现非法字符),此时可以输出提示要求重新输入。
自然地我们写出以下代码:
//以检查输入的是否一个整型为例(VS2019)
int n;
while (scanf_s("%d", &n) == 0)
{
printf("输入了非法字符!\n");
}
!!但是,问题出现了
输入非法字符后,结果是这样的:
可以看到,while变成死循环了,并没有给我们再次输入的机会QAQ,到底发生了甚么?!
# 分析
这时候就需要看看scanf的运作原理了
当要求的类型与输入的类型不符合时,scanf会选择直接跳过不接收该输入,注意只是不接收,也就是说缓存区中输入的东西既没被接收也没有被清除,就这么留在那里。
那问题就来了,当下一次用户要输入时,scanf看到缓存区有东西,就直接去读取了,结果又读到与指定类型不符合的,又跳过了,由此触发了无限循环(傻fufu的)
# 解决方案
完成了分析,接下来就好处理了,只需要把缓存区的东西清掉不要让scanf傻傻的又去读取就好啦!
相关代码段:while (getchar() != '\n');
这一句可以简单地解决清楚缓存区的功能
原理是每次都向缓存区读取数据,如果没到尾就继续读取,直到把所有东西读完,再跳出(注意while执行的是空语句)
到这里,问题就都解决了 – 需求 OK,bug KO
# 完整代码
//以检查输入的是否一个整型为例(VS2019)
int n;
while (scanf_s("%d", &n) == 0)
{
printf("输入了非法字符,请重新输入:");
while (getchar() != '\n');
}
*注:这里的getchar已经不用自己输入了,原因和scanf的死循环一样,缓冲区已经有东西了,getchar会直接读取而不会让我们输入
运行结果:
可以看到问题已经完美解决了~
2021-3-29 方案完善
在后续的使用中,出现了一些问题,如下:
可以看到:
当输入的数据以数字开头,而带有字符时
该解决方案会截取到数字部分,视为合法数据,而后面的字符则留在了缓冲区
这将直接导致下一次的输入被跳过直接取出缓冲区的字符,显然不是我们希望的,所以做了如下改进:
int n;
while (scanf_s("%d", &n) == 0 || getchar() != '\n')
{
printf("输入了非法字符,请重新输入:");
while (getchar() != '\n'); // 清除缓存区
}
解释:
- 如果为 0 则说明第一个位置出现了字符
- 不为 0 说明前面是整型,此时再取出后面一个字符
- 如果为 \n 则数据没问题,要是还有东西则又是非法字符
这样就可以保证输入的全部为所需的整型
效果如下:
好的,完结收工~
如果还有后续问题欢迎指正!
第3篇完成,打卡!!
冰冻三尺非一日之寒(寒冰小澈)