C语言 作业成绩管理系统

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

// 学生信息结构体
struct Student
{
	// 学号
	long stuid;
	// 姓名
	char stuname[20];
};

// 作业信息结构体
struct Homework
{
	// 作业编号
	long worksno;
	// 作业内容
	char workdata[100];
	// 作业成绩指针
	// struct list_node *p;
};

// 作业成绩单链表
struct list_node
{
	//数据域,用于存储数据
	// 学号
	long stuid;
	// 作业编号
	long worksno;
	// 作业成绩
	float grade;

	//指针,可以用来访问节点数据,也可以遍历,指向下一个节点
	struct list_node *next;
};

// 作业成绩结构体
struct Grade
{
	// 学号
	long stuid;
	// 作业编号
	long worksno;
	// 作业成绩
	float grade;
};

// 新增学生信息
void addStuInfo(struct Student stu[], int count)
{
	printf("请输入学号 姓名:\n");
	scanf("%d", &stu[count].stuid);
	scanf("%s", &stu[count].stuname);
}

// 修改学生信息
void updStuInfo(struct Student stu[], int count)
{
	long stuid;
	printf("请输入学号:\n");
	scanf("%d", &stuid);

	// 遍历数组 找到输入学号 并修改
	for (int i = 0; i < count; i++)
	{
		if (stu[i].stuid == stuid)
		{
			printf("请输入更改姓名:\n");
			scanf("%s", &stu[i].stuname);
			return;
		}
	}

	// 未找到 打印该信息
	printf("无此学号记录!\n");
}

// 查询学生信息
void qryStuInfo(struct Student stu[], int count)
{
	printf("学号\t姓名\n");
	// 遍历数组 打印学号 姓名信息
	for (int i = 0; i < count; i++)
	{
		printf("%d\t%s\n", stu[i].stuid, stu[i].stuname);
	}
}

// 新增作业信息
void addWorkInfo(struct Homework work[], int count)
{
	printf("请输入作业内容:\n");
	work[count].worksno = count;
	scanf("%s", &work[count].workdata);
}

// 修改作业信息
void updWorkInfo(struct Homework work[], int count)
{
	long wordsno;
	printf("请输入作业编号:\n");
	scanf("%d", &wordsno);

	// 遍历数组 找到输入对应作业编号 并修改
	for (int i = 0; i < count; i++)
	{
		if (work[i].worksno == wordsno)
		{
			printf("请输入更改内容:\n");
			scanf("%s", &work[i].workdata);
			return;
		}
	}

	// 未找到 打印该信息
	printf("无此作业记录!\n");
}

// 查询作业信息
void qryWorkInfo(struct Homework work[], int count)
{
	printf("作业编号\t作业内容\n");
	// 遍历数组 打印作业编号 作业内容信息
	for (int i = 0; i < count; i++)
	{
		printf("%d\t\t%s\n", work[i].worksno, work[i].workdata);
	}
}

// 创建成绩信息
struct list_node *createGradeInfo(long stuid, long worksno, float grade)
{
	//给每个节点分配结构体一样的空间大小 
	struct list_node *p = malloc(sizeof(struct list_node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return NULL;
	}
	//由于结构体在未初始化的时候一样是脏数据,所以要清 
	memset(p, 0, sizeof(struct list_node));
	//初始化第一个节点 进行赋值
	p->stuid = stuid;
	p->worksno = worksno;
	p->grade = grade;
	//将节点的后继指针设置为NULL 
	p->next = NULL;
	return p;
}

// 插入成绩信息
void insertGradeInfo(struct list_node *pH, struct list_node *new)
{
	//获取当前的位置 
	struct list_node *p = pH;
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		//移动到下一个节点 
		p = p->next;
	}
	//如果跳出以上循环,所以已经到了NULL的这个位置
	//此时直接把新插入的节点赋值给NULL这个位置 
	p->next = new;
}

// 录入 修改成绩
void updGrade(struct list_node *pH)
{
	long stuid;
	long worksno;
	printf("请输入学号 作业编号:\n");
	scanf("%d", &stuid);
	scanf("%d", &worksno);

	struct list_node *p = pH;
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		p = p->next;
		if (p->stuid == stuid
			&&p->worksno == worksno)
		{
			float grade;
			printf("请输入成绩:\n");
			scanf("%.2f", &grade);
			p->grade = grade;
			return;
		}
	}

	printf("未找到该学号 作业号信息!\n");
}

// 查看所有成绩信息
void showAllGrade(struct list_node *pH)
{
	//获取当前的位置 
	struct list_node *p = pH;
	printf("学号\t作业编号\t作业成绩\n");
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		p = p->next;
		printf("%d\t%d\t\t%.2f\n", p->stuid, p->worksno, p->grade);
	}
}

// 根据作业编号查看所有成绩
void showAllGradeByWorksno(struct list_node *pH)
{
	long worksno;
	printf("请输入作业编号:\n");
	scanf("%d", &worksno);

	//获取当前的位置 
	struct list_node *p = pH;
	printf("学号\t作业编号\t作业成绩\n");
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		p = p->next;

		if (p->worksno == worksno)
		{
			printf("%d\t%d\t\t%.2f\n", p->stuid, p->worksno, p->grade);
		}
	}
}

// 根据作业编号查看没有成绩学生信息
void showAllGradeByWorksnoWithNoGrade(struct list_node *pH)
{
	long worksno;
	printf("请输入作业编号:\n");
	scanf("%d", &worksno);

	//获取当前的位置 
	struct list_node *p = pH;
	printf("学号\t作业编号\t作业成绩\n");
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		p = p->next;

		if (p->worksno == worksno && p->grade == 0)
		{
			printf("%d\t%d\t\t%.2f\n", p->stuid, p->worksno, p->grade);
		}
	}
}

// 查看作业平均分
void showAvgGrade(struct list_node *pH, struct Homework work[], int stucount)
{
	// 该数组 存放对应作业总分
	float sum = 0;

	long worksno;
	printf("请输入作业编号:\n");
	scanf("%d", &worksno);

	//获取当前的位置 
	struct list_node *p = pH;
	//如果当前位置的下一个节点不为空 
	while (p->next)
	{
		p = p->next;
		if (p->worksno == worksno)
		{
			sum += p->grade;
		}
	}

	printf("作业编号\t平均分\n");
	printf("%d\t\t%.2f\n", worksno, sum / stucount);
}

// 根据作业编号查看所有成绩(降序)
void showAllGradeByWorksnoDesc(struct list_node *pH, int stucount)
{
	// 定义grade动态数组 存储每个学生 成绩
	struct Grade* const grade = (struct Grade*)malloc(sizeof(struct Grade*)*stucount);

	long worksno;
	printf("请输入作业编号:\n");
	scanf("%d", &worksno);

	//获取当前的位置 
	struct list_node *p = pH;
	printf("学号\t作业编号\t作业成绩\n");

	// 将作业编号为worksno 的学生成绩信息存入grade数组
	int n = 0;
	while (p->next)
	{
		p = p->next;

		if (p->worksno == worksno)
		{
			grade[n].stuid = p->stuid;
			grade[n].worksno = worksno;
			grade[n].grade = p->grade;
			n++;
		}
	}

	// 对grade数组进行排序(倒序)
	int i, j;

	struct Grade temp;
	for (i = 0; i < stucount; ++i) {
		for (j = stucount - 1; j > i; --j) {
			if (grade[j].grade > grade[j - 1].grade) {
				temp = grade[j];
				grade[j] = grade[j - 1];
				grade[j - 1] = temp;
			}
		}
	}

	// 遍历 打印信息
	for (int i = 0; i < stucount; ++i) {
		printf("%d\t%d\t\t%.2f\n", grade[i].stuid, grade[i].worksno, grade[i].grade);
	}
}

// 单链表释放
void Free_list(struct list_node *pHead) //释放链表
{
	struct list_node * p;
	while (pHead != NULL)
	{
		p = pHead;
		pHead = pHead->next;
		free(p);
		p = NULL;
	}
}


