如何将读取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; }
核心说明
独立函数设计
- 原main中的读取逻辑被抽为
read_students_from_text函数,通过参数传递数组和配置,不再依赖全局变量,提升了代码的复用性和可维护性。 - 函数返回成功读取的学生数量,失败返回-1,方便调用者快速判断执行结果。
- 原main中的读取逻辑被抽为
原逻辑优化
- 增大行缓冲区避免内容截断,用
strncpy替代strcpy防止缓冲区溢出,增加格式错误判断避免程序崩溃,读取完成后自动关闭文件防止资源泄漏。
- 增大行缓冲区避免内容截断,用
二进制读写方案
- 如果不需要文本文件的可读性,使用
fwrite/fread直接操作结构体数组效率更高:fwrite一次性将整个结构体数组写入文件,无需逐行解析。fread直接从文件读取二进制数据填充结构体数组,速度远快于文本解析。
- 如果不需要文本文件的可读性,使用
内容的提问来源于stack exchange,提问作者KonstantaV
相关产品推荐
相关产品推荐

