如何结合用户输入将多个结构体写入单个文件?
结构体文件读写问题解决
问题描述
我想把两个结构体写入文件,后续需要时可以读取。但不知道怎么获取用户输入的多组结构体数据并写入单个文件。
我试过用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
相关产品推荐
相关产品推荐