int main()
{
	// 学生数量统计
	int stucount = 0;
	// 作业数量统计(作业编号)
	int workcount = 0;
	// 作业成绩统计
	int gradecount = 0;

	// 定义学生信息结构体数组
	struct Student stu[100];
	// 定义作业信息结构体数组
	struct Homework work[100];

	// 创建单链表头结点
	struct list_node *header = createGradeInfo(0, 0, 0);

	int n = 0;
	long stuid;

	// 从文件读取学生信息
	FILE *frStu = fopen("stuinfo.txt", "r");
	if (frStu != NULL)
	{
		char StrLine[1024];
		while (!feof(frStu))
		{
			fgets(StrLine, 1024, frStu);	// 读取一行
			// 去除读取行末尾\n换行符 保证显示正常
			if (StrLine[strlen(StrLine) - 1]=='\n')
			{
				StrLine[strlen(StrLine) - 1] = '\0';
			}
			char* temp = strtok(StrLine, " ");// 按空格 分开 取学号
			char* temp1 = strtok(NULL, " ");// 取姓名
			// char* 转long 对学号赋值
			stu[stucount].stuid = strtol(temp, NULL, 10);
			// 对姓名赋值
			strcpy(stu[stucount].stuname, temp1);
			stucount++;
		}
		fclose(frStu);
	}

	// 从文件读取作业信息
	FILE *frWork = fopen("work.txt", "r");
	if (frWork != NULL)
	{
		char StrLine[1024];
		while (!feof(frWork))
		{
			fgets(StrLine, 1024, frWork);	// 读取一行
			// 去除读取行末尾\n换行符 保证显示正常
			if (StrLine[strlen(StrLine) - 1] == '\n')
			{
				StrLine[strlen(StrLine) - 1] = '\0';
			}
			// 文件 内容为空 跳过
			char* temp = strtok(StrLine, " ");// 按空格 分开 作业编号
			char* temp1 = strtok(NULL, " ");// 取作业内容
			// char* 转long 对作业编号赋值
			work[workcount].worksno = strtol(temp, NULL, 10);
			// 对作业内容赋值
			strcpy(work[workcount].workdata, temp1);
			workcount++;
		}
		fclose(frWork);
	}

	// 从文件读取成绩信息
	FILE *frGrade = fopen("grade.txt", "r");
	if (frGrade != NULL)
	{
		char StrLine[1024];
		while (!feof(frGrade))
		{
			fgets(StrLine, 1024, frGrade);	// 读取一行
			// 去除读取行末尾\n换行符 保证显示正常
			if (StrLine[strlen(StrLine) - 1] == '\n')
			{
				StrLine[strlen(StrLine) - 1] = '\0';
			}
			// 文件 内容为空 跳过
			char* temp = strtok(StrLine, " ");// 取学号
			char* temp1 = strtok(NULL, " ");// 取作业编号
			char* temp2 = strtok(NULL, " ");// 取成绩
			insertGradeInfo(header, createGradeInfo(strtol(temp, NULL, 10), strtol(temp1, NULL, 10), strtof(temp2, NULL)));
			gradecount++;
		}
		fclose(frGrade);
	}

	while (n != 3)
	{
		printf("请选择访问角色:\n");
		printf("1.教师  2.学生 3.退出\n");
		scanf("%d", &n);

		if (n == 1)
		{
			// 教师模块
			int n1 = 0;
			while (n1 != 4)
			{
				printf("请选择操作内容:\n");
				printf("1.学生信息管理  2.作业信息管理 3.作业成绩管理 4.返回\n");
				scanf("%d", &n1);
				if (n1 == 1)
				{
					int n2 = 0;
					while (n2 != 4)
					{
						printf("请选择操作内容:\n");
						printf("1.增加学生信息  2.修改学生信息 3.查询学生信息 4.返回\n");
						scanf("%d", &n2);

						if (n2 == 1)
						{
							addStuInfo(stu, stucount);
							// 新增后 学生记录数加1
							stucount++;
						}
						else if (n2 == 2)
						{
							updStuInfo(stu, stucount);
						}
						else if (n2 == 3)
						{
							qryStuInfo(stu, stucount);
						}
					}
				}
				else if (n1 == 2)
				{
					int n3 = 0;
					while (n3 != 5)
					{
						printf("请选择操作内容:\n");
						printf("1.增加作业信息  2.修改作业信息 3.查询作业信息  4.删除作业信息 5.返回\n");
						scanf("%d", &n3);

						if (n3 == 1)
						{
							addWorkInfo(work, workcount);

							// 创建作业时 更新所有学生该作业成绩链表 默认成绩为0
							for (int i = 0; i < stucount; i++)
							{
								insertGradeInfo(header, createGradeInfo(stu[i].stuid, work[workcount].worksno, 0));
							}

							// 新增后 作业记录数加1
							workcount++;
						}
						else if (n3 == 2)
						{
							updWorkInfo(work, workcount);
						}
						else if (n3 == 3)
						{
							qryWorkInfo(work, workcount);
						}
						else if (n3 == 4)
						{
							long worksno;
							printf("请输入要删除的作业编号:\n");
							scanf("%d", &worksno);
							int delRow = -1;
							for (int i = 0; i < workcount; i++)
							{
								if (worksno == work[i].worksno)
								{
									// 找到后并记录当前数据的下标(索引)
									delRow = i;
									break;
								}
							}

							// 根据索引的判断,如果你要删除的数的下标和所给定索引的初值相同,那么肯定就是没找到。
							if (delRow == -1)
							{
								printf("没有找到该作业!\n");
							}
							else
							{
								// 如果找到了,建立一个循环并且从下标开始,数组中的元素后面一个覆盖前面一个,且数组长度 - 1
								for (int i = delRow; i < workcount - 1; i++)
								{
									work[i] = work[i + 1];
								}

								// 删除成功后 作业记录数减1
								workcount--;

								// 删除成功后 清除作业成绩单链表该作业信息 并释放内存
								struct list_node *p, *q, *s;
								p = header;
								q = header->next;
								while (q) {
									if (q->worksno == worksno)
									{
										p->next = q->next;
										s = q;
										q = q->next;
										free(s);
									}
									else {
										p = p->next;
										q = q->next;
									}
								}
							}
						}
					}
				}
				else if (n1 == 3)
				{
					int n4 = 0;
					while (n4 != 8)
					{
						printf("请选择操作内容:\n");
						printf("1.录入成绩  2.修改成绩 3.查看所有成绩 4.根据作业编号查看所有成绩 5.根据作业编号查看没有成绩学生信息 \n");
						printf("6.查看作业平均分 7.根据作业编号查看所有成绩(降序) 8.返回\n");
						scanf("%d", &n4);

						if (n4 == 1)
						{
							updGrade(header);
						}
						else if (n4 == 2)
						{
							updGrade(header);
						}
						else if (n4 == 3)
						{
							showAllGrade(header);
						}
						else if (n4 == 4)
						{
							showAllGradeByWorksno(header);
						}
						else if (n4 == 5)
						{
							showAllGradeByWorksnoWithNoGrade(header);
						}
						else if (n4 == 6)
						{
							showAvgGrade(header, work, stucount);
						}
						else if (n4 == 7)
						{
							showAllGradeByWorksnoDesc(header, stucount);
						}
					}
				}
			}

		}
		else if (n == 2)
		{
			printf("请输入学号:\n");
			scanf("%d", &stuid);
			// 学生模块
			int n5 = 0;
			while (n5 != 4)
			{
				printf("请选择操作内容:\n");
				printf("1.查看所有成绩信息  2.查看第N次作业信息 3.查看作业总分及平均分 4.返回\n");
				scanf("%d", &n5);

				if (n5 == 1)
				{
					//获取当前的位置 
					struct list_node *p = header;
					printf("学号\t作业编号\t作业成绩\n");
					//如果当前位置的下一个节点不为空 
					while (p->next)
					{
						p = p->next;

						if (p->stuid == stuid)
						{
							printf("%d\t%d\t\t%.2f\n", p->stuid, p->worksno, p->grade);
						}
					}
				}
				else if (n5 == 2)
				{
					long count;
					printf("请输入第几次:\n");
					scanf("%d", &count);

					int i = 0;
					//获取当前的位置 
					struct list_node *p = header;
					printf("学号\t作业编号\t作业成绩\n");
					//如果当前位置的下一个节点不为空 
					while (p->next)
					{
						p = p->next;

						if (p->stuid == stuid)
						{
							i++;
							if (i == count)
							{
								printf("%d\t%d\t\t%.2f\n", p->stuid, p->worksno, p->grade);
								break;
							}
						}
					}
				}
				else if (n5 == 3)
				{
					float sum = 0;
					struct list_node *p = header;
					//如果当前位置的下一个节点不为空 
					while (p->next)
					{
						p = p->next;
						if (p->stuid == stuid)
						{
							sum += p->grade;
						}
					}

					printf("总分\t\t平均分\n");
					printf("%.2f\t%.2f\n", sum, sum / workcount);
				}
			}
		}
	}

	// 保存学生信息
	FILE *fwStu = fopen("stuinfo.txt", "w");
	if (fwStu != NULL)
	{
		char buffer[20];
		for (int i = 0; i < stucount; i++)
		{
			fputs(ltoa(stu[i].stuid, buffer, 10), fwStu);
			fputs(" ", fwStu);
			fputs(stu[i].stuname, fwStu);

			// 最后一行记录 末尾不能存\n 不然会多空行
			if (i != stucount - 1)
			{
				fputs("\n", fwStu);
			}
		}
		fclose(fwStu);
	}

	// 保存作业信息
	FILE *fwWork = fopen("work.txt", "w");
	if (fwWork != NULL)
	{
		char buffer[20];
		for (int i = 0; i < workcount; i++)
		{
			fputs(ltoa(work[i].worksno, buffer, 10), fwWork);
			fputs(" ", fwWork);
			fputs(work[i].workdata, fwWork);

			// 最后一行记录 末尾不能存\n 不然会多空行
			if (i != workcount - 1)
			{
				fputs("\n", fwWork);
			}
		}
		fclose(fwWork);
	}

	// 保存成绩信息
	FILE *fwGrade = fopen("grade.txt", "w");
	if (fwGrade != NULL)
	{
		char buffer[20];
		struct list_node *p = header;
		while (p->next)
		{
			p = p->next;

			fputs(ltoa(p->stuid, buffer, 10), fwGrade);
			fputs(" ", fwGrade);
			fputs(ltoa(p->worksno, buffer, 10), fwGrade);
			fputs(" ", fwGrade);
			sprintf(buffer, "%.2f ", p->grade);
			fputs(buffer, fwGrade);

			// 最后一行记录 末尾不能存\n 不然会多空行
			if (p->next != NULL)
			{
				fputs("\n", fwGrade);
			}
		}

		fclose(fwGrade);
	}

	// 释放单链表
	Free_list(header);

	system("pause");
	return 0;
}

学习、交流 qq8660673 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值