C语言读取酒店房间结构体数组数据失败问题求助
酒店房间数据读取问题排查与解决
问题核心
通过saveRoomData写入文本格式的房间数据后,readRoomData无法正确读取数据到结构体数组,出现空值或错误数值,无编译错误。
代码错误点排查
文件模式不匹配
saveRoomData用文本模式"w"写入数据,但readRoomData用二进制模式"rb"读取,导致文本格式解析异常,需统一使用文本模式"r"读取。文件指针未重置
统计行数时,文件指针移动到了EOF位置,后续fscanf无法读取数据,需用rewind(roomReadFile)将指针重置到文件开头。换行符判断错误
代码中用c == "\n"(字符串字面量)判断换行,正确写法应为c == '\n'(单个字符)。行数统计逻辑错误
初始hotelSize=1会导致空文件或单行数据时统计错误,应初始化为0,统计换行符数量后,若文件非空且最后一行无换行需额外加1。读取目标错误
循环中始终往hotelRoom[0]写入数据,未遍历数组索引,导致所有数据覆盖到第一个元素。fscanf格式串错误
原格式串%c,%f,%d\n会读取任意字符(包括换行、逗号),而code是字符串,应使用%[^,]读取逗号前的内容,避免逗号被读入code字段。局部数组作用域失效
readRoomData中定义的hotelRoom是局部变量,函数返回后内存被释放,main中重新定义的数组与读取的数据无关,需通过动态分配内存传递数据。feof使用不当
!feof(roomReadFile)作为循环条件会导致多执行一次循环,应使用fscanf的返回值判断是否成功读取3个字段。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct roomsInHotel { char code[3]; // 房间编码:可选值p1、p2、p3 float price; int status; // 房间状态:1可用,0不可用 } Hotel; // 读取房间数据,动态分配内存并返回数组指针,返回值为房间数量 int readRoomData(Hotel **hotelRoom) { char c; int hotelSize = 0; FILE *roomReadFile = fopen("roomdata.dat", "r"); if (roomReadFile == NULL) { printf("文件打开失败。\n"); return 0; } // 统计文件行数 while ((c = fgetc(roomReadFile)) != EOF) { if (c == '\n') { hotelSize++; } } // 处理最后一行无换行的情况 fseek(roomReadFile, 0, SEEK_END); long fileSize = ftell(roomReadFile); if (fileSize > 0 && c != '\n') { hotelSize++; } // 重置文件指针到开头 rewind(roomReadFile); // 动态分配内存存储房间数据 *hotelRoom = (Hotel*)malloc(sizeof(Hotel) * hotelSize); if (*hotelRoom == NULL) { printf("内存分配失败。\n"); fclose(roomReadFile); return 0; } // 读取每一行数据到结构体数组 int i = 0; while (fscanf(roomReadFile, "%[^,],%f,%d\n", (*hotelRoom)[i].code, &(*hotelRoom)[i].price, &(*hotelRoom)[i].status) == 3) { i++; } fclose(roomReadFile); return hotelSize; } // 保存房间数据到文件 void saveRoomData(Hotel hotelRoom[], int hotelSize) { FILE *roomDataFile = fopen("roomdata.dat", "w"); if (roomDataFile == NULL) { printf("文件打开失败\n"); exit(0); } for (int i = 0; i < hotelSize; i++) { fprintf(roomDataFile, "%s,%.2f,%d\n", hotelRoom[i].code, hotelRoom[i].price, hotelRoom[i].status); } fclose(roomDataFile); } // 假设以下函数已实现 void enterRoom(Hotel hotelRoom[], int hotelSize); void mainMenu(Hotel hotelRoom[], int hotelSize); int main() { int hotelSize; Hotel *hotelRoom = NULL; hotelSize = readRoomData(&hotelRoom); // 若文件不存在或读取失败,初始化默认房间数据 if (hotelSize == 0 && hotelRoom == NULL) { hotelSize = 3; hotelRoom = (Hotel*)malloc(sizeof(Hotel) * hotelSize); strcpy(hotelRoom[0].code, "p1"); hotelRoom[0].price = 500.0f; hotelRoom[0].status = 1; strcpy(hotelRoom[1].code, "p2"); hotelRoom[1].price = 700.0f; hotelRoom[1].status = 1; strcpy(hotelRoom[2].code, "p3"); hotelRoom[2].price = 900.0f; hotelRoom[2].status = 0; } enterRoom(hotelRoom, hotelSize); saveRoomData(hotelRoom, hotelSize); mainMenu(hotelRoom, hotelSize); // 释放动态分配的内存 free(hotelRoom); return 0; }
关键修正说明
- 改用动态内存分配传递读取到的结构体数组,避免局部变量作用域问题。
- 使用
%[^,]格式符准确读取逗号分隔的房间编码,避免格式匹配错误。 - 完善行数统计逻辑,覆盖空文件、单行无换行等边界情况。
- 读取循环依赖
fscanf的返回值判断,避免feof的逻辑陷阱。
内容的提问来源于stack exchange,提问作者camilo5
相关产品推荐
相关产品推荐

