如何在已完成的C语言学生记录程序中融入指针并实现文件存储?
学生记录管理程序:指针优化与文件存储实现
你的原代码其实已经在使用指针了——比如getscore函数的char *name、int *grade1这些参数都是指针,用来接收主函数中数组元素的地址,从而修改对应的值。不过我们可以进一步用结构体+指针更系统地应用指针,同时实现文件存储功能,满足教授的要求。
原代码的小问题修正
average函数中(a+b+c)/3是整数除法,会导致平均分计算错误(比如80+80+81=241,整数除法结果为80,实际应为80.33),需要强制转换为浮点数计算。rate函数的条件错误:ave > 91、ave >94、ave>97、ave>99应改为>=,否则对应分数会被错误归类为5.00。getch()需要包含<conio.h>头文件,换成更通用的system("pause")兼容性更好。
结构体+指针重构代码(含文件功能)
我们定义Student结构体统一存储单个学生的所有数据,用指针操作结构体数组,同时添加文件读写函数实现记录持久化。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_STUDENTS 3 // 定义学生结构体,整合所有数据 typedef struct { char name[50]; int quiz1; int quiz2; int quiz3; float average; float rating; } Student; // 函数声明 void getStudentData(Student *student); float calculateAverage(int a, int b, int c); float getRating(float ave); void displayStudents(Student *students, int count); void saveToFile(Student *students, int count); void loadFromFile(Student *students, int *count); int main() { Student students[MAX_STUDENTS]; int i; int studentCount = MAX_STUDENTS; system("cls"); for (i = 0; i < MAX_STUDENTS; i++) { system("cls"); printf("\t\tInput Student Record\n"); printf("Student# %d\n", i + 1); getStudentData(&students[i]); // 传递结构体元素的地址(指针) students[i].average = calculateAverage(students[i].quiz1, students[i].quiz2, students[i].quiz3); students[i].rating = getRating(students[i].average); } displayStudents(students, studentCount); saveToFile(students, studentCount); printf("\n\n数据已保存到student_records.txt\n"); // 可选:从文件读取数据并验证 Student loadedStudents[MAX_STUDENTS]; int loadedCount; loadFromFile(loadedStudents, &loadedCount); printf("\n\n从文件读取的记录:\n"); displayStudents(loadedStudents, loadedCount); system("pause"); return 0; } // 用结构体指针直接修改学生数据 void getStudentData(Student *student) { printf("Student Name: "); scanf("%s", student->name); // 指针访问结构体成员用-> printf("Quiz Score#1: "); scanf("%d", &student->quiz1); // 基本类型成员需取地址 printf("Quiz Score#2: "); scanf("%d", &student->quiz2); printf("Quiz Score#3: "); scanf("%d", &student->quiz3); } float calculateAverage(int a, int b, int c) { return (float)(a + b + c) / 3; // 强制转换为浮点数避免整数除法误差 } float getRating(float ave) { if (ave >= 99 && ave <= 100) return 1.00; else if (ave >= 97 && ave <= 98) return 1.25; else if (ave >= 94 && ave <= 96) return 1.50; else if (ave >= 91 && ave <= 93) return 1.75; else if (ave >= 88 && ave <= 90) return 2.00; else if (ave >= 84 && ave <= 87) return 2.25; else if (ave >= 80 && ave <= 83) return 2.50; else if (ave >= 77 && ave <= 79) return 2.75; else if (ave >= 75 && ave <= 76) return 3.00; else return 5.00; } // 用指针遍历结构体数组,批量显示数据 void displayStudents(Student *students, int count) { int i; printf("\nStudent Grade Record\n"); printf("\nNo. Name\tQuiz_1\tQuiz_2\tQuiz_3\tAverage\tRating\n"); for (i = 0; i < count; i++) { printf("%d.) %s\t\t%d\t%d\t%d\t%.2f\t%.2f\n", i+1, students[i].name, students[i].quiz1, students[i].quiz2, students[i].quiz3, students[i].average, students[i].rating); } } // 将学生数据写入文件 void saveToFile(Student *students, int count) { FILE *file = fopen("student_records.txt", "w"); if (!file) { printf("无法打开文件!\n"); return; } for (int i = 0; i < count; i++) { fprintf(file, "%s %d %d %d %.2f %.2f\n", students[i].name, students[i].quiz1, students[i].quiz2, students[i].quiz3, students[i].average, students[i].rating); } fclose(file); } // 从文件读取学生数据 void loadFromFile(Student *students, int *count) { FILE *file = fopen("student_records.txt", "r"); if (!file) { printf("无法打开文件!\n"); *count = 0; return; } *count = 0; while (fscanf(file, "%s %d %d %d %f %f", students[*count].name, &students[*count].quiz1, &students[*count].quiz2, &students[*count].quiz3, &students[*count].average, &students[*count].rating) != EOF) { (*count)++; if (*count >= MAX_STUDENTS) break; } fclose(file); }
关键指针应用说明
- 结构体指针:
getStudentData(Student *student)接收结构体地址,通过student->name直接修改主函数中结构体数组的元素,避免值传递的冗余。 - 数组指针:
displayStudents(Student *students, int count)中,students是结构体数组的指针,students[i]等价于*(students+i),通过指针遍历数组。 - 文件指针:
FILE *file是文件操作的核心指针,用来控制文件的打开、读写和关闭。
内容的提问来源于stack exchange,提问作者Tharanee Benlot
相关产品推荐
相关产品推荐

