C语言程序中scanf读取oper时出现命令跳过问题求助
医院费用计算C程序的输入异常问题分析
问题概述
编写的医院费用计算C程序在运行时,输入手术费变量oper环节出现输入被“跳过”的异常,此前还遇到char类型变量agree被错误识别为int的问题。以下是原程序代码、异常代码段及运行结果:
原程序代码
#include <stdio.h> int main() { int inpa, med, oper, day, total; char agree; printf(" Bach Mai Hospital"); printf("\n\nHello, please enter your fee and we will calculate\npayment based on your insurance\n"); printf("How many days have you been in the hospital "); scanf("%d", &day); printf("How much is your medicine fee "); scanf("%d", &med); printf("Have you undergone surgery (Yes or No)"); scanf("%s", &agree); switch(agree){ case 'Y': printf("Enter your surgery fee "); scanf(" %d", &oper); break; case 'N': oper = 0; break; }; printf("%s", agree); inpa = day * 15000; printf("Your total fee\n"); printf("Inpatient fee: %-10d x 15000 = %d\n", day, inpa); printf("Medicine fee: %-10d\n", med); printf("Surgery fee: %-10d\n", oper); total = inpa + med + oper; printf("\n\nYou pay: %d\n", total); return 0; }
异常代码段
printf("Enter your surgery fee "); scanf(" %d", &oper);
程序执行结果
Bach Mai Hospital Hello, please enter your fee and we will calculate payment based on your insurance How many days have you been in the hospital 8 How much is your medicine fee 90000000 Have you undergone surgery (Yes or No)Yes Enter your surgery fee 80000000 PS D:\Desktop\Cprogram>
问题原因分析
char变量使用%s格式符读取的内存越界问题agree是单个char类型变量,仅占1字节内存,但代码中用scanf("%s", &agree);读取输入。%s用于读取字符串,会把输入的所有字符(包括后续的'e'、's'以及自动添加的字符串结束符'\0')依次写入&agree指向的内存地址。- 这会直接覆盖
agree后面相邻的内存区域(恰好是oper变量的内存),导致oper的初始值被破坏。后续读取oper时,内存已被篡改,进而出现输入异常甚至程序崩溃。
printf格式符不匹配的未定义行为printf("%s", agree);中,%s要求传入字符串指针,但实际传入的是char类型的agree。程序会把agree的字符值当作内存地址去读取字符串,属于未定义行为,可能输出乱码或导致程序异常。
修复方案
修复后的代码
#include <stdio.h> int main() { int inpa, med, oper, day, total; char agree; printf(" Bach Mai Hospital"); printf("\n\nHello, please enter your fee and we will calculate\npayment based on your insurance\n"); printf("How many days have you been in the hospital "); scanf("%d", &day); printf("How much is your medicine fee "); scanf("%d", &med); // 用%c读取单个字符,前面加空格跳过输入缓冲区的换行符 printf("Have you undergone surgery (Yes or No)"); scanf(" %c", &agree); switch(agree){ case 'Y': case 'y': // 兼容小写输入 printf("Enter your surgery fee "); scanf("%d", &oper); break; case 'N': case 'n': // 兼容小写输入 oper = 0; break; default: printf("Invalid input, defaulting to no surgery.\n"); oper = 0; break; }; // 用%c打印单个字符 printf("Your choice: %c\n", agree); inpa = day * 15000; printf("Your total fee\n"); printf("Inpatient fee: %-10d x 15000 = %d\n", day, inpa); printf("Medicine fee: %-10d\n", med); printf("Surgery fee: %-10d\n", oper); total = inpa + med + oper; printf("\n\nYou pay: %d\n", total); return 0; }
关键修复点
- 将
scanf("%s", &agree);改为scanf(" %c", &agree);:%c专门用于读取单个字符,前面的空格会自动跳过输入缓冲区中残留的换行符,避免读取到之前输入留下的空白字符。 - 将
printf("%s", agree);改为printf("%c", agree);:用%c匹配char类型变量,避免未定义行为。 - 增加大小写兼容的判断和默认分支:处理用户输入小写字母或无效字符的情况,提升程序健壮性。
内容的提问来源于stack exchange,提问作者Phan Đào Minh Quân
相关产品推荐
相关产品推荐

