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

如何将读取test.txt结构体的代码从main函数抽离为独立函数?

重构学生数据读取逻辑为独立函数

以下是重构后的完整代码,包含文本文件读取的核心实现,以及二进制文件读写的扩展方案:

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

#define N 100  // 定义数组最大容量,可根据实际需求修改

struct student {
    char surname[50];
    char name[50];
    char dayBirth[50];
    int mark;
};

// 从文本文件读取学生数据到数组,返回成功读取的数量,失败返回-1
int read_students_from_text(const char* filename, struct student* students, int max_students) {
    if (filename == NULL || students == NULL || max_students <= 0) {
        return -1;
    }

    FILE* ptr = fopen(filename, "r");
    if (ptr == NULL) {
        printf("无法打开文件 %s\n", filename);
        return -1;
    }

    char str[150];  // 增大缓冲区,避免一行内容过长被截断
    const char* delimiter = " ";
    int count = 0;

    while (count < max_students && fgets(str, sizeof(str), ptr) != NULL) {
        // 去掉行尾的换行符
        str[strcspn(str, "\n")] = '\0';

        // 分割并填充姓氏
        char* token = strtok(str, delimiter);
        if (token == NULL) continue;
        strncpy(students[count].surname, token, sizeof(students[count].surname) - 1);
        students[count].surname[sizeof(students[count].surname) - 1] = '\0';

        // 分割并填充名字
        token = strtok(NULL, delimiter);
        if (token == NULL) continue;
        strncpy(students[count].name, token, sizeof(students[count].name) - 1);
        students[count].name[sizeof(students[count].name) - 1] = '\0';

        // 分割并填充出生日期
        token = strtok(NULL, delimiter);
        if (token == NULL) continue;
        strncpy(students[count].dayBirth, token, sizeof(students[count].dayBirth) - 1);
        students[count].dayBirth[sizeof(students[count].dayBirth) - 1] = '\0';

        // 分割并转换分数
        token = strtok(NULL, delimiter);
        if (token == NULL) continue;
        students[count].mark = atoi(token);

        count++;
    }

    fclose(ptr);
    return count;
}

// 可选:将学生数组写入二进制文件(高效存储)
int write_students_to_binary(const char* filename, const struct student* students, int student_count) {
    if (filename == NULL || students == NULL || student_count <= 0) {
        return -1;
    }

    FILE* ptr = fopen(filename, "wb");
    if (ptr == NULL) {
        printf("无法打开文件 %s\n", filename);
        return -1;
    }

    size_t written = fwrite(students, sizeof(struct student), student_count, ptr);
    fclose(ptr);

    return (written == student_count) ? student_count : -1;
}

// 可选:从二进制文件读取学生数组(高效读取)
int read_students_from_binary(const char* filename, struct student* students, int max_students) {
    if (filename == NULL || students == NULL || max_students <= 0) {
        return -1;
    }

    FILE* ptr = fopen(filename, "rb");
    if (ptr == NULL) {
        printf("无法打开文件 %s\n", filename);
        return -1;
    }

    size_t read = fread(students, sizeof(struct student), max_students, ptr);
    fclose(ptr);

    return (int)read;
}

int main() {
    struct student PI1[N];
    int student_count;

    // 从文本文件读取数据
    student_count = read_students_from_text("test.txt", PI1, N);
    if (student_count == -1) {
        return 1;
    }
    printf("成功读取 %d 名学生数据\n", student_count);

    // 可选:将数据写入二进制文件
    if (write_students_to_binary("students.bin", PI1, student_count) != -1) {
        printf("已将数据写入二进制文件\n");
    }

    // 可选:从二进制文件读取数据
    struct student PI2[N];
    int read_count = read_students_from_binary("students.bin", PI2, N);
    if (read_count != -1) {
        printf("从二进制文件读取 %d 名学生数据\n", read_count);
    }

    return 0;
}

核心说明

  1. 独立函数设计

    • 原main中的读取逻辑被抽为read_students_from_text函数,通过参数传递数组和配置,不再依赖全局变量,提升了代码的复用性和可维护性。
    • 函数返回成功读取的学生数量,失败返回-1,方便调用者快速判断执行结果。
  2. 原逻辑优化

    • 增大行缓冲区避免内容截断,用strncpy替代strcpy防止缓冲区溢出,增加格式错误判断避免程序崩溃,读取完成后自动关闭文件防止资源泄漏。
  3. 二进制读写方案

    • 如果不需要文本文件的可读性,使用fwrite/fread直接操作结构体数组效率更高:
      • fwrite一次性将整个结构体数组写入文件,无需逐行解析。
      • fread直接从文件读取二进制数据填充结构体数组,速度远快于文本解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:16:11