C语言自定义strsub函数未加'\0'致字符串输出异常求助
C语言结构体字段输出异常排查(强制使用strsub函数)
问题背景
读取文件每行数据,通过自定义strsub函数拆分后存入结构体字符数组,再将结构体存入数组,但打印各字段时每个字段会输出后续所有内容,需排查并修复问题(必须保留strsub函数)。
核心错误点拆解
结构体成员数组容量不足,导致终止符越界
例如type[2]需要存储1个字符+1个'\0',但原代码中strsub(buf, train.type, 10, 11)试图读取2个字符,写入后sub[j] = '\0'会写到type[2],超出数组边界(仅索引0、1有效),破坏内存结构,导致字符串无法正确终止。
类似的容量不匹配问题存在于多个结构体成员:car[10]:需存10个字符+'\0',数组大小应改为11length[3]:需存2个字符+'\0',原代码读取3个字符会溢出horsepower[3]:同理,原代码读取3个字符溢出numberInTrain[4]:原代码读取4个字符溢出
strsub的end参数取值错误
原代码中end参数为包含式索引,导致读取字符数超过目标数组的可用容量(需留1位给'\0')。while(!feof(fp))逻辑缺陷
feof仅在读取操作失败后才置位,导致最后一次循环中fgets读取失败(已到文件末尾),但仍会执行拆分和存储操作,引入错误数据。printArray函数声明错误
原声明void printArray(struct trainCartrain[])中结构体名拼写错误,应为struct trainCar。
修复后的完整代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> // 补充exit所需头文件 #define MAX 100 FILE *fp, *csit; void strsub(char buf[], char sub[], int start, int end); void printArray(struct trainCar arr[], int count); // 增加元素个数参数 struct trainCar { char car[11]; // 10个字符 + '\0' char type[2]; // 1个字符 + '\0' char weight[6]; // 5个字符 + '\0' char length[3]; // 2个字符 + '\0' char horsepower[3]; // 2个字符 + '\0' char numberInTrain[4]; // 3个字符 + '\0' }; int main() { struct trainCar ar[7]; struct trainCar train; int i = 0; char buf[MAX]; if (!(fp = fopen("train.txt", "r"))) { printf("train.txt could not be opened for input.\n"); exit(1); } if (!(csit = fopen("csit.txt", "w"))) { printf("csit.txt could not be opened for output.\n"); exit(1); } // 用fgets返回值判断循环,替代feof逻辑 while (fgets(buf, MAX, fp) != NULL) { // 移除每行末尾的换行符 buf[strcspn(buf, "\n")] = '\0'; // 调整end参数,确保读取字符数=数组容量-1 strsub(buf, train.car, 0, 9); // 10个字符 strsub(buf, train.type, 10, 10); // 1个字符 strsub(buf, train.weight, 12, 16); // 5个字符 strsub(buf, train.length, 18, 19); // 2个字符 strsub(buf, train.horsepower, 21, 22); // 2个字符 strsub(buf, train.numberInTrain, 24, 26); // 3个字符 ar[i] = train; i++; } printArray(ar, i); // 传入实际存储的元素数量 fclose(csit); fclose(fp); return 0; } void strsub(char buf[], char sub[], int start, int end) { int i, j; // 增加边界检查,防止buf索引越界 if (start < 0 || end >= strlen(buf)) { sub[0] = '\0'; return; } for (j = 0, i = start; i <= end; i++, j++) { sub[j] = buf[i]; } sub[j] = '\0'; // 此时j的取值不会超过数组容量-1 } void printArray(struct trainCar arr[], int count) { for (int k = 0; k < count; k++) { printf("车厢类型:%s\n", arr[k].car); printf("类型标识:%s\n", arr[k].type); printf("重量:%s\n", arr[k].weight); printf("长度:%s\n", arr[k].length); printf("马力:%s\n", arr[k].horsepower); printf("编组序号:%s\n\n", arr[k].numberInTrain); } }
修复说明
- 调整所有结构体字符数组的大小,确保能容纳目标字符数+终止符
'\0'。 - 修改
strsub调用的end参数,使读取字符数等于数组容量-1,避免终止符越界。 - 用
fgets(buf, MAX, fp) != NULL替代while(!feof(fp)),避免最后一次无效循环。 - 补充
stdlib.h头文件,适配exit函数。 - 修复
printArray函数的声明和实现,增加元素个数参数,避免固定遍历超出实际存储数量。 - 给
strsub增加边界检查,防止对buf的越界访问。
验证结果
修复后每个字段会正确输出自身内容,不会带出后续字段数据,示例输出:
车厢类型:Boxcar 类型标识:D 重量:44000 长度:55 马力:16 编组序号:45 车厢类型:Hopper 类型标识:B 重量:23000 长度:62 马力:18 编组序号:33 ...
内容的提问来源于stack exchange,提问作者The Elina
相关产品推荐
相关产品推荐

