C语言读取向量文件时strcat向字符串插入垃圾字符如何解决?
问题根源排查
你的代码存在4个核心问题,其中直接导致垃圾字符的是第2个:
- 第一次遍历完文件统计行数和逗号总数后,文件指针已经指向文件末尾,第二次循环调用
getc会直接返回EOF,读取逻辑根本不会执行,你观察到的垃圾值本质是calloc初始化后未被覆盖的残留值,或者非法操作写入的乱码。
- 第一次遍历完文件统计行数和逗号总数后,文件指针已经指向文件末尾,第二次循环调用
- 直接产生垃圾字符的核心错误:
strcat要求传入的两个参数都是以\0结尾的合法C字符串,你传入的&c是单个字符的地址,后面没有自动追加\0,strcat拼接时会从&c地址往后读取内存,直到碰到随机的\0才停止,自然会混入大量垃圾字符。
- 直接产生垃圾字符的核心错误:
- 变量重复定义:
str、ret、X三个变量在代码中被重复声明两次,部分编译器会直接报错。
- 变量重复定义:
- 数组分配大小错误:你给
X分配的大小是n*n,但实际你存储的是n行dim列的向量,应该分配n * dim * sizeof(double)的空间。
- 数组分配大小错误:你给
修复方案
按以下步骤修改代码即可解决问题:
- 第一次遍历统计完成后,调用
rewind(file)将文件指针重置到文件开头。 - 不要用
strcat拼接单个字符,改用下标直接赋值的方式往字符串里加字符,每次加完手动追加\0保证字符串合法。 - 删除重复的变量声明,修正数组分配的大小。
- 补充文件关闭、内存释放的逻辑,避免资源泄漏。
修复后可运行的核心代码示例
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h> int main(int argc, char* argv[]) { FILE *file; int n = 1, dim, i=0; int c; int com=0; assert(argc==2 && "argc != 2"); file = fopen(argv[1], "r"); assert(file && "file open failed"); // 第一遍统计行数和逗号数 for(c = getc(file); c!= EOF; c = getc(file)){ if(c == '\n'){ n++; } else if(c==','){ com++; } } dim = com/n +1; // 重置文件指针到开头 rewind(file); double* X = (double *)calloc(n * dim, sizeof(double)); assert(X); char* str = (char *)calloc(100, sizeof(char)); assert(str); int str_pos = 0; // 记录当前字符串填充位置 for(c = getc(file); c!= EOF; c = getc(file)){ if(c!=',' && c!= '\n' && str_pos < 99){ // 直接用下标赋值,不要用strcat str[str_pos++] = c; str[str_pos] = '\0'; // 手动加结束符 } else{ // 跳过空行的情况 if (str_pos > 0) { double ret = strtod(str, NULL); X[i] = ret; i++; // 重置字符串位置 str_pos = 0; str[0] = '\0'; } } } // 处理最后一行没有换行符的情况,避免漏掉最后一个元素 if (str_pos > 0) { double ret = strtod(str, NULL); X[i] = ret; i++; } // 测试输出 for (int j = 0; j < n; j++) { for (int k = 0; k < dim; k++) { printf("%lf ", X[j*dim +k]); } printf("\n"); } // 资源释放 fclose(file); free(X); free(str); return 0; }
内容的提问来源于stack exchange,提问作者Kahalon
相关产品推荐
相关产品推荐

