C语言读取固定16字符行WAIT/NOWAIT指令文件的实现问题
题目要求的语义澄清
题目中提到的每行长度为16字符(包含行尾换行符),是对文件存储结构的硬性约定:
- 每一行从行首到行尾换行符
\n的总字节数固定为16,不是要求代码端主动补全空格适配短行。 - 合法行的组成逻辑是:
WAIT/NOWAIT 指令内容 + 填充空格 + 换行符,凑满16字节总长度,确保程序可以按固定偏移量(0、16、32...)快速定位每一行的起始位置。 - 你遇到的测试文件未补全空格的情况,属于测试用例的非标准场景,代码需要做兼容,不能因为行尾提前出现换行就解析错位。
现有代码的核心问题
你目前的逻辑之所以跨行解析,根源是:
- 硬编码每次固定读取16字节内容,完全没有识别内容里的换行符边界。当测试文件的行实际长度小于16字节(没有补空格)时,read系统调用会一次性把当前行+下一行的开头内容一起读到缓冲区里,直接喂给sscanf就会出现内容错位。
- 没有对解析过程做边界保护,裸用
%s格式的sscanf存在缓冲区溢出风险。 - 遗漏了文件描述符的关闭操作,存在资源泄漏。
可直接运行的调整方案
按照定长块读取+换行符边界截断的逻辑修改,既可以兼容标准的16字节定长行文件,也可以正确解析未补全空格的短行测试文件,修改要点:
- 每次固定从文件读取16字节(匹配题目约定的行长)
- 读取完成后立刻定位缓冲区里的第一个换行符,将其作为当前行的结束位置,替换为字符串结束符,从根源上避免把下一行的内容带入解析
- 给sscanf增加长度限制,防止缓冲区溢出
- 补充文件描述符的关闭操作
修改后的核心循环代码:
#define EXPECTED_LINE_LEN 16 // 严格匹配题目约定的含换行的行长 char read_buf[EXPECTED_LINE_LEN + 1]; // 多预留1字节位置放字符串结束符 while (1) { ssize_t read_count = read(fd, read_buf, EXPECTED_LINE_LEN); // 读到文件末尾或者发生读错误时退出循环 if (read_count <= 0) break; read_buf[read_count] = '\0'; // 无论实际读了多少字节,先补字符串结束符 // 定位当前读块内的第一个换行符,作为真实行边界 char *line_break = strchr(read_buf, '\n'); if (line_break) { *line_break = '\0'; // 将换行符替换为结束符,截断行尾的填充/后续行内容 } char type[16], cmd[16]; // 带长度限制的sscanf,避免越界 int parse_status = sscanf(read_buf, "%15s %15s", type, cmd); if (parse_status != 2) { fprintf(stderr, "行格式非法: %s\n", read_buf); close(fd); exit(4); } printf("type=%s; command=%s;\n", type, cmd); } close(fd);
兼容效果说明
- 当遇到严格符合要求的16字节定长行(补了空格的版本):换行符位于第16字节位置,截断后不影响sscanf正常识别WAIT/NOWAIT和对应的命令内容
- 当遇到未补全空格的短行测试文件:换行符提前出现在读块的靠前位置,截断后只会解析当前行的内容,不会跨行读取下一行的数据
- 自动跳过行中间的多余空格,不会因为填充字符干扰解析结果
内容的提问来源于stack exchange,提问作者Gius
相关产品推荐
相关产品推荐

