如何避免scanf("%d")读取非数字字符时陷入死循环
解决scanf输入非数字导致死循环及非法输入检测问题
问题描述
使用scanf("%d", &n)时,若输入字符而非数字,程序会陷入死循环,需要实现非法输入的检测逻辑。原代码如下:
printf("first prime number till : "); scanf("%d", &n); if(n >= 1) { printf("\n%d prime number till n:\n", n); printf("2 "); for(count = 2; count <= n; i++) { for(c = 2; c < i; c++) { if(i%c == 0) break; } if(c == i) { printf("%d ", i); count++; } } } else { printf("Error, wrong input."); system("pause"); }
(注:原代码存在语法错误,比如for循环递增变量错误、未闭合大括号,已修正明显问题)
原因分析
scanf("%d")读取非数字输入时会匹配失败,此时输入缓冲区中的非法字符不会被清除,后续scanf会反复读取这些非法字符,持续匹配失败,进而引发死循环。scanf匹配失败时,n的值不会被修改,可能是未初始化的随机值,导致后续逻辑混乱。
解决方案
要解决问题,需做到两点:检查scanf返回值判断输入合法性,以及清空输入缓冲区中的非法字符。
1. 检查scanf返回值
scanf的返回值表示成功读取的变量个数:
- 成功读取数字时,返回值为1;
- 输入非法时,返回值为0;
- 遇到文件结束符时,返回值为
EOF。
2. 清空输入缓冲区
输入非法时,需将缓冲区剩余字符全部读取并丢弃,避免影响后续输入,可通过getchar()循环读取直到遇到换行符实现。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> // 用于system() int main() { int n, count = 2, i = 3, c; // 初始化变量,修复原代码未初始化问题 printf("first prime number till : "); // 循环直到输入合法 while(scanf("%d", &n) != 1) { // 清空输入缓冲区 while(getchar() != '\n'); printf("非法输入,请输入一个正整数:"); } if(n >= 1) { printf("\n前%d个小于等于n的素数:\n", n); if(n >= 1) printf("2 "); // 处理n=1的情况 for(count = 2; count <= n; i++) { for(c = 2; c < i; c++) { if(i % c == 0) break; } if(c == i) { printf("%d ", i); count++; } } } else { printf("Error, wrong input."); system("pause"); } return 0; }
关键说明
- 用
while(scanf("%d", &n) != 1)循环,直到用户输入合法整数。 - 内层
while(getchar() != '\n')逐个读取缓冲区字符,直到换行符,彻底清空非法输入。 - 修复了原代码中变量未初始化、
for循环递增变量错误的问题,避免额外逻辑错误。
内容的提问来源于stack exchange,提问作者A11__
相关产品推荐
相关产品推荐

