如何重构C语言do-while循环以避免非法输入引发的无限循环
解决非法输入导致的程序无限循环问题
原代码在输入1、2、3、4之外的非法内容时会陷入无限循环,根本原因是**scanf("%d", &choice)读取失败时,非法输入会滞留在输入缓冲区中**,后续循环里scanf会反复读取这些无效内容,永远触发default分支,导致死循环。你尝试用count变量控制循环次数的方案只是临时规避,不能从根源解决问题。
原代码
do { printf("\n\t***CHOOSE HOW TO SORT***\n\n\tBy firstname: 1\n\tBy lastname: 2\n\tBy age: 3\n\tExit Program: 4\n\n"); scanf("%d", &choice); switch (choice) { case 1: printf("\t***SORTING BY FIRSTNAME...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_firstname); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n", P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 2: printf("\t***SORTING BY LASTNAME...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_lastname); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n", P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 3: printf("\t***SORTING BY AGE...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_age); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n",P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 4: printf("\t***EXITING PROGRAM***\n\n"); for (i = 0; i < n; i++) { free(P[i]); } exit(0); default: printf("\t***INVALID OPTION***\n\n"); break; } } while (1);
你的尝试代码片段
... default: printf("\t***INVALID OPTION***\n\n"); count = count + 2; break; } }while(count < 2);
正确重构方案
核心要做两件事:
- 检查
scanf的返回值:scanf("%d", &choice)成功读取整数时返回1,读取失败(输入非数字)时返回0,遇到EOF返回-1。 - 清空输入缓冲区:读取失败时,把缓冲区里的非法内容全部清空,避免下次循环重复读取。
修改后的完整代码:
do { printf("\n\t***CHOOSE HOW TO SORT***\n\n\tBy firstname: 1\n\tBy lastname: 2\n\tBy age: 3\n\tExit Program: 4\n\n"); // 检查scanf返回值,判断是否成功读取整数 int scan_result = scanf("%d", &choice); // 处理读取失败的情况:清空输入缓冲区 if (scan_result != 1) { printf("\t***INVALID OPTION***\n\n"); // 清空缓冲区直到换行符,避免残留内容影响下次读取 while ((getchar()) != '\n'); continue; // 跳过后续switch,直接进入下一轮循环 } switch (choice) { case 1: printf("\t***SORTING BY FIRSTNAME...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_firstname); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n", P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 2: printf("\t***SORTING BY LASTNAME...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_lastname); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n", P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 3: printf("\t***SORTING BY AGE...***\n\n"); qsort(P, n, sizeof *P, Person_cmp_age); printf("\t***DONE***\n\n"); for (i = 0; i < n; i++) { printf("Firstname: %s\t| Lastname: %s\t| Age: %d\n",P[i]->firstname, P[i]->lastname, P[i]->age); } break; case 4: printf("\t***EXITING PROGRAM***\n\n"); for (i = 0; i < n; i++) { free(P[i]); } exit(0); default: printf("\t***INVALID OPTION***\n\n"); break; } } while (1);
关键说明
- 通过
scan_result = scanf("%d", &choice)获取读取状态,判断是否成功读取整数。 - 读取失败时,用
while ((getchar()) != '\n');清空输入缓冲区里的所有字符直到换行符,确保下一轮循环的scanf能正常读取新的输入。 - 用
continue直接进入下一轮循环,避免执行后续的switch逻辑。
内容的提问来源于stack exchange,提问作者jian
相关产品推荐
相关产品推荐

