C语言实现正整数输入校验,不使用isdigit时输入字符触发无限循环
问题成因定位
- 校验逻辑错位:代码中
quantity是存储整数解析结果的int类型变量,并非原始输入的字符内容。写的quantity>='0' && quantity<='9'判断,本质是将整数值与字符'0'、'9'对应的ASCII值(48、57)做范围比较,和“输入内容是否为数字字符”的校验目标完全无关——哪怕输入100这类大于57的合法正整数,也会触发错误提示。 - 输入缓冲区残留触发死循环:当
scanf("%d")遇到非数字字符时,会立即停止匹配并返回失败结果,不会把这些非数字字符从输入缓冲区中移除,此时quantity的值不会被更新。后续循环再次调用scanf("%d")时,会持续读取缓冲区中残留的同一批非数字字符,反复匹配失败,形成无限循环。 - 逻辑无退出分支:循环内没有设置“校验通过即跳出”的判断,哪怕输入合法值,程序也会持续在循环内执行判断,不会终止。
可正常运行的实现方案
方案要求:不使用isdigit函数,覆盖负值、非整数两类异常场景,输入非法时持续提示重输。
核心实现思路:
- 改用整行读取的方式获取输入内容,从根源上避免
scanf遇到非法字符时缓冲区残留的问题 - 逐字符校验输入内容,直接通过ASCII范围判断是否为数字字符,不依赖
isdigit接口 - 分层校验:先判断是否全为数字字符、再判断转换后的数值是否为正整数,对应不同的错误提示
- 主动清空读取后残留的输入缓冲区内容,避免后续读取受历史残留影响
实现代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { int quantity = 0; char input_buf[256]; int input_valid = 0; while (!input_valid) { printf("Please enter term(s) number: "); // 读取整行输入 if (fgets(input_buf, sizeof(input_buf), stdin) == NULL) { clearerr(stdin); continue; } size_t str_len = strlen(input_buf); // 处理输入长度超出缓冲区的场景 if (str_len > 0 && input_buf[str_len - 1] != '\n') { int clear_ch; while ((clear_ch = getchar()) != '\n' && clear_ch != EOF); printf("Input content too long, please re-enter.\n"); continue; } // 移除输入末尾的换行符 if (str_len > 0 && input_buf[str_len - 1] == '\n') { input_buf[str_len - 1] = '\0'; str_len--; } // 空输入校验 if (str_len == 0) { printf("Please enter a number.\n"); continue; } // 逐字符校验是否全为数字,不使用isdigit int is_all_digit = 1; for (size_t i = 0; i < str_len; i++) { if (!(input_buf[i] >= '0' && input_buf[i] <= '9')) { is_all_digit = 0; break; } } if (!is_all_digit) { printf("Please enter a number.\n"); continue; } // 转换数值并校验正整数 quantity = atoi(input_buf); if (quantity <= 0) { printf("Please enter positive number.\n"); continue; } input_valid = 1; } printf("Received valid quantity: %d\n", quantity); return 0; }
内容的提问来源于stack exchange,提问作者user15465584
相关产品推荐
相关产品推荐

