scanf提前终止问题:汽车受欢迎度统计程序输入异常
C语言程序scanf提前终止循环及统计异常问题解决
问题背景
需要统计孟买、加尔各答、德里、马德拉斯四座城市中Ambassador、Fiat、Dolphin、Maruti四款汽车的受欢迎度,输入为城市首字母+车型编码的组合,预设循环36次接收36组数据,但程序仅接收19组输入就提前终止,且输出结果存在异常(如马德拉斯的Maruti数值与Ambassador一致)。
问题原因分析
scanf读取换行符导致循环异常:
使用scanf("%c %hu", &city, &car)时,%c会读取输入缓冲区中的任意字符,包括每次输入后按下的换行符\n。每输入一组有效数据后,换行符会留在缓冲区,下一次循环中%c会直接读取这个换行符,此时scanf尝试读取车型编码%hu时,会遇到下一组输入的城市首字母(非数字),导致转换失败,循环计数被消耗但未完成有效数据录入。多次循环后,36次循环会被无效的换行符快速消耗,提前终止。输出笔误导致统计结果异常:
马德拉斯的Maruti输出语句中,错误使用了survey[4][1](对应Ambassador的统计值),正确应为survey[4][4]。非标准main函数定义:
C标准中main函数应返回int类型,而非void,这可能导致程序行为不可预测。
修复方案
- 修改
scanf格式串,在%c前添加空格,跳过所有空白字符(换行、空格、制表符),确保每次读取的都是有效城市首字母:scanf(" %c %hu", &city, &car); - 修正马德拉斯输出的笔误:
将survey[4][1]改为survey[4][4]。 - 将
void main()改为int main(),并在末尾添加return 0;,符合C标准。 - (可选)检查
scanf的返回值,确保每次成功读取2个数据,避免无效输入干扰统计:if (scanf(" %c %hu", &city, &car) != 2) { printf("输入无效,请重新输入\n"); i--; // 回退循环计数,重新接收该组输入 continue; }
修复后的完整代码
#include<stdio.h> int main(){ unsigned short car, i, survey[5][5] = {{0}}; // 简化初始化方式 char city; printf("Enter city initial and car code\n"); for (i = 0; i < 36; i++) { // 检查输入是否有效 if (scanf(" %c %hu", &city, &car) != 2) { printf("无效输入,请重新输入\n"); i--; // 清空输入缓冲区的无效内容 while (getchar() != '\n'); continue; } switch (city) { case 'b': survey[1][car]++; break; case 'c': survey[2][car]++; break; case 'd': survey[3][car]++; break; case 'm': // 显式处理马德拉斯的情况,避免default覆盖其他无效输入 survey[4][car]++; break; default: printf("无效城市首字母,请输入b/c/d/m\n"); i--; continue; } } printf("BOMBAY:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n", survey[1][1], survey[1][2], survey[1][3], survey[1][4]); printf("CALCUTTA:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n", survey[2][1], survey[2][2], survey[2][3], survey[2][4]); printf("DELHI:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n", survey[3][1], survey[3][2], survey[3][3], survey[3][4]); printf("MADRAS:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n", survey[4][1], survey[4][2], survey[4][3], survey[4][4]); // 修正笔误 return 0; }
修复效果说明
- 修改后的
scanf会自动跳过换行符,确保每次循环都接收一组有效输入,36次循环可完整接收36组数据。 - 修正输出笔误后,马德拉斯的Maruti统计值将正确显示。
- 添加输入有效性检查后,可避免无效输入导致的统计错误,提升程序健壮性。
内容的提问来源于stack exchange,提问作者Anuska Saha
相关产品推荐
相关产品推荐

