Unix C开发中scanf忽略空格、跳过输入及文件写入循环异常问题排查
问题排查与修复方案
核心错误点梳理
- 野指针访问:
char* str未初始化就调用scanf写入内容,属于非法内存访问,会随机改写附近变量的值(比如题目数quest_num被改大,就会出现额外的循环条目),同时sizeof(str)取的是指针本身的长度(32位系统4字节、64位系统8字节),不是字符串实际长度,写入内容长度错误。 - 输入缓冲区残留换行符:输入题目数按下回车后,换行符残留在输入缓冲区,
scanf("%[^\n]")遇到换行直接返回空,导致第二题(甚至第一题)输入被跳过,且%[^\n]是完整格式符,后面多余的s属于错误写法。 - 写入逻辑错误:
write函数缺失长度参数、写入变量错误(应该写入题干buffer,错误写入了存储题目数的str)、temp数组长度只有2,存储超过1位的数字时会发生内存越界。 - 缺少参数校验:未判断程序启动时是否传入了文件名参数,
open调用容易崩溃。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> // 补充close、write的头文件 int main (int argc, char* argv[]) { int fd, quest_num, i; char buffer[100]; // 扩大题干缓冲区,避免长度不足 char line_buf[128]; // 用于拼接完整的写入行,减少write调用 // 校验入参 if (argc < 2) { printf("请传入要写入的文件名参数\n"); return 1; } // 加O_TRUNC避免旧文件内容干扰 fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd < 0) { perror("打开文件失败"); return 1; } printf("Insert number of questions\n"); // 直接读整数,避免字符串转换的冗余逻辑 scanf("%d", &quest_num); for (i = 1; i <= quest_num; i++) { printf("Insert question %d\n", i); // 格式符前加空格,跳过缓冲区残留的所有空白字符(包括换行),限制输入长度避免溢出 scanf(" %99[^\n]", buffer); // 拼接要写入的行,符合预期格式 snprintf(line_buf, sizeof(line_buf), "Question %d: %s\n", i, buffer); write(fd, line_buf, strlen(line_buf)); // 按预期补充选项内容(可根据实际需求调整) if (i == 1) { write(fd, "1. 5\n2. 2\n3. 0\n4. 1 ", strlen("1. 5\n2. 2\n3. 0\n4. 1 ")); } else if (i == 2) { write(fd, "1. X=y\n2. X= y\n3. X=1\n4. Y=1\n", strlen("1. X=y\n2. X= y\n3. X=1\n4. Y=1\n")); } } close(fd); return 0; }
验证说明
修复后可正常读取带空格的题干内容,不会出现输入被跳过、循环次数异常、写入内容错乱的问题,生成的文件完全符合预期格式。
内容的提问来源于stack exchange,提问作者Light Lamps
相关产品推荐
相关产品推荐

