C语言读取两行整数输入的代码问题咨询
问题排查与解决方案
嗨,我来帮你看看这段代码的问题所在,以及怎么修复它!
你的代码为什么会出问题?
你当前的实现依赖于scanf("%d%c")来读取整数和后续字符,以此判断是否到达行尾,但这里有几个关键问题:
- 没检查
scanf的返回值:当scanf无法读取整数时(比如遇到换行、非数字字符),它会返回小于2的数值,但你的代码直接忽略了这个情况,会导致数组元素被赋予不确定的值,甚至陷入死循环。 - 跨平台换行符不兼容:在Windows系统中,回车键生成的是
\r\n而非\n,你的第一个循环会把\r读入temp,因为它不等于\n,循环会继续执行下一次scanf,但此时下一个字符是\n,无法被%d读取,直接导致逻辑混乱。 - 空白字符处理漏洞:如果一行末尾有多个空格再换行,读完最后一个整数后,下一次
scanf会尝试读取空格后的整数,显然失败,同样会引发错误。
更可靠的解决方案:先读整行再解析
推荐用fgets先读取整行内容,再用strtok或sscanf解析每行的整数,这种方式能避开所有换行符和读取失败的问题,逻辑也更清晰。
方案1:使用strtok分割字符串(简洁版)
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int arr[10000], brr[10000]; int i = 0, j = 0; char line[1024]; // 假设每行最多1024字符,可根据需求调整 char *token; // 读取并解析第一行 if (fgets(line, sizeof(line), stdin)) { // 用空格、换行、回车作为分隔符分割字符串 token = strtok(line, " \n\r"); while (token != NULL) { arr[i++] = atoi(token); // 把字符串转成整数 token = strtok(NULL, " \n\r"); // 获取下一个分割后的片段 } } // 读取并解析第二行 if (fgets(line, sizeof(line), stdin)) { token = strtok(line, " \n\r"); while (token != NULL) { brr[j++] = atoi(token); token = strtok(NULL, " \n\r"); } } // 输出第一行数组 for (int k = 0; k < i; k++) { printf("%d ", arr[k]); } printf("\n"); // 输出第二行数组 for (int l = 0; l < j; l++) { printf("%d ", brr[l]); } printf("\n"); return 0; }
方案2:使用sscanf逐次解析(更可控)
如果你不想用strtok,也可以用sscanf配合指针移动来解析:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int arr[10000], brr[10000]; int i = 0, j = 0; char line[1024]; char *ptr; // 处理第一行 if (fgets(line, sizeof(line), stdin) != NULL) { ptr = line; // 每次解析一个整数,直到解析失败 while (sscanf(ptr, "%d", &arr[i]) == 1) { i++; // 跳过当前数字后的所有非数字字符 while (*ptr != '\0' && (*ptr < '0' || *ptr > '9')) { ptr++; } // 跳过当前数字本身 while (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9')) { ptr++; } } } // 处理第二行 if (fgets(line, sizeof(line), stdin) != NULL) { ptr = line; while (sscanf(ptr, "%d", &brr[j]) == 1) { j++; while (*ptr != '\0' && (*ptr < '0' || *ptr > '9')) { ptr++; } while (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9')) { ptr++; } } } // 输出结果 for (int k = 0; k < i; k++) printf("%d ", arr[k]); printf("\n"); for (int l = 0; l < j; l++) printf("%d ", brr[l]); printf("\n"); return 0; }
为什么这个方案更好?
fgets会一次性读取整行内容,不管系统的换行符是\n还是\r\n,都能正确处理。- 先拿到整行再解析,能完全避免
scanf因混合读取整数和字符带来的各种边界问题。 - 逻辑更直观,后续维护或扩展(比如处理更多行)也更方便。
内容的提问来源于stack exchange,提问作者Piotr Wasilewicz




