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

C语言读取酒店房间结构体数组数据失败问题求助

酒店房间数据读取问题排查与解决

问题核心

通过saveRoomData写入文本格式的房间数据后,readRoomData无法正确读取数据到结构体数组,出现空值或错误数值,无编译错误。

代码错误点排查

  1. 文件模式不匹配
    saveRoomData用文本模式"w"写入数据,但readRoomData用二进制模式"rb"读取,导致文本格式解析异常,需统一使用文本模式"r"读取。

  2. 文件指针未重置
    统计行数时,文件指针移动到了EOF位置,后续fscanf无法读取数据,需用rewind(roomReadFile)将指针重置到文件开头。

  3. 换行符判断错误
    代码中用c == "\n"(字符串字面量)判断换行,正确写法应为c == '\n'(单个字符)。

  4. 行数统计逻辑错误
    初始hotelSize=1会导致空文件或单行数据时统计错误,应初始化为0,统计换行符数量后,若文件非空且最后一行无换行需额外加1。

  5. 读取目标错误
    循环中始终往hotelRoom[0]写入数据,未遍历数组索引,导致所有数据覆盖到第一个元素。

  6. fscanf格式串错误
    原格式串%c,%f,%d\n会读取任意字符(包括换行、逗号),而code是字符串,应使用%[^,]读取逗号前的内容,避免逗号被读入code字段。

  7. 局部数组作用域失效
    readRoomData中定义的hotelRoom是局部变量,函数返回后内存被释放,main中重新定义的数组与读取的数据无关,需通过动态分配内存传递数据。

  8. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:33:25