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

如何结合用户输入将多个结构体写入单个文件?

结构体文件读写问题解决

问题描述

我想把两个结构体写入文件,后续需要时可以读取。但不知道怎么获取用户输入的多组结构体数据并写入单个文件。

我试过用scanf()读取输入,甚至在%d后加%*c来处理读取整数后留下的换行符'\n',但好像fwrite()只能传单个结构体当参数,也不知道怎么处理不同数据类型的输入并存到文件里,求帮忙解决。

原代码

#include <stdio.h>
#include <stdlib.h>

typedef struct Student_Details {
    int Num;
    char Name[15];
    char Message[100];
} Notes1;

typedef struct Additional_Details {
    float Marks;
    char Gender;
    int Class;
} Notes2;

void write(FILE *, Notes1, Notes2);
void read(FILE *);

int main()
{
    int ch;
    FILE *fp = fopen("Notes.txt", "w+");
    Notes1 txt1;
    Notes2 txt2;
    printf("Select choice\n1.Write\n2.Read\n");
    scanf("%d%*c", &ch);
    if (fp == NULL)
        printf("Could not able to open the file\n");
    else
        switch(ch) {
          case 1:
            write(fp, txt1, txt2);
          case 2:
            read(fp);
        }
   return 0;
}

void write(FILE *fp, Notes1 msg1, Notes2 msg2)
{
    printf("Enter Num,Name,Message,Marks,Gender & Class\n");
    scanf("%d%*c%s%s%f%*c%c%d",
          &msg1.Num, msg1.Name, msg1.Message,
          &msg2.Marks, msg2.Gender, &msg2.Class);
    fwrite(&msg1, sizeof(msg1), 1, fp);
    fclose(fp);
}

void read(FILE *fp)
{
    char ch;
    do {
        ch = fgetc(fp);
        printf("%c", ch);
    } while (ch != EOF);
    fclose(fp);
}

原代码存在的问题

  • switch语句中case 1没有break,执行完写入后会直接执行读取操作
  • write函数采用值传递结构体,修改的是副本,原数据不会被更新
  • scanf的%s会在空格处停止读取,无法获取带空格的Message;性别Gender的读取容易被换行符干扰
  • fwrite只写入了Notes1,遗漏了Notes2结构体
  • 用fgetc逐字符读取二进制写入的结构体,会显示乱码,应该用fread对应读取
  • 文件打开用w+文本模式,二进制读写应该用wb+/ab+模式
  • write函数直接关闭文件,后续操作无法进行;且不支持多组数据输入

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Student_Details {
    int Num;
    char Name[15];
    char Message[100];
} Notes1;

typedef struct Additional_Details {
    float Marks;
    char Gender;
    int Class;
} Notes2;

void writeRecords(FILE *fp);
void readRecords(FILE *fp);

int main()
{
    int ch;
    FILE *fp = NULL;

    printf("Select choice\n1.Write\n2.Read\n");
    scanf("%d%*c", &ch);

    switch(ch) {
        case 1:
            // 二进制追加模式,支持多组写入不覆盖原有内容
            fp = fopen("Notes.txt", "ab+");
            if (fp == NULL) {
                printf("Could not open the file\n");
                return 1;
            }
            writeRecords(fp);
            break;
        case 2:
            fp = fopen("Notes.txt", "rb");
            if (fp == NULL) {
                printf("Could not open the file\n");
                return 1;
            }
            readRecords(fp);
            break;
        default:
            printf("Invalid choice\n");
            return 1;
    }

    if (fp != NULL) fclose(fp);
    return 0;
}

void writeRecords(FILE *fp)
{
    char cont;
    Notes1 msg1;
    Notes2 msg2;

    do {
        printf("Enter Student Number: ");
        scanf("%d%*c", &msg1.Num);

        printf("Enter Name (no spaces): ");
        scanf("%s%*c", msg1.Name);

        printf("Enter Message (can include spaces): ");
        fgets(msg1.Message, sizeof(msg1.Message), stdin);
        // 移除fgets读取的换行符
        msg1.Message[strcspn(msg1.Message, "\n")] = '\0';

        printf("Enter Marks: ");
        scanf("%f%*c", &msg2.Marks);

        printf("Enter Gender (M/F): ");
        scanf("%c%*c", &msg2.Gender);

        printf("Enter Class: ");
        scanf("%d%*c", &msg2.Class);

        // 连续写入两个结构体
        fwrite(&msg1, sizeof(Notes1), 1, fp);
        fwrite(&msg2, sizeof(Notes2), 1, fp);

        printf("Do you want to add another record? (Y/N): ");
        scanf("%c%*c", &cont);
    } while (cont == 'Y' || cont == 'y');
}

void readRecords(FILE *fp)
{
    Notes1 msg1;
    Notes2 msg2;

    printf("\n--- Student Records ---\n");
    // 循环读取直到文件结束
    while (fread(&msg1, sizeof(Notes1), 1, fp) == 1 &&
           fread(&msg2, sizeof(Notes2), 1, fp) == 1) {
        printf("\nStudent Number: %d\n", msg1.Num);
        printf("Name: %s\n", msg1.Name);
        printf("Message: %s\n", msg1.Message);
        printf("Marks: %.2f\n", msg2.Marks);
        printf("Gender: %c\n", msg2.Gender);
        printf("Class: %d\n", msg2.Class);
    }
}

关键说明

  • 结构体处理:在写入函数内直接定义结构体,避免值传递的副本问题;如需外部传递,应使用指针
  • 输入优化:用fgets读取带空格的Message,并用strcspn清理换行符;每个输入后用%*c清空缓冲区的换行符
  • 文件操作:
    • 写入用ab+二进制追加模式,支持多次添加记录不覆盖
    • 读取用rb二进制只读模式,保证结构体数据正确解析
    • fwrite可连续调用,每次写入一组Notes1和Notes2
  • 多组输入:通过循环让用户选择是否继续添加,实现多组结构体写入
  • 读取逻辑:用fread对应fwrite的方式读取,每次读取一组两个结构体,直到文件结尾

内容的提问来源于stack exchange,提问作者IndyRose

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 23:15:57