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

C语言读取TXT文件单词存入结构体及后续操作实现问题

C语言读取文本单词到结构体修复方案

原代码核心问题

  • 结构体赋值位置错误:sscanf始终写入第一个结构体元素,没有按行写入w[*count]对应的位置
  • 计数变量count递增逻辑错误:仅在数组扩容时才执行count++,正常读取行时不会移动下标
  • 内存分配失败后缺少返回逻辑:calloc分配失败时未直接返回NULL,会后续触发空指针访问
  • 多余未使用变量i,无实际作用
  • 缺少文件关闭、内存释放逻辑,存在资源泄漏

修复后完整代码

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

#define MAX (10)     // 单单词最大字母数小于10

struct word{
    char word1[MAX+1];  // 存储每行第一个单词,缺省为空
    char word2[MAX+1];  // 存储每行第二个单词,缺省为空
};

struct word *file_read(FILE *fp, int *count){
    int dim = 2;        // 结构体数组初始容量
    char buf[1024];     // 行读取缓冲区
    struct word *w;
    int conv = 0;       // sscanf匹配成功的字段数

    // 初始化结构体数组,calloc默认0初始化,刚好满足缺省字段留空的需求
    if(!(w = calloc(dim , sizeof(*w)))){
        return NULL;
    }
    
    *count = 0; // 初始化计数为0
    while(fgets(buf, sizeof(buf), fp) != NULL){
        // 先检查是否需要扩容,避免下标越界
        if(*count >= dim){
            dim *= 2;
            struct word* temp = realloc(w, sizeof(*w)*dim);
            if(temp == NULL){
                free(w);
                return NULL;
            }
            w = temp;
            // 新扩容的空间清零,保证缺省字段为空
            memset(w + *count, 0, (dim - *count) * sizeof(*w));
        }

        // 向当前下标对应的结构体写入数据
        conv = sscanf(buf, "%s %s", w[*count].word1, w[*count].word2);

        // 测试打印,可删除
        if(conv >= 1){
            printf("\n第%d行:%s ", *count + 1, w[*count].word1);
        }
        if(conv == 2){
            printf("%s", w[*count].word2);
        }

        // 每读完一行,计数+1
        (*count)++;
    }
    return w;
}

// 示例:冒泡排序,按word1字典序排序
void bubble_sort(struct word *w, int count){
    for(int i = 0; i < count - 1; i++){
        for(int j = 0; j < count - i - 1; j++){
            if(strcmp(w[j].word1, w[j+1].word1) > 0){
                struct word temp = w[j];
                w[j] = w[j+1];
                w[j+1] = temp;
            }
        }
    }
}

// 示例:修改指定行的单词
int modify_word(struct word *w, int count, int line, int word_idx, char *new_val){
    if(line < 0 || line >= count || word_idx < 1 || word_idx > 2){
        return -1; // 参数非法
    }
    if(word_idx == 1){
        strncpy(w[line].word1, new_val, MAX);
        w[line].word1[MAX] = '\0'; // 防止溢出
    }else{
        strncpy(w[line].word2, new_val, MAX);
        w[line].word2[MAX] = '\0';
    }
    return 0;
}

int main(int argc, char *argv[]){
    if(argc < 2){
        printf("请传入文件路径参数\n");
        return 1;
    }

    FILE *fp = fopen(argv[1], "r");
    if(fp == NULL){
        perror("文件打开失败");
        return 1;
    }
    
    struct word *w;
    int count = 0;
    w = file_read(fp, &count);
    fclose(fp); // 读取完成关闭文件

    if(w == NULL){
        printf("文件读取失败\n");
        return 1;
    }

    // 以下为功能测试示例
    printf("\n\n读取完成,共%d行数据\n", count);
    
    // 测试冒泡排序
    bubble_sort(w, count);
    printf("\n排序后结果:\n");
    for(int i = 0; i < count; i++){
        printf("第%d行:%s %s\n", i+1, w[i].word1, w[i].word2);
    }

    // 测试修改第2行第1个单词为new_word3
    modify_word(w, count, 1, 1, "new_word3");
    printf("\n修改后结果:\n");
    for(int i = 0; i < count; i++){
        printf("第%d行:%s %s\n", i+1, w[i].word1, w[i].word2);
    }

    // 释放内存
    free(w);
    return 0;
}

关键修改说明

  1. 赋值逻辑修正:sscanf直接写入当前下标对应的结构体w[*count],保证每行数据对应一个结构体元素
  2. 计数逻辑修正:每成功读取一行就执行(*count)++,扩容逻辑提前判断,避免下标越界
  3. 初始化逻辑优化:calloc默认将所有结构体字段初始化为0,缺省的单词字段自动为空字符串,符合需求
  4. 补充了扩容后内存清零逻辑,保证新分配的结构体字段默认是空
  5. 新增了冒泡排序、单词修改的示例实现,可直接扩展其他操作
  6. 补充了参数校验、资源释放逻辑,避免内存泄漏和非法访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:36:09