如何将CSV分词字符串元素分配至结构体成员?代码问题排查
问题分析与修复方案
核心错误原因
你的代码中**i的递增顺序完全错位**,导致结构体成员的赋值逻辑和预期不符:
在token循环里,你先执行i++再判断i的值,第一个token处理时i从0变成1,直接进入i==1的分支给var1赋值,而ot1.time(对应i==0)永远没有被赋值的机会,后续var2、var3的对应关系也全部偏移。
此外还有几个次要问题:
- 冗余的
sleep函数和标准库重名,且无实际作用 fscanf("%s", line)无法读取包含空格的CSV行,建议改用fgetsstrcpy存在缓冲区溢出风险
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> struct ot{ int time, var1; float var2; char var3[10]; }; int selection(){ printf("1.start/resume 4.end\n"); switch(getch()){ case '1': //直接用字符常量更易读,避免ASCII码硬编码 return 0; case '4': exit(0); default: return 1; //默认返回1,保持循环 } } int main() { struct ot ot1; const char *token; int i = 0, status; FILE *the_file = fopen("sample_data.csv", "r"); if (the_file == NULL) { perror("unable to open the file"); exit(1); } char line[2000]; status = selection(); //用fgets读取整行,替代fscanf避免空格截断问题 while (fgets(line, sizeof(line), the_file) != NULL) { if (kbhit()) { status = selection(); } int delay_ms = 0; token = strtok(line, ",\n"); //把换行符也加入分隔符,避免行尾的换行被当作token i = 0; //每次处理新行前重置i while(token != NULL){ printf("%s\n", token); //先根据当前i的值赋值,再递增i switch(i){ case 0: ot1.time = atoi(token); delay_ms = ot1.time; //如果需要用第一个字段作为延迟时间 break; case 1: ot1.var1 = atoi(token); break; case 2: ot1.var2 = atof(token); break; case 3: //用strncpy替代strcpy,避免缓冲区溢出,手动加终止符 strncpy(ot1.var3, token, sizeof(ot1.var3)-1); ot1.var3[sizeof(ot1.var3)-1] = '\0'; break; default: //处理多余的字段(可选) printf("Warning: unexpected extra token: %s\n", token); break; } i++; token = strtok(NULL, ",\n"); } Sleep(delay_ms); system("cls"); //打印结构体验证赋值结果 printf("结构体赋值结果:\n"); printf("time: %d\n", ot1.time); printf("var1: %d\n", ot1.var1); printf("var2: %.2f\n", ot1.var2); printf("var3: %s\n", ot1.var3); } fclose(the_file); //记得关闭文件 return 0; }
关键修改点
- 调整
i的赋值逻辑:先根据当前i的值将token分配到对应结构体成员,再执行i++,确保第一个token对应i=0(ot1.time),第二个对应i=1(ot1.var1),以此类推。 - 替换
fscanf为fgets:保证能读取包含空格的完整CSV行,同时把换行符加入strtok的分隔符,避免行尾的换行被误当作有效token。 - 安全处理字符串拷贝:用
strncpy替代strcpy,并手动添加字符串终止符,防止var3缓冲区溢出。 - 移除冗余代码:删除无意义的
sleep函数,优化selection函数的字符判断逻辑(直接用'1'、'4'替代ASCII码,可读性更强)。 - 添加文件关闭操作:避免资源泄漏。
测试建议
确保你的sample_data.csv每行格式符合预期,例如:
1000,123,45.67,test 2000,456,89.01,demo
运行程序后,就能看到每个token被正确分配到结构体的对应成员中。
内容的提问来源于stack exchange,提问作者Delwin Mathew
相关产品推荐
相关产品推荐

