You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体与文件读写问题求助:写入正常但读取异常

结构体与文件数据读写异常排查

问题现象

结构体数据写入文件功能正常,但从文件读取到结构体时仅第一条数据显示正确,其余数据出现乱码或值异常。

原代码

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:21:07