C语言strtok解析CSV时如何排除字符串末尾NULL终止符与多余%字符
问题原因
你遇到的异常来自三个代码逻辑缺陷:
- 文件循环判断逻辑错误:
while(feof(file) != true)是C语言文件操作的常见错误,feof()仅在读取操作已经触发文件末尾标志后才会返回真值,会导致循环多执行一次,读取到无效残留内容。 - 字符串分割符不全:最后一次调用
strtok仅用逗号作为分割符,fgets读取到的行尾换行符\n、Windows格式换行\r、文件末尾残留的不可见控制字符都会被划入最后一个字段,你看到的末尾%本质是终端检测到输出行没有正常换行时追加的提示符,不是文件本身存储的字符。 - 缺少有效性校验:没有判断
fopen、strtok的返回值,遇到异常行、空行时会直接触发内存错误。
修改后代码
#include <stdio.h> #include <string.h> #include <stdbool.h> #include <ctype.h> // 按实际业务需求调整这两个宏的长度定义 #define MAX_LINE 1024 #define MAX_COLUMN 256 int main() { FILE *file; char row[MAX_LINE]; char method[MAX_COLUMN]; char url[MAX_COLUMN]; char query[MAX_COLUMN]; char servers[MAX_COLUMN]; char *tkn; file = fopen("whitelist.csv", "r"); if (!file) { perror("打开文件失败"); return 1; } // 直接通过fgets返回值判断是否读到文件末尾,替代错误的feof前置判断 while(fgets(row, MAX_LINE, file) != NULL) { // 跳过空行 if (row[0] == '\n') continue; // 解析前三个字段 tkn = strtok(row, ","); if (!tkn) continue; strcpy(method, tkn); tkn = strtok(NULL, ","); if (!tkn) continue; strcpy(url, tkn); tkn = strtok(NULL, ","); if (!tkn) continue; strcpy(query, tkn); // 最后一个字段增加换行、回车符作为分割符,提前过滤行尾控制字符 tkn = strtok(NULL, ",\n\r"); if (!tkn) continue; // 二次清理:遍历最后一个数值字段,遇到非数字的异常字符直接截断,彻底过滤空字节、不可见残留 int i = 0; while (tkn[i] != '\0') { if (!isdigit((unsigned char)tkn[i])) { tkn[i] = '\0'; break; } i++; } strcpy(servers, tkn); // 此处编写后续业务逻辑,四个字段已完成异常字符清理 printf("Method: %s\n", method); printf("URL: %s\n", url); printf("Query: %s\n", query); printf("Servers: %s\n", servers); } fclose(file); return 0; }
关键改动说明
- 移除错误的
feof前置判断,直接通过fgets返回值判断文件读取状态,避免无效循环读取垃圾内容 - 最后一次
strtok的分割符新增\n和\r,自动剔除不同系统下的行尾换行符 - 对最后一个数值型字段增加字符校验,遇到非数字字符直接截断,彻底过滤文件末尾残留的空字节、不可见控制字符
- 增加文件打开、字段解析的空指针判断,兼容空行、格式异常行,避免程序崩溃
- 补充文件关闭逻辑,避免文件句柄泄漏
内容的提问来源于stack exchange,提问作者connor.rawls
相关产品推荐
相关产品推荐

