信息学实验室作业(三)
更新: 2025/3/15 字数: 0 字 时长: 0 分钟
一、实验目的
本次实验聚焦于二进制文件处理,旨在熟练运用C语言标准库<stdio.h>
中的fread
、fwrite
、fseek
等函数,实现对包含学生信息的二进制文件的创建、数据读取与写入、成绩修正、不及格成绩处理以及文件内容查看等操作,进而深入理解二进制文件的特性及文件操作原理,提升文件处理编程能力。
二、实验内容
创建一个二进制文件,该文件由包含学生信息的结构体组成。结构体包含学生姓名、成绩数量以及不超过五个成绩的数组。根据补考结果对文件内容进行修正,在此过程中输出所有不及格成绩并获取新的成绩。同时,实现对文件内容的查看功能。
三、实现思路
- 定义学生结构体:设计一个结构体来存储学生的各项信息,包括姓名、成绩数量和成绩数组,以便后续对学生数据进行统一管理和操作。
- 创建二进制文件并录入学生信息:使用
fopen
函数以二进制写入模式("wb"
)打开文件。若文件打开成功,将预先设定的学生信息通过fwrite
函数逐笔写入文件。写入完成后,使用fclose
函数关闭文件,确保数据安全保存。 - 根据补考结果修正成绩:以二进制读写模式(
"rb+"
)重新打开文件。利用fseek
函数结合循环,遍历文件中的每一个学生结构体。读取学生成绩,判断是否存在不及格成绩(假设成绩低于60分为不及格)。若有不及格成绩,输出该成绩并提示用户输入补考后的新成绩。使用fseek
函数将文件指针定位到该不及格成绩对应的位置,使用fwrite
函数将更新后的成绩写回文件。 - 查看文件内容:以二进制读取模式(
"rb"
)打开文件。通过循环使用fread
函数读取文件中的每个学生结构体,并将学生的姓名、成绩数量和成绩等信息按一定格式输出到控制台,以便直观查看文件内容。
四、代码实现
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 50
#define MAX_SCORES 5
// 定义学生结构体
typedef struct {
char name[MAX_NAME_LENGTH];
int scoreCount;
float scores[MAX_SCORES];
} Student;
// 创建二进制文件并录入学生信息
void createStudentFile(const char *filename) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
perror("无法打开文件");
return;
}
Student students[] = {
{"张三", 3, {70, 50, 80}},
{"李四", 2, {40, 90}},
{"王五", 3, {60, 65, 55}}
};
int numStudents = sizeof(students) / sizeof(students[0]);
for (int i = 0; i < numStudents; i++) {
fwrite(&students[i], sizeof(Student), 1, file);
}
fclose(file);
}
// 根据补考结果修正成绩
void correctScores(const char *filename) {
FILE *file = fopen(filename, "rb+");
if (file == NULL) {
perror("无法打开文件");
return;
}
Student student;
float newScore;
while (fread(&student, sizeof(Student), 1, file) == 1) {
for (int i = 0; i < student.scoreCount; i++) {
if (student.scores[i] < 60) {
printf("学生 %s 的成绩 %.2f 不及格,请输入补考后的成绩: ", student.name, student.scores[i]);
scanf("%f", &newScore);
student.scores[i] = newScore;
}
}
// 将文件指针移动到当前学生结构体的起始位置
fseek(file, -sizeof(Student), SEEK_CUR);
// 写入修改后的学生结构体
fwrite(&student, sizeof(Student), 1, file);
}
fclose(file);
}
// 查看文件内容
void viewStudentFile(const char *filename) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
perror("无法打开文件");
return;
}
Student student;
while (fread(&student, sizeof(Student), 1, file) == 1) {
printf("姓名: %s\n", student.name);
printf("成绩数量: %d\n", student.scoreCount);
printf("成绩: ");
for (int i = 0; i < student.scoreCount; i++) {
printf("%.2f ", student.scores[i]);
}
printf("\n\n");
}
fclose(file);
}
int main() {
const char *filename = "students.dat";
// 创建二进制文件并录入学生信息
createStudentFile(filename);
// 根据补考结果修正成绩
correctScores(filename);
// 查看文件内容
viewStudentFile(filename);
return 0;
}
五、代码解释
- 结构体定义:
Student
结构体包含name
(姓名)、scoreCount
(成绩数量)和scores
(成绩数组)三个成员,用于存储单个学生的相关信息,方便后续在文件操作中对学生数据进行整体处理。 createStudentFile
函数:该函数接受一个文件名作为参数。使用fopen
函数以二进制写入模式打开文件,如果文件打开失败,通过perror
函数输出错误信息并返回。函数内部定义了一个包含多个学生信息的数组,通过循环遍历该数组,使用fwrite
函数将每个学生的结构体信息写入文件。最后,使用fclose
函数关闭文件,确保数据写入磁盘。correctScores
函数:此函数接受文件名作为参数,以二进制读写模式打开文件。在循环中,使用fread
函数读取文件中的每个学生结构体。对于每个学生的成绩数组,遍历判断是否有不及格成绩。若有,提示用户输入补考后的新成绩,更新结构体中的成绩。通过fseek
函数将文件指针定位到需要修改的成绩位置,使用fwrite
函数将新成绩写回文件。修改完成后,调整文件指针位置,以便继续读取下一个学生的信息。循环结束后,关闭文件。viewStudentFile
函数:该函数接受文件名作为参数,以二进制读取模式打开文件。在循环中,使用fread
函数读取文件中的每个学生结构体,并将学生的姓名、成绩数量和成绩等信息按特定格式输出到控制台。循环结束后,关闭文件。main
函数:在main
函数中,定义了文件名。首先调用createStudentFile
函数创建并初始化学生信息文件;接着调用correctScores
函数根据补考结果修正学生成绩;最后调用viewStudentFile
函数查看修正后的文件内容。
六、编译与运行
- 将上述代码保存为一个
.c
文件,例如student_grades.c
。 - 在命令行中,使用
gcc
编译器对代码进行编译,命令为gcc student_grades.c -o student_grades
。编译成功后会生成一个可执行文件student_grades
。 - 运行生成的可执行文件,命令为
./student_grades
。运行过程中,根据提示输入补考后的成绩。程序运行结束后,可在控制台查看修正后的学生信息。
七、实验总结
通过本次实验,成功掌握了二进制文件的基本操作,包括文件的创建、数据的写入与读取、文件指针的定位以及结构体在二进制文件中的应用。在实验过程中,遇到了文件指针定位不准确、数据覆盖错误等问题,通过仔细检查代码和查阅资料,深入理解了fseek
函数的工作原理和文件操作的细节,最终解决了问题。这不仅提高了对二进制文件处理的编程能力,还培养了在面对复杂问题时的调试和解决问题的能力。未来,将进一步探索二进制文件在更复杂数据管理场景中的应用,如大规模数据存储与检索,以提升自己的编程技能。