编制一个C语言成绩记录簿,每个学生信息包括:学号、姓名、C语言成绩。具体功能:
1)创建一个文本文件用来记录学生信息,输入至少30名学生的信息,保存在文本文件中;
2)将文本文件中的数据读出,按学号或姓名查询成绩;
3)能添加成绩记录;
4)能修改指定姓名或学号的学生的成绩;
5)显示输出60分以下、60~79、80~89、90分以上各分数段的学生信息,显示及格率和平均分,显示最高分和最低分,显示所有学生的排名(不能改变学生的学号顺序);
6)以上信息能保存在原文本文件中。
简易流程图:
源码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "malloc.h"
#include <stdlib.h>
#define STU_NUM 100 //学生人数(可一键修改)
#define LEN sizeof(struct Student) //链表长度
typedef struct Student{ //定义类并取一个别名
long num; //每个学生的学号
char name[20]; //每个学生的姓名
float score; //每个学生的C语言成绩
struct Student* next;
}STU;
int Menu(); //创建菜单
void Print(STU* head, int n); //打印函数
void AverSumofCourse(STU* head, int n); //计算每个学生的总分和平均分
STU* SortbyScore(STU* head, int n); //按每个学生的总分由高到低排出名次表
STU* Creat(int n); //创建链表并录入信息
STU* Creat1(int n); //功能同上
STU* SortbyNum(STU* head); //按学号由小到大排出成绩表
STU* SortbyName(STU* head, int n); //按姓名的字典顺序排出成绩表
void SearchbyNum(STU* head, int n); //按学号查询学生排名及其考试成绩
void SearchbyName(STU* head, int n); //按姓名查询学生排名及其考试成绩
void ModifybyNum(STU* head, int n); //按学号查询并修改学生考试成绩
void ModifybyName(STU* head, int n); //按姓名查询并修改学生考试成绩
void StatisticAnalysis(STU* head, int n); //按类别及比例输出
void WritetoFile(STU* head, int n); //将每个学生的纪录信息写入文件
STU* ReadfromFile(STU* head, int* n); //从文件中读出每个学生的纪录信息并显示
int main(){
int n, i;
STU* head; //定义链表头指针
head = (STU*)malloc(LEN);
head = ReadfromFile(head, &n);
while (1){
i = Menu();
if (i == 1) {
printf("******************************************************************************\n");
printf("请输入您要录入的学生人数:\n"); //输入录入学生人数
scanf("%d", &n);
printf("请依次输入录入学生的学号、姓名和C语言成绩(每输入一个数据按回车键)\n");
head = Creat(n);
//system("cls"); //清屏
}
else if (i == 2) {
printf("******************************************************************************\n");
printf("* *\n");
printf("* <1.按学号查询> <2.按姓名查询> *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf("请选择您的查询方式:");
int choice;
scanf("%d", &choice);
if (choice == 1) {
printf("\n");
printf("******************************************************************************\n");
printf("请输入您要查询学生的学号:");
SearchbyNum(head, n);
}
else {
printf("\n");
printf("******************************************************************************\n");
printf("请输入您要查询学生的姓名:");
SearchbyName(head, n);
}
}
else if (i == 3) {
printf("******************************************************************************\n");
printf("* *\n");
printf("* <1.按学号查询> <2.按姓名查询> *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf("请选择您的查询方式:");
int choice;
scanf("%d", &choice);
if (choice == 1) {
printf("\n");
printf("******************************************************************************\n");
printf("请输入您要查询学生的学号:");
ModifybyNum(head, n);
}
else {
printf("\n");
printf("******************************************************************************\n");
printf("请输入您要查询学生的姓名:");
ModifybyName(head, n);
}
}
else if (i == 4) {
printf("******************************************************************************\n");
printf("* *\n");
printf("* <1.按学号排序> <2.按姓名排序> <3.按成绩排序> *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf("请选择您的查询方式:");
int style;
scanf("%d", &style);
if (style == 1) {
printf("正在根据学生学号排序:\n");
head = SortbyNum(head);
Print(head, n);
}
else if (style == 2) {
printf("正在根据学生姓名排序:\n");
head = SortbyName(head, n);
Print(head, n);
}
else if (style == 3) {
printf("正在根据学生C语言成绩排序:\n");
head = SortbyScore(head, n);
Print(head, n);
};
}
else if (i == 5) {
printf("******************************************************************************\n");
StatisticAnalysis(head, n);
AverSumofCourse(head, n);
}
else if (i == 0) {
printf("******************************************************************************\n");
printf(" 欢迎下次使用本系统,谢谢!!!\n");
printf("******************************************************************************\n");
break;
}
else {
printf("******************************************************************************\n");
printf(" 输入错误!!!请重新输入。\n");
printf("******************************************************************************\n");
}
}
WritetoFile(head, n);
return 0;
}
// 创建菜单
int Menu(){
int i;
system("title 学生成绩记录簿管理");
printf("\n\n");
printf("******************************************************************************\n");
printf("* *\n");
printf("* <1.录入学生成绩> <2.查询学生成绩> *\n");
printf("* <3.修改学生成绩> <4.排序学生成绩> *\n");
printf("* <5.按分段分析成绩> <0.退出成绩管理系统> *\n");
printf("* *\n");
printf("******************************************************************************\n");
printf("\n");
printf("\n");
printf("#请输入您的操作:");
scanf("%d", &i);
return i;
}
// 创建链表
STU* Creat(int n) {
STU* head = NULL;
STU* p1, * p2 = NULL;
int i;
// system("cls");
for (i = 1; i < n + 1; i++){
p1 = (STU*)malloc(LEN);
printf("学号:");
scanf("%ld", &p1->num);
printf("姓名:");
scanf("%s", p1->name);
printf("C语言成绩:");
scanf("%f", &p1->score);
p1->next = NULL;
if (i == 1){
head = p2 = p1;
}
else{
p2->next = p1;
p2 = p1;
}
}
return(head);
}
STU* Creat1(int n){
STU* head = NULL;
STU* p1, * p2 = NULL;
int i;
// system("cls");
for (i = 1; i < n + 1; i++){
p1 = (STU*)malloc(LEN);
p1->next = NULL;
if (i == 1){
head = p2 = p1;
}
else{
p2->next = p1;
p2 = p1;
}
}
return(head);
}
void SearchbyNum(STU* head, int n){
long num;
int flag = 1;
scanf("%ld", &num);
STU* p;
p = head;
if (head != NULL){
do {
if (p->num == num){
printf("%ld\t%s\t", p->num, p->name);
printf("%.0f\t", p->score);
printf("\n");
flag = 0;
}
p = p->next;
} while (p != NULL);
if (flag){
printf("抱歉,没有找到该学生的成绩,请确定其是否已录入系统。\n");
}
}
printf("******************************************************************************\n");
}
void SearchbyName(STU* head, int n){
char name[20];
int flag = 1;
scanf("%s", name);
STU* p;
p = head;
if (head != NULL){
do {
if (strcmp(name, p->name) == 0){
printf("%ld\t%s\t", p->num, p->name);
printf("%.0f\t", p->score);
printf("\n");
flag = 0;
}
p = p->next;
} while (p != NULL);
if (flag){
printf("抱歉,没有找到该学生的成绩,请确定其是否已录入系统。\n");
}
}
printf("******************************************************************************\n");
}
void ModifybyNum(STU* head, int n) {
long num;
int flag = 1;
scanf("%ld", &num);
STU* p;
p = head;
if (head != NULL) {
do {
if (p->num == num) {
printf("请输入该学生的新成绩:");
scanf("%f", &(p->score));
printf("\n");
printf("修改成功!!!\n");
flag = 0;
}
p = p->next;
} while (p != NULL);
if (flag) {
printf("抱歉,没有找到该学生的成绩,请确定其是否已录入系统。\n");
}
}
printf("******************************************************************************\n");
}
void ModifybyName(STU* head, int n) {
char name[20];
int flag = 1;
scanf("%s", name);
STU* p;
p = head;
if (head != NULL) {
do {
if (strcmp(name, p->name) == 0) {
printf("请输入该学生的新成绩:");
scanf("%f", &(p->score));
printf("\n");
printf("修改成功!!!\n");
flag = 0;
}
p = p->next;
} while (p != NULL);
if (flag) {
printf("抱歉,没有找到该学生的成绩,请确定其是否已录入系统。\n");
}
}
printf("******************************************************************************\n");
}
STU* SortbyNum(STU* head){
STU* first; //为原链表剩下用于直接插入排序的节点头指针
STU* t; //临时指针变量:插入节点
STU* p=NULL, * q; //临时指针变量
first = head->next; //原链表剩下用于直接插入排序的节点链表:可根据图12来理解
head->next = NULL; //只含有一个节点的链表的有序链表:可根据图11来理解
while (first != NULL){ //遍历剩下无序的链表
//注意:这里for语句就是体现直接插入排序思想的地方
for (t = first, q = head; ((q != NULL) && (q->num < t->num)); p = q, q = q->next); //无序节点在有序链表中找插入的位置
first = first->next; //无序链表中的节点离开,以便它插入到有序链表中
if (q == head){ //插在第一个节点之前
head = t;
}
else{ //p是q的前驱
p->next = t;
}
t->next = q; //完成插入动作
//first = first->next;
}
return head;
}
STU* SortbyName(STU* head, int n){
STU* endpt; //控制循环比较
STU* p; //临时指针变量
STU* p1, * p2;
p1 = (STU*)malloc(LEN);
p1->next = head; //注意理解:我们增加一个节点,放在第一个节点的前面,主要是为了便于比较。因为第一个节点没有前驱,我们不能交换地址
head = p1; //让head指向p1节点,排序完成后,我们再把p1节点释放掉
for (endpt = NULL; endpt != head; endpt = p){
for (p = p1 = head; p1->next->next != endpt; p1 = p1->next){
if (strcmp(p1->next->name, p1->next->next->name) > 0){ //如果前面的节点键值比后面节点的键值大,则交换
p2 = p1->next->next;
p1->next->next = p2->next;
p2->next = p1->next;
p1->next = p2; //结合第4点理解
p = p1->next->next; //结合第6点理解
}
}
}
p1 = head; //把p1的信息去掉
head = head->next; //让head指向排序后的第一个节点
free(p1); //释放p1
p1 = NULL; //p1置为NULL,保证不产生“野指针”,即地址不确定的指针变量
return head;
}
STU* SortbyScore(STU* head, int n){
STU* endpt; //控制循环比较
STU* p; //临时指针变量
STU* p1, * p2;
p1 = (STU*)malloc(LEN);
p1->next = head; //注意理解:我们增加一个节点,放在第一个节点的前面,主要是为了便于比较。因为第一个节点没有前驱,我们不能交换地址
head = p1; //让head指向p1节点,排序完成后,我们再把p1节点释放掉
for (endpt = NULL; endpt != head; endpt = p){
for (p = p1 = head; p1->next->next != endpt; p1 = p1->next){
if (p1->next->score < p1->next->next->score){ //如果前面的节点键值比后面节点的键值大,则交换
p2 = p1->next->next;
p1->next->next = p2->next;
p2->next = p1->next;
p1->next = p2;
p = p1->next->next;
}
}
}
p1 = head; //把p1的信息去掉
head = head->next; //让head指向排序后的第一个节点
free(p1); //释放p1
p1 = NULL; //p1置为NULL,保证不产生“野指针”,即地址不确定的指针变量
return head;
}
void AverSumofCourse(STU* head, int n){
STU* p;
p = head;
float sum = 0;
if (head != NULL) { //只要不是空链表,就输出链表中所有节点
do {
sum += p->score;
p = p->next; //移到下一个节点
} while (p != NULL);
printf("学生平均分为:");
printf("%.2f\n", sum / n);
printf("******************************************************************************\n");
}
}
void StatisticAnalysis(STU* head, int n) {
int a[6];
STU* p;
p = head;
int j;
p = head; // 初始化
for (j = 0; j < 6; j++) { // 初始化
a[j] = 0;
}
do {
if (p->score < 60) {
a[0]++;
}
else if (p->score < 70) {
a[1]++;
}
else if (p->score < 80) {
a[2]++;
}
else if (p->score < 90) {
a[3]++;
}
else if (p->score < 100) {
a[4]++;
}
else {
a[5]++;
}
p = p->next;
} while (p != NULL);
printf("******************************************************************************\n");
printf("* 成绩情况如下:\n");
char x = '%';
printf("* <60\t%d\t%.2lf", a[0], (100 * (float)a[0] / n)); printf("%c", x); printf("\n");
printf("* %d-%d\t%d\t%.2lf", 60, 69, a[1], 100 * (float)a[1] / n); printf("%c",x); printf("\n");
printf("* %d-%d\t%d\t%.2lf", 70, 79, a[2], 100 * (float)a[2] / n); printf("%c", x); printf("\n");
printf("* %d-%d\t%d\t%.2lf", 80, 89, a[3], 100 * (float)a[3] / n); printf("%c", x); printf("\n");
printf("* %d-%d\t%d\t%.2lf", 90, 99, a[4], 100 * (float)a[4] / n); printf("%c", x); printf("\n");
printf("* %d\t%d\t%.2lf", 100, a[5], 100 * (float)a[5] / 6.0); printf("%c", x); printf("\n");
printf("学生及格率:%.2lf", 100*(float)(n - a[0]) / n); printf("%c", x);
printf("\n");
}
void Print(STU* head, int n){
STU* p;
p = head;
if (head != NULL){ //只要不是空链表,就输出链表中所有节点
printf("******************************************************************************\n");
do{
printf("%ld\t%s\t", p->num, p->name);
printf("%.0f\t", p->score);
printf("\n");
p = p->next; //移到下一个节点
} while (p != NULL);
printf("******************************************************************************\n");
}
}
STU* ReadfromFile(STU* head, int* n){
STU* p;
FILE* fp;
int i;
if ((fp = fopen("student.txt", "r")) == NULL){
printf("打开文件失败!!!\n");
return NULL;
}
fscanf(fp, "%d\n", n);
head = Creat1(*n); //创建了一个空链表,并且赋给head
p = head;
for (i = 0; i < *n; i++){
fscanf(fp, "%12ld", &p->num);
fscanf(fp, "%12s", &p->name);
fscanf(fp, "%12f", &p->score);
p = p->next;
}
i = *n;
//printf("文件读取成功!!!\n");
fclose(fp);
//Print(head, i);
return head;
}
void WritetoFile(STU* head, int n){
STU* p;
p = head;
FILE* fp;
int i;
printf("******************************************************************************\n");
if ((fp = fopen("student.txt", "a+")) == NULL){
printf("打开文件失败!!!\n");
return;
}
for (i = 0; i < n; i++){
fprintf(fp, "\n");
fprintf(fp, "%12ld%12s", p->num, p->name);
fprintf(fp, "%12.0f", p->score);
p = p->next;
}
printf("******************************************************************************\n");
printf(" 保存数据成功!!!\n");
printf("******************************************************************************\n");
fclose(fp);
}
总结:
本课程设计为C语言程序设计,使用了链表进行数据存储,设计相对简洁且已经过调试。