嵌套switch语句中%c读取char类型choice失效问题求助
嘿,我来帮你搞定这个问题——这可是C语言里用scanf读取字符时超级常见的一个坑!
问题根源
你遇到的问题完全是输入缓冲区残留的换行符搞的鬼:
当你用scanf("%d", &ch)输入数字后,按下回车键确认,这个回车键对应的换行符\n会被留在输入缓冲区里。接下来执行scanf("%c", &choice)时,%c不会跳过任何空白字符,它会直接读取缓冲区里的\n,而不是你手动输入的A/S/M/D/P,所以嵌套的switch直接进入了default分支,看起来像是%c失效了。
至于你说用%s看似能生效,这其实是个巧合+危险的未定义行为:scanf("%s")会自动跳过所有前导空白字符(包括换行),所以它能读取到你输入的字符,但你没有声明对应的字符串变量(比如char input[2];),直接用%s的话,scanf会把数据写入到内存中一个不确定的位置,轻则程序崩溃,重则破坏其他数据,绝对不能这么用!
有效解决方案
这里有两种标准且安全的方法可以解决这个问题:
方法一:在%c前添加空格
修改读取choice的scanf语句为:
scanf(" %c", &choice);
这里的空格是关键——它会告诉scanf自动跳过所有空白字符(换行、空格、制表符都算),直到遇到第一个非空白字符,这样就能准确读取你输入的操作符了。
方法二:用getchar()清除缓冲区的换行符
在第一个scanf读取完ch之后,添加一行代码:
scanf("%d",&ch); getchar(); // 吃掉输入缓冲区里残留的换行符
这样就能把之前留下的\n读取并丢弃,后面的scanf("%c", &choice)就能正常读取用户输入的字符了。
注意:网上有些教程会推荐用
fflush(stdin)清空缓冲区,但这是不符合C语言标准的未定义行为,只有部分编译器(比如MSVC)支持,跨平台使用很容易出问题,所以优先推荐前两种方法。
修改后的完整代码
下面是用方法一修改后的完整代码,我还补充了主菜单的default分支、除数不为0的判断,让程序更健壮:
#include<stdio.h> #include<conio.h> void main() { int a,b,c,ch; char choice; clrscr(); printf("1.Calculator\n2.Converter\n\n"); printf("Enter your choice : "); scanf("%d",&ch); switch(ch) { case 1: printf("1.Addition(A)\n2.Subtraction(S)\n3.Multiplication(M)\n4.Division(D)\n5.Module(P)\n\n"); printf("Enter your choice : "); // 添加空格跳过空白字符 scanf(" %c",&choice); switch(choice) { case 'A': printf("Provide the value of a : "); scanf("%d",&a); printf("Provide the value of b : "); scanf("%d",&b); printf("\nResult: %d", a + b); break; case 'S': printf("Provide the value of a : "); scanf("%d",&a); printf("Provide the value of b : "); scanf("%d",&b); printf("\nResult: %d", a - b); break; case 'M': printf("Provide the value of a : "); scanf("%d",&a); printf("Provide the value of b : "); scanf("%d",&b); printf("\nResult: %d", a * b); break; case 'D': printf("Provide the value of a : "); scanf("%d",&a); printf("Provide the value of b : "); scanf("%d",&b); // 新增除数不为0的判断 if(b != 0) printf("\nResult: %d", a / b); else printf("\nError: Division by zero!"); break; case 'P': printf("Provide the value of a : "); scanf("%d",&a); printf("Provide the value of b : "); scanf("%d",&b); // 新增取模除数不为0的判断 if(b != 0) printf("\nResult: %d", a % b); else printf("\nError: Modulo by zero!"); break; default: printf("Invalid Input"); } break; case 2: printf("Converter functionality is under development!"); break; default: printf("Invalid main menu choice!"); } getch(); }
内容的提问来源于stack exchange,提问作者Keval Vora

