C语言连续调用两次scanf函数的异常运行问题排查
问题原因分析
你提供的可复现问题的代码如下:
#include <stdio.h> #include <stdlib.h> void main () { char c; int choice, dummy; do { printf ("\n1. Print Hello\n2. Print Javatpoint\n3. Exit\n"); scanf ("%d", &choice); switch (choice) { case 1: printf ("Hello"); break; case 2: printf ("Javatpoint"); break; case 3: exit (0); break; default: printf ("please enter valid choice"); } printf ("\ndo you want to enter more?"); scanf ("%d", &dummy); scanf ("%c", &c); } while (c == 'y'); }
该现象是C语言标准输入缓冲区的字符残留 + 不同scanf格式符的匹配规则差异共同导致的,具体逻辑如下:
- 首先明确
scanf的两个基础规则:%d格式符只会匹配输入流中的数字字符,遇到非数字字符(比如输入结束按下回车产生的\n换行符)就会终止读取,且不会自动丢弃这个未匹配的非数字字符,会将其残留在标准输入缓冲区中。%c格式符不会跳过任何前置空白字符(换行、空格、制表符都属于空白字符),会直接读取输入缓冲区中的第一个字符,不管是什么类型。
- 输入整数时的执行流程:
你输入1之后按下回车,实际输入到缓冲区的内容是1\n。- 第一个
scanf("%d", &dummy)读取到1,匹配成功,将1存入dummy,剩下的\n留在缓冲区中。 - 第二个
scanf("%c", &c)直接读取到缓冲区里残留的\n,不需要等待你新输入内容,此时c的值为\n,不等于'y',循环条件不成立,程序直接终止。
- 第一个
- 输入
y时运行正常的原因:
当你输入y时,%d格式符无法匹配字母y,读取失败,y会被留在缓冲区中,接下来%c直接读取到这个y,刚好符合循环条件,因此看起来运行正常。
修复方案
最简单的修复方式是给%c前添加一个空格,让scanf自动跳过所有前导空白字符:
// 把原来的 scanf("%c", &c); 改成 scanf(" %c", &c);
也可以在两次scanf之间调用getchar()吞掉残留的换行符:
scanf("%d", &dummy); getchar(); // 吃掉缓冲区残留的\n scanf("%c", &c);
内容的提问来源于stack exchange,提问作者Ashikul Islam
相关产品推荐
相关产品推荐

