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

如何正确使用fgets从文件逐行读取内容并存入pokemon结构体数组?

Pokemon结构体文件读写:修复readfile函数问题

需求说明

需要实现两个函数:

  • writefile:将pokemon结构体数组的内容写入文件,格式为每行交替存储等级和名称,例如:

30
Pikachu
12
Charizard

  • readfile:从上述格式的文件中逐行读取,将数据还原到pokemon结构体数组中

当前readfile函数的错误点

  1. 错误使用feof作为循环条件:feof仅在读取操作失败后才会触发,会导致循环多执行一次,读取无效数据
  2. 直接用fgets写入int类型变量:pokearray[i].level是int类型,fgets只能读取字符串,直接赋值会导致内存错误
  3. 无效代码:pokearray[10].level;这行没有任何实际作用,属于冗余代码
  4. 未处理名字读取:循环只尝试读取等级,完全忽略了名称的读取逻辑
  5. 未递增索引i:循环中没有更新i,所有数据会覆盖到同一个结构体位置
  6. 未更新num参数:没有将实际读取到的宝可梦数量返回给调用者
  7. 未处理读取失败的情况:没有判断fgets的返回值,无法提前终止循环

修复后的readfile函数

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

struct pokemon
{
    int level;
    char name[30];
};

int readfile(struct pokemon pokearray[], int* num, char filename[])
{
    FILE *fp;
    int i = 0;
    char level_buf[20]; // 临时存储读取到的等级字符串

    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        printf("打开文件失败");
        return -1;
    }

    // 循环读取每组(等级+名称)数据,直到读取失败或数组满
    while (i < 10) // 假设pokearray最多存储10个元素,可根据实际调整
    {
        // 读取等级字符串
        if (fgets(level_buf, sizeof(level_buf), fp) == NULL)
            break;
        // 移除字符串末尾的换行符
        level_buf[strcspn(level_buf, "\n")] = '\0';
        // 转换为int类型赋值给level
        pokearray[i].level = atoi(level_buf);

        // 读取名称
        if (fgets(pokearray[i].name, sizeof(pokearray[i].name), fp) == NULL)
            break;
        // 移除名称末尾的换行符
        pokearray[i].name[strcspn(pokearray[i].name, "\n")] = '\0';

        i++;
    }

    *num = i; // 将实际读取到的数量返回给调用者
    fclose(fp);
    return 0;
}

关键修复说明

  • 替换循环条件:通过判断fgets的返回值终止循环,避免feof的坑
  • 等级读取处理:先用临时字符串存储读取到的等级,再通过atoi转换为int类型
  • 移除换行符:使用strcspn自动定位换行符位置并替换为结束符,避免结构体中存储多余的换行
  • 完整读取逻辑:每次循环读取一组等级和名称,确保每个结构体对应一条完整的宝可梦数据
  • 数组越界保护:添加i < 10的判断,防止超出结构体数组的容量
  • 返回读取数量:通过num指针将实际读取到的宝可梦个数传递给调用者

配套writefile函数示例

int writefile(struct pokemon pokearray[], int num, char filename[])
{
    FILE *fp = fopen(filename, "w");
    if (fp == NULL)
    {
        printf("打开文件失败");
        return -1;
    }

    for (int i = 0; i < num; i++)
    {
        fprintf(fp, "%d\n", pokearray[i].level);
        fprintf(fp, "%s\n", pokearray[i].name);
    }

    fclose(fp);
    return 0;
}

内容的提问来源于stack exchange,提问作者Isaiah Dela Cruz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 12:45:47