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

C语言路线数据处理疑问:读取文件首数字且不写入二进制文件

问题解决:C语言路线数据处理程序优化

需求回顾

  • 处理.txt文件中的路线结构体数组,结构体包含起点(30字符)、终点(30字符)、路线编号
  • 将数据按路线编号排序后写入二进制文件
  • 用户输入编号后,仅加载对应路线到内存,输出起点和终点
  • 当前困惑:无法读取.txt首行的记录数,且不将该数值写入二进制文件

解决方案代码

步骤说明

  1. 读取txt首行的记录数,用于后续读取结构体数据
  2. 读取所有路线数据到临时数组,排序后写入二进制文件(仅写入结构体数据,不包含记录数)
  3. 查询时,利用二进制文件的随机访问特性,遍历查找目标编号,找到后仅加载该结构体到内存

完整代码

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

// 路线结构体定义
struct MARSH
{
    char startOfRoute[30];
    char finalOfRoute[30];
    unsigned int routeNumber;
};

// 排序函数:按路线编号升序
void sortRoutes(struct MARSH* routes, int count)
{
    struct MARSH temp;
    for (int i = 0; i < count - 1; i++)
    {
        for (int j = i + 1; j < count; j++)
        {
            if (routes[j].routeNumber < routes[i].routeNumber)
            {
                temp = routes[i];
                routes[i] = routes[j];
                routes[j] = temp;
            }
        }
    }
}

// 从二进制文件查找目标路线,找到后加载到传入的结构体指针
bool findRouteFromBin(unsigned int targetNum, FILE* binFile, struct MARSH* result)
{
    struct MARSH temp;
    // 文件指针移到开头
    fseek(binFile, 0, SEEK_SET);
    // 逐个读取结构体,直到文件结束
    while (fread(&temp, sizeof(struct MARSH), 1, binFile) == 1)
    {
        if (temp.routeNumber == targetNum)
        {
            // 找到后复制到结果结构体,仅加载该数据到内存
            memcpy(result, &temp, sizeof(struct MARSH));
            return true;
        }
    }
    return false;
}

int main()
{
    FILE* txtFile = fopen("routes.txt", "r");
    if (!txtFile)
    {
        perror("Failed to open txt file");
        return 1;
    }

    // 读取txt首行的记录数
    int recordCount;
    if (fscanf(txtFile, "%d", &recordCount) != 1)
    {
        perror("Failed to read record count");
        fclose(txtFile);
        return 1;
    }
    // 跳过首行剩余的换行符,避免影响后续fgets
    fgetc(txtFile);

    // 动态分配内存存储所有路线(仅在转换阶段使用)
    struct MARSH* allRoutes = malloc(recordCount * sizeof(struct MARSH));
    if (!allRoutes)
    {
        perror("Failed to allocate memory");
        fclose(txtFile);
        return 1;
    }

    // 读取txt中的路线数据
    for (int i = 0; i < recordCount; i++)
    {
        // 读取起点
        fgets(allRoutes[i].startOfRoute, 30, txtFile);
        // 去掉fgets读取的换行符
        allRoutes[i].startOfRoute[strcspn(allRoutes[i].startOfRoute, "\n")] = '\0';
        
        // 读取终点
        fgets(allRoutes[i].finalOfRoute, 30, txtFile);
        allRoutes[i].finalOfRoute[strcspn(allRoutes[i].finalOfRoute, "\n")] = '\0';
        
        // 读取路线编号
        fscanf(txtFile, "%u", &allRoutes[i].routeNumber);
        // 跳过编号后的换行符
        fgetc(txtFile);
    }
    fclose(txtFile);

    // 按路线编号排序
    sortRoutes(allRoutes, recordCount);

    // 写入二进制文件(仅写入结构体数据,不包含记录数)
    FILE* binFile = fopen("routes.bin", "wb");
    if (!binFile)
    {
        perror("Failed to open binary file");
        free(allRoutes);
        return 1;
    }
    fwrite(allRoutes, sizeof(struct MARSH), recordCount, binFile);
    fclose(binFile);
    // 转换完成后释放临时内存
    free(allRoutes);

    // 用户查询阶段
    unsigned int routeChoice;
    printf("Enter the route number you need information about: ");
    scanf("%u", &routeChoice);

    // 打开二进制文件准备查询
    binFile = fopen("routes.bin", "rb");
    if (!binFile)
    {
        perror("Failed to open binary file for query");
        return 1;
    }

    struct MARSH targetRoute;
    bool found = findRouteFromBin(routeChoice, binFile, &targetRoute);
    fclose(binFile);

    if (!found)
    {
        printf("\nThere is no such route number.\n");
    }
    else
    {
        printf("\nStarting point of the route: %s\n", targetRoute.startOfRoute);
        printf("The final destination of the route: %s\n", targetRoute.finalOfRoute);
    }

    return 0;
}

关键细节说明

  • 读取txt首行记录数:用fscanf读取首行数字后,必须用fgetc跳过换行符,否则后续fgets会读取空行
  • 不写入记录数到二进制文件:写入时直接将排序后的结构体数组写入,不额外写入记录数值
  • 仅加载目标路线到内存:查询时逐个读取二进制文件中的结构体,找到目标后仅复制该结构体到内存,无需加载整个数组
  • 动态内存分配:避免固定数组大小限制,根据txt中的记录数分配内存

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 23:42:34