结构体与文件读写问题求助:写入正常但读取异常
结构体与文件数据读写异常排查
问题现象
结构体数据写入文件功能正常,但从文件读取到结构体时仅第一条数据显示正确,其余数据出现乱码或值异常。
原代码
#include <stdio.h> #include <stdlib.h> const char* MemberFormatIn="(%[^,], %[^,], %[^,], %d)"; const char* MemberFormatOut="(%s, %s, %s, %d)\n"; typedef struct member { char name[20], lastName[20], address[20]; int age; }p1,p2; void inputMemberList(struct member p[],int count) { printf("name:"); scanf("%s",p[count].name); printf("lastName:"); scanf("%s",p[count].lastName); printf("address:"); scanf("%s",p[count].address); printf("age:"); scanf("%d",&p[count].age); } void printMemberList(struct member p[],int count) { system("cls"); for(int i=0; i<count; i++) { printf("\aMember %d:\n", i+1); printf("Name is: %s", p[i].name); printf("\nLast name is: %s", p[i].lastName); printf("\nAddress is: %s", p[i].address); printf("\nAge is: %d", p[i].age); printf("\n\n"); } } void saveMember(struct member p[],int count) { FILE* fp = fopen("member.txt","a+"); if (fp == NULL) { printf("File can't open."); exit(1); } fprintf(fp, MemberFormatOut, p[count].name, p[count].lastName, p[count].address, p[count].age); fclose(fp); } void fileToStructure(struct member p[],int count) { FILE* fp = fopen("member.txt","a+"); if (fp == NULL) { printf("File can't open."); exit(1); } fseek(fp, 0, SEEK_SET); for (int i=0; i<count+1; i++) { fscanf(fp, MemberFormatIn, p[i].name, p[i].lastName, p[i].address, &p[i].age); } fclose(fp); } int numberOfMember() { int count = 0; char c; FILE* fp = fopen("member.txt","r"); if(fp == NULL) { printf("File can't open."); exit(1); } do { c = fgetc(fp); if(c == '\n') count++; }while(c != EOF); fclose(fp); return count; } int main() { int len = 100; p1 p[len]; int count = numberOfMember(); inputMemberList(p,count); saveMember(p,count); fileToStructure(p,count); printMemberList(p,count); return 0; }
文件示例数据
(ahmad, dad, tir, 12) (hossein, dad, tiran, 12) (ali, dad, tir, 15) (mohammadi, mmad, tiron, 16) (helma, dad, tiran, 5) (mohammad, amin, dadkhah, 5)
异常输出示例
Member 1: Name is: ahmad Last name is: dad Address is: tir Age is: 12 Member 2: Name is: ├wöΩ` Last name is: Address is: ↑ Age is: 0 Member 3: Name is: Ä Last name is: t Address is: e Age is: 7471221 Member 4: Name is: r Last name is: l Address is: o Age is: 6881396 Member 5: Name is: n Last name is: s Address is: Age is: 0 Member 6: Name is: Last name is: Address is: Age is: 0
问题根源与修复方案
1. 读取格式字符串不匹配
你的MemberFormatIn未匹配文件中每条数据的完整格式:文件每行结尾是)加换行符,而原格式字符串只读到%d就结束,导致)和换行符残留输入缓冲区,干扰后续读取。
修复:修改格式字符串,完整匹配行尾的)和换行:
const char* MemberFormatIn="(%[^,], %[^,], %[^,], %d)\n";
2. fileToStructure循环次数与逻辑问题
原函数循环i<count+1,但count是写入前的文件行数,写入后总数据量应为count+1,且打开文件用a+冗余,只读场景用r更稳妥。
修复:
void fileToStructure(struct member p[],int totalCount) { FILE* fp = fopen("member.txt","r"); if (fp == NULL) { printf("File can't open."); exit(1); } for (int i=0; i<totalCount; i++) { // 增加读取失败检查,避免无效数据填充 if (fscanf(fp, MemberFormatIn, p[i].name, p[i].lastName, p[i].address, &p[i].age) != 4) { printf("读取第%d条数据失败\n", i+1); break; } } fclose(fp); }
3. numberOfMember计数逻辑缺陷
原函数仅统计换行符数量,若文件最后一行无换行,会少统计一条数据。
修复:
int numberOfMember() { int count = 0; char c; FILE* fp = fopen("member.txt","r"); if(fp == NULL) { printf("File can't open."); exit(1); } // 处理空文件 if (fgetc(fp) == EOF) { fclose(fp); return 0; } fseek(fp, 0, SEEK_SET); do { c = fgetc(fp); if(c == '\n') count++; }while(c != EOF); // 检查最后一行是否无换行,补统计 fseek(fp, -1, SEEK_END); c = fgetc(fp); if (c != '\n') { count++; } fclose(fp); return count; }
4. main函数参数传递修正
原fileToStructure传入的count是写入前的数量,应传入写入后的总数量count+1:
int main() { int len = 100; p1 p[len]; int count = numberOfMember(); inputMemberList(p,count); saveMember(p,count); int totalCount = count + 1; fileToStructure(p,totalCount); printMemberList(p,totalCount); return 0; }
完整修复后代码
#include <stdio.h> #include <stdlib.h> const char* MemberFormatIn="(%[^,], %[^,], %[^,], %d)\n"; const char* MemberFormatOut="(%s, %s, %s, %d)\n"; typedef struct member { char name[20], lastName[20], address[20]; int age; } p1,p2; void inputMemberList(struct member p[],int count) { printf("name:"); scanf("%s",p[count].name); printf("lastName:"); scanf("%s",p[count].lastName); printf("address:"); scanf("%s",p[count].address); printf("age:"); scanf("%d",&p[count].age); } void printMemberList(struct member p[],int count) { system("cls"); for(int i=0; i<count; i++) { printf("Member %d:\n", i+1); printf("Name is: %s", p[i].name); printf("\nLast name is: %s", p[i].lastName); printf("\nAddress is: %s", p[i].address); printf("\nAge is: %d", p[i].age); printf("\n\n"); } } void saveMember(struct member p[],int count) { FILE* fp = fopen("member.txt","a+"); if (fp == NULL) { printf("File can't open."); exit(1); } fprintf(fp, MemberFormatOut, p[count].name, p[count].lastName, p[count].address, p[count].age); fclose(fp); } void fileToStructure(struct member p[],int totalCount) { FILE* fp = fopen("member.txt","r"); if (fp == NULL) { printf("File can't open."); exit(1); } for (int i=0; i<totalCount; i++) { if (fscanf(fp, MemberFormatIn, p[i].name, p[i].lastName, p[i].address, &p[i].age) != 4) { printf("读取第%d条数据失败\n", i+1); break; } } fclose(fp); } int numberOfMember() { int count = 0; char c; FILE* fp = fopen("member.txt","r"); if(fp == NULL) { printf("File can't open."); exit(1); } if (fgetc(fp) == EOF) { fclose(fp); return 0; } fseek(fp, 0, SEEK_SET); do { c = fgetc(fp); if(c == '\n') count++; }while(c != EOF); fseek(fp, -1, SEEK_END); c = fgetc(fp); if (c != '\n') { count++; } fclose(fp); return count; } int main() { int len = 100; p1 p[len]; int count = numberOfMember(); inputMemberList(p,count); saveMember(p,count); int totalCount = count + 1; fileToStructure(p,totalCount); printMemberList(p,totalCount); return 0; }
内容的提问来源于stack exchange,提问作者Mohap
相关产品推荐
相关产品推荐

