C语言解析CSV文件问题:解析后打印异常数字,求错误排查
嘿,你遇到的「奇怪数字」其实是字符的ASCII码值——这是代码里几个关键错误导致的,咱们一个个理清楚:
核心错误:字符直接赋值给整型变量
你把CSV里的字符(比如'1')直接赋值给int类型的ID、AGE、GPA数组,比如:
ID[j] = data[i];
字符'1'的ASCII码是49,所以你打印出来的是49而不是数字1。要把字符转成对应数字,单字符可以用data[i] - '0',但多位数的话需要用atoi()/atof()这类转换函数来处理。
其他关键问题
feof()的误用while(!feof(x))会导致最后一行被重复读取,因为feof()只有在读取到文件末尾后才会返回真。正确的写法应该是用fgets()的返回值判断:while(fgets(data, 999, x) != NULL)循环变量混乱
你在解析字段时同时用i和j递增,还在循环里额外i++,这会导致索引完全错乱,根本没法正确定位CSV的分隔符。建议用一个单独的索引变量(比如pos)来遍历当前行的字符,每个字段解析完更新pos的位置。GPA的类型错误
GPA是浮点数,但你定义了int GPA[300];,这会丢失小数部分,应该改成float GPA[300];,解析时用atof()转换。字符串未加终止符
解析NAME字符数组后,没有添加'\0',会导致打印时出现乱码,必须在解析完后手动加上:NAME[j] = '\0';条件判断逻辑错误
第三个循环的条件( data[i] != '\0' || data[i] != '\r' || data[i] != data[i] != '\n')完全错误:- 用
||(或)的话,条件永远为真(一个字符不可能同时等于'\0'和'\r') - 多写了重复的
data[i] !=,应该改成&&(与):(data[pos] != '\0' && data[pos] != '\r' && data[pos] != '\n')
- 用
未检查文件是否打开成功
如果database.csv不存在或者无法读取,fopen()会返回NULL,直接操作会导致崩溃,必须先判断:FILE *x = fopen("database.csv","rt"); if(x == NULL) { perror("无法打开文件"); return 1; }
修正后的示例代码
用strtok()分割CSV字段会更简洁可靠,这里给你一个简化版:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char data[1000]; FILE *x = fopen("database.csv","rt"); if(x == NULL) { perror("无法打开文件"); return 1; } char NAME[300][300]; // 二维数组存储多个名字 int ID[300], AGE[300]; float GPA[300]; int count = 0; while(fgets(data, 999, x) != NULL) { // 去掉换行符 data[strcspn(data, "\r\n")] = '\0'; // 分割字段 char *token = strtok(data, ","); if(token != NULL) ID[count] = atoi(token); token = strtok(NULL, ","); if(token != NULL) strcpy(NAME[count], token); token = strtok(NULL, ","); if(token != NULL) AGE[count] = atoi(token); token = strtok(NULL, ","); if(token != NULL) GPA[count] = atof(token); count++; } // 打印测试 for(int i=0; i<count; i++) { printf("ID: %d, 姓名: %s, 年龄: %d, GPA: %.2f\n", ID[i], NAME[i], AGE[i], GPA[i]); } fclose(x); return 0; }
内容的提问来源于stack exchange,提问作者Hidden Dragon

