strtok返回长度为1的零值字符串?CSV转double矩阵数值显示0问题
首先咱们先揪出导致printf输出0的核心原因:你用了%d格式符来输出double类型的值!%d是用来打印整数的,把double传给它会导致类型不匹配,输出结果属于未定义行为(这里刚好显示0,但本质是完全错误的)。这是最直接的问题,先解决这个,你的转换结果就能正常显示了。
接下来咱们一步步梳理所有潜在问题:
1. 格式符错误(最紧急修正项)
你代码里的这行:
printf(", converted %d, assigned %d\n", d, csv[rows][cols]);
d和csv[rows][cols]都是double类型,必须用%f(或%lf,在printf里两者等价)来打印,改成:
printf(", converted %.2f, assigned %.2f\n", d, csv[rows][cols]);
这样就能正确显示转换后的浮点数值了。
2. 二维数组声明语法错误
你写的double csv [MAX_SIZE, MAX_SIZE];是错误的C语法,二维数组的声明应该用嵌套方括号:
double csv[MAX_SIZE][MAX_SIZE];
编译器大概率会报错这个点,必须先修正。
3. Strtok的使用逻辑问题
3.1 行遍历的初始化问题
你用strtok(lnptr, ",")拆分字段,但要确保lnptr初始指向当前行的首地址——比如用strtok(line, "\n")先拆分出每行,再对每行调用strtok拆分字段。你的代码里lnptr = NULL;放在循环内是对的,但要保证第一次调用strtok时传入的是有效行指针。
3.2 空Token的处理
你的示例字符串里有,4.2,6.8,开头的逗号会让strtok返回空字符串"",此时strtod("", NULL)会返回0,同时设置错误标记。如果你的CSV允许空值,需要额外判断处理:
char* endptr; double d = strtod(token, &endptr); // 如果token是空字符串,或者转换失败(比如非数字内容) if (endptr == token) { // 可设为NaN标记空值,需要包含<math.h> d = NAN; }
4. 列索引的逻辑混淆
你把记录最大列数的cols当成了当前列的索引,这完全搞混了变量用途!当前列的索引应该是l_cols,cols只需要在每次循环后更新为最大列数即可:
for (int l_cols = 0; (token = strtok(lnptr, ",")) != NULL; l_cols++) { lnptr = NULL; // 更新最大列数(l_cols从0开始,列数是索引+1) if (l_cols >= cols) { cols = l_cols + 1; } char* endptr; double d = strtod(token, &endptr); if (endptr == token) { d = NAN; // 处理空值/非法转换 } printf("csv[%d,%d] = '%s'", rows, l_cols, token); csv[rows][l_cols] = d; printf(", converted %.2f, assigned %.2f\n", d, csv[rows][l_cols]); }
之前的写法会导致所有值都错误地存在同一个列位置,逻辑完全混乱。
修正后的完整代码片段示例
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #define MAX_SIZE 100 #define LINE_CAP 256 int main() { double csv[MAX_SIZE][MAX_SIZE]; char line[LINE_CAP] = "1,5\n6,4\n,4.2,6.8"; int rows = 0; int cols = 0; // 先按换行拆分每行 char* lnptr = strtok(line, "\n"); while (lnptr != NULL && rows < MAX_SIZE) { int l_cols = 0; char* token = strtok(lnptr, ","); // 再按逗号拆分当前行的每个字段 while (token != NULL && l_cols < MAX_SIZE) { // 更新最大列数 if (l_cols >= cols) { cols = l_cols + 1; } char* endptr; double d = strtod(token, &endptr); if (endptr == token) { d = NAN; // 标记空值/非法转换 } printf("csv[%d,%d] = '%s'", rows, l_cols, token); csv[rows][l_cols] = d; printf(", converted %.2f, assigned %.2f\n", d, csv[rows][l_cols]); token = strtok(NULL, ","); l_cols++; } rows++; lnptr = strtok(NULL, "\n"); } return 0; }
总结
- 优先修正
printf的格式符错误,这是你看到输出0的直接原因; - 修正二维数组的声明语法;
- 明确区分当前列索引(
l_cols)和最大列数(cols)的用途; - 处理空Token的情况,避免意外的0值;
- 确保
strtok的调用逻辑正确:先按换行拆分每行,再按逗号拆分每个字段。
内容的提问来源于stack exchange,提问作者Prophet Lamb

