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

C语言实现表格文本文件动物位置搜索的最优方法问询

动物位置搜索功能实现方案

问题背景

我有一个table.txt文件,内容如下:

class #1
Sect1: cat
Sect2: dog
Sect3: mouse
Sect4: bird
Sect5: squirrel

class#2
Sect1: shark
Sect2: octopus
Sect3: tuna
Sect4: eel
Sect5: dolphin

需要实现功能:提示用户输入动物名称,搜索文件内容后输出该动物的位置(例如输入mouse,输出The animal mouse is located at Class #1 in Sect#3)。

现有C代码已完成文件读取到缓冲区的部分,但搜索逻辑尚未实现,同时不确定是将每行存入数组还是用结构体组织数据更优,也不清楚当前缓冲区是否适合直接搜索,需要先解析内容。

现有代码

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

int main()
{
    FILE* infile;
    char* buffer;
    long numbytes;
    char animal[10];
    char class[10];
    char sect[10];

    infile = fopen("table.txt", "r");

    if (NULL == infile) {
        printf("file can't be opened \n");
        return 1; // 原代码未处理此分支的退出逻辑,会导致后续错误
    }

    /* 获取文件字节数 */
    fseek(infile, 0L, SEEK_END);
    numbytes = ftell(infile);

    /* 重置文件指针到开头 */
    fseek(infile, 0L, SEEK_SET);

    /* 分配缓冲区内存 */
    buffer = (char*)calloc(numbytes, sizeof(char));

    /* 内存分配失败处理 */
    if (buffer == NULL)
        return 1;

    /* 将文件内容读入缓冲区 */
    fread(buffer, sizeof(char), numbytes, infile);
    fclose(infile); // 原代码此处已关闭文件,后续重复关闭会报错

    printf("Enter animal to search: ");
    scanf("%s", animal);

    // 待实现搜索逻辑
    
    printf("\nThe aninmal %s is located in %s and %s", animal, class, sect);

    /* 释放缓冲区内存 */
    free(buffer);

    // 重复关闭文件,存在错误
    fclose(infile);
    return 0;
}

解决方案

思路分析

直接在缓冲区搜索虽然可行,但代码维护性差、扩展性弱。更优的方式是先将缓冲区内容解析为结构化数据(比如结构体数组),把每个动物的位置信息规整存储,后续搜索逻辑会更清晰高效。

修改后的完整代码

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

// 定义结构体存储动物的位置信息
typedef struct {
    char animal_name[20];
    char class[10];
    char section[10];
} AnimalLocation;

int main()
{
    FILE* infile;
    char* buffer;
    long numbytes;
    char animal[20];
    AnimalLocation* locations = NULL;
    int location_count = 0;
    char* line_start;
    char* line_end;
    char current_class[10] = {0};

    infile = fopen("table.txt", "r");
    if (NULL == infile) {
        printf("file can't be opened \n");
        return 1;
    }

    // 获取文件大小并分配缓冲区(多1字节存字符串结束符)
    fseek(infile, 0L, SEEK_END);
    numbytes = ftell(infile);
    fseek(infile, 0L, SEEK_SET);

    buffer = (char*)calloc(numbytes + 1, sizeof(char));
    if (buffer == NULL) {
        fclose(infile);
        return 1;
    }

    fread(buffer, sizeof(char), numbytes, infile);
    fclose(infile);

    // 逐行解析缓冲区内容
    line_start = buffer;
    while (line_start < buffer + numbytes) {
        // 定位行尾(换行符或文件末尾)
        line_end = strchr(line_start, '\n');
        if (!line_end) {
            line_end = buffer + numbytes;
        }
        *line_end = '\0'; // 将换行符替换为结束符,方便单行处理

        // 跳过空行
        if (strlen(line_start) == 0) {
            line_start = line_end + 1;
            continue;
        }

        // 识别并记录当前class
        if (strstr(line_start, "class") != NULL) {
            strncpy(current_class, line_start, sizeof(current_class) - 1);
            current_class[sizeof(current_class)-1] = '\0';
            // 统一class格式:将class#2转为class #2(可选,匹配示例输出格式)
            char* hash_pos = strchr(current_class, '#');
            if (hash_pos && hash_pos > current_class + 5) {
                memmove(hash_pos + 1, hash_pos, strlen(hash_pos));
                *hash_pos = ' ';
            }
        }
        // 解析Sect行,存储动物位置信息
        else if (strstr(line_start, "Sect") != NULL) {
            char* colon_pos = strchr(line_start, ':');
            if (colon_pos) {
                // 扩容结构体数组
                locations = realloc(locations, sizeof(AnimalLocation) * (location_count + 1));
                if (!locations) {
                    free(buffer);
                    return 1;
                }

                // 提取章节信息
                strncpy(locations[location_count].section, line_start, colon_pos - line_start);
                locations[location_count].section[colon_pos - line_start] = '\0';
                // 提取动物名称(跳过冒号后的空格)
                strncpy(locations[location_count].animal_name, colon_pos + 2, sizeof(locations[location_count].animal_name) - 1);
                locations[location_count].animal_name[sizeof(locations[location_count].animal_name)-1] = '\0';
                // 记录当前所属class
                strcpy(locations[location_count].class, current_class);
                location_count++;
            }
        }

        line_start = line_end + 1;
    }

    // 接收用户输入
    printf("Enter animal to search: ");
    scanf("%s", animal);

    // 搜索目标动物
    int found = 0;
    for (int i = 0; i < location_count; i++) {
        if (strcmp(locations[i].animal_name, animal) == 0) {
            printf("\nThe animal %s is located at %s in %s", animal, locations[i].class, locations[i].section);
            found = 1;
            break; // 假设动物名称唯一,找到即退出
        }
    }

    if (!found) {
        printf("\nAnimal %s not found", animal);
    }

    // 释放资源
    free(buffer);
    if (locations) {
        free(locations);
    }

    return 0;
}

代码说明

  1. 结构体设计:用AnimalLocation统一存储每个动物的名称、所属类和章节,结构化数据便于后续搜索和维护。
  2. 缓冲区解析:逐行处理缓冲区内容,先识别当前class,再解析每个Sect行,将信息存入结构体数组。
  3. 搜索逻辑:遍历结构体数组,对比动物名称,找到后输出标准格式的位置信息;未找到则提示。
  4. 错误修复:解决了原代码中重复关闭文件、未初始化变量、缓冲区无结束符等问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:15:05