scanf陷入无限循环且不返回-1/EOF的stdin重定向问题
解决scanf读取重定向输入时无限循环的问题
这是个很典型的scanf输入处理陷阱,我来帮你拆解原因和解决办法:
核心原因:scanf的返回值逻辑被忽略了
你的程序在正常stdin下运行正常,但重定向读取文件时卡死,大概率是循环条件没处理好scanf的返回值,或者输入文件末尾存在scanf无法解析的内容。
scanf的返回值有三种情况:
- 返回1:成功读取一个整数
- 返回0:遇到了无法解析成整数的字符(比如字母、符号、乱码)
- 返回EOF:到达输入流末尾
如果你的循环写的是while(scanf("%d", &num) != EOF),那当遇到非整数字符时,scanf返回0,不等于EOF,循环会一直执行——而且输入指针会停在那个非法字符上,每次循环都读同一个字符,永远返回0,直接陷入死循环。
解决方案一:正确处理scanf的返回值
修改你的循环逻辑,同时覆盖成功读取、读取失败和EOF三种情况:
#include <stdio.h> int main() { int num, ret; int count = 0; int nums[100]; // 根据实际需求调整数组大小 while ((ret = scanf("%d", &num)) != EOF) { if (ret == 1) { // 成功读取整数,存入数组 nums[count++] = num; } else { // 遇到非整数字符,跳过所有无效内容直到换行或EOF char c; while ((c = getchar()) != '\n' && c != EOF); // 如果你希望遇到非法字符就终止读取,可以在这里加break } } // 处理输出逻辑 if (count == 0) { printf("No integers were provided.\n"); } else { printf("{"); for (int i = 0; i < count; i++) { if (i > 0) printf(", "); printf("%d", nums[i]); } printf("}\n"); } return 0; }
解决方案二:用fgets+sscanf更可控
如果你觉得scanf的行为太“顽固”,可以换一种思路:先读取整行输入,再从行内解析整数。这种方式不会因为单个非法字符卡住整个输入流,容错性更强:
#include <stdio.h> #include <ctype.h> int main() { char line[1024]; int count = 0; int nums[100]; // 逐行读取输入 while (fgets(line, sizeof(line), stdin) != NULL) { char *ptr = line; int num; // 从当前行解析所有整数 while (sscanf(ptr, "%d", &num) == 1) { nums[count++] = num; // 移动指针跳过当前整数和后续空白字符 while (*ptr != '\0' && isdigit(*ptr)) ptr++; while (*ptr != '\0' && isspace(*ptr)) ptr++; } } // 输出逻辑和之前一致 if (count == 0) { printf("No integers were provided.\n"); } else { printf("{"); for (int i = 0; i < count; i++) { if (i > 0) printf(", "); printf("%d", nums[i]); } printf("}\n"); } return 0; }
额外排查步骤:检查输入文件的完整性
如果上面的代码还是有问题,那可能是你的input.txt文件本身有问题:
- 用文本编辑器打开文件,查看末尾是否有奇怪的非打印字符(比如Windows下的
^Z标记,在Linux系统下不会被识别为EOF) - 可以用命令行工具验证:比如Linux下运行
cat -A input.txt,查看文件的隐藏字符,确认末尾是正常的换行符或EOF。
内容的提问来源于stack exchange,提问作者user3194396
相关产品推荐
相关产品推荐

