欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言实现学生管理系统

程序员文章站 2022-05-06 09:40:15
...

C语言实现-学生管理系统

程序员的必经之路吧,学生管理系统。在制作过程中体会到了编写一个具体可用的软件而要做的工作,无论是编写前的准备,还是编写过程中每个细节的处理,都让我理解了这份工作是个什么样子。程序并不是抬手就来,一个软件要完整,同时还要将每个功能部分区分开,所以在编写之前一定要先规划清楚,这是一项工程。逻辑要严密,编程完全就是对逻辑思维的考验,大大小小的函数、语句都是靠逻辑连接起来的。基础知识要扎实,在我现在这个阶段,经常会遇到为干掉bug而苦思半天,在逻辑上寻觅没有出口,其实只是对用法不了解,上课时认为那种不太常考的东西不用太费心,只要把主要的知识记住就行,但事实上每个知识点都是有用的,接下来使用数组,动态数组,单向链表,文件操作等来实现C语言:学生管理系统。
这里使用的是VS2019,如果你使用的是CodeBlocks或DEV C++等请先把第一行注释掉。

对学生信息管理系统,要求完成以下基本任务:

1.改写程序为良好程序风格(文档注释,函数注释,语句注释)。
2.将功能补充完全(基于文件处理,完成刷新和保存功能)。
3.将学生信息改为更好的数据组织,而非离散形式(结构体)。
4.可将程序中的不足(如数据验证)等根据自己的能力与理解完成。
5.用使用C语言做一个学生信息管理系统,我的想法是先把需要的一些变量封装在结构体中,然后结合以前学过的数据结构知识(链表),做一些增删查改的操作,并将其保存在文件中。

群内有各种学习资料,欢迎大家一起来学习哦~
如果大家遇到什么问题也欢迎大家进群讨论哦~

qq群:759252814

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include<conio.h>

/**********************保存学生信息的结构体**********************/

typedef struct Student       //使用typedef为struct Student起别名为XIN
{
	char Student_id[30];     //学生编号
	char name[30];           //学生姓名
	int age;                 //学生年龄
	char sex[5];             //学生性别
	float Ascore;            //语文分数
	float Bscore;            //数学分数 
	float Cscore;            //英语分数
	float Count;             //三科总分
	struct Student* next;    //指向下一个地址
}XIN;

int color(int n);										 //字体颜色 
void gotoxy(int x, int y);								 //字体位置 
void Aframe();											 //边框 1号 蓝 紫
void Bframe();										     //边框 2号 蓝 红
void Main_interface();                                   //主界面
void Write_in();                                         //输入信息
void Output();                                           //输出信息
void Lookup();                                           //查找信息
void Sort();                                             //成绩排序
void Delete();                                           //删除信息

/**********************主界面**********************/

void Main_interface()
{
	system("cls");                           //每次调用 Main_interface() 函数时调用一次 system("cls") 进行清屏函数
	gotoxy(19, 2);                           //字符打印位置,如最左上角的坐标为 0.0
	color(13);                               //接下来打印的字体颜色如:10为绿色,13为紫色
	printf("===========学 生 管 理 系 统 菜 单===========\n");
	Aframe();                   //使用边框 1号 
	color(2);
	gotoxy(60, 1);
	printf("欢迎您的使用! ^_^");
	color(14);
	gotoxy(24, 6);
	color(9);
	printf("=======请选择功能列表=======\n");
	color(10);
	gotoxy(12, 8);
	printf("1.添加学生信息\n");
	gotoxy(12, 10);
	color(14);
	printf("2.查看学生信息n");
	gotoxy(12, 12);
	color(13);
	printf("3.查找学生信息\n");
	gotoxy(12, 14);
	color(11);
	printf("4.按成绩排序\n");
	gotoxy(12, 16);
	color(9);
	printf("5.删除学生信息\n");
	color(7);
	gotoxy(12, 18);
	printf("6.退出程序");

label:                       //标签 用于goto语句
	gotoxy(26, 22);
	color(14);
	printf("本程序会自动读取 请选择[ ]\b\b");
	char ch;                 //存放输入的字符
	ch = _getch();           //读取键盘输入的一个字符不显示 \不回显函数
	
	putchar(ch);
	switch (ch)
	{
		case '1':system("cls"); Write_in(); 	    break;      //system("cls"); 清屏函数
		case '2':system("cls"); Output();  		break;
		case '3':system("cls"); Lookup(); 		break;
		case '4':system("cls"); Sort();         break;
		case '5':Delete();   					break;
		case '6':system("cls"); exit(0);   		break;      //exit(0):结束程序返回值为0
		case 27 :system("cls"); exit(0);   		break;      //27为Esc的ASCLL编号
		default:goto label;                     break;      //goto label:无条件跳转至标签 label 处
	};
}
int main(void)
{
	Main_interface();
	return 0;
}

/**********************输入信息**********************/

void Write_in()
{
	FILE* fp;                 //文件指针
	XIN temp;                 //为当前输入内容

	//打开文件并判断是否打开成功或创建成功,ab+是以二进制追加的方式打开,如果找不到该文件则创建一个studentA.datd文件来储存信息,如果也创建失败则报错并结束程序
	if ((fp = fopen("studentA.datd", "ab+")) == NULL)    
	{
		printf("创建文件或添加信息失败! 错误代码:0x001");
		exit(1);
	}
	int count = 0;                  //当前输入的学生人数
	while (TRUE)                    //一直输入信息直到break跳出
	{
		system("cls");
		count++;
		gotoxy(17, 2);
		color(13);
		printf("===========添 加 学 生 信 息 界 面===========\n");
		Aframe();
		gotoxy(10, 6);
		color(10);
		printf("请输入第%d位学生的学号:", count);
		scanf("%s", temp.Student_id);
		if (strcmp(temp.Student_id, "-1") == 0)                 //当学号输入为-1时退出输入,把信息储存到文件并关闭文件
		{
			break;
		}
		gotoxy(10, 8);
		printf("请输入第%d位学生的名字:", count);
		scanf("%s", temp.name);
		gotoxy(10, 10);
		printf("请输入第%d位学生的性别:", count);
		scanf("%s", temp.sex);
		gotoxy(10, 12);
		printf("请输入第%d位学生的年龄:", count);
		scanf("%d", &temp.age);
		gotoxy(10, 14);
		printf("请输入第%d位学生的语文成绩:", count);
		scanf("%f", &temp.Ascore);
		gotoxy(10, 16);
		printf("请输入第%d位学生的数学成绩:", count);
		scanf("%f", &temp.Bscore);
		gotoxy(10, 18);
		printf("请输入第%d位学生的英语成绩:", count);
		scanf("%f", &temp.Cscore);
		temp.Count = temp.Ascore + temp.Bscore + temp.Cscore;
		fwrite(&temp, sizeof(XIN), 1, fp);
		gotoxy(26, 22);
		color(14);
		printf("是否要继续'y'或者'n'[ ]\b\b");
		char ch;
	label:                                 //判断 
		ch = _getch();
		if (ch == 'y' || ch == 'Y')
		{
			printf("\n");
		}
		else if (ch == 'n' || ch == 'N')
		{
			fclose(fp);
			Main_interface();
		}
		else
			goto label;
	}
	fclose(fp);
}

/**********************输出信息**********************/
void Output()
{
	system("cls");
	XIN temp;
	FILE* fp;
	char ch;
	//打开文件并判断是否打开成功,rb是以二进制只读的方式打开,如果找不到则报错并结束程序
	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x002");
		exit(1);
	}
	int i = 1;
	int count = 0;                        //判断是否存文件中读取信息
	fread(&temp, sizeof(XIN), 1, fp);
	while (!feof(fp))                     //feof用检测流上的文件结束符,其返回值有两种情况:如果遇到文件结束,函数值为非零值,否则函数值为0
	{
		system("cls");
		count = 1;
		Aframe();
		gotoxy(19, 2);
		color(13);
		printf("=========== 查 看 信 息 界 面===========\n");
		gotoxy(18, 9);
		color(13);
		printf("学号为:%s\n", temp.Student_id);
		gotoxy(48, 9);
		color(10);
		printf("名字为:%s\n", temp.name);
		gotoxy(18, 12);
		color(9);
		printf("性别为:%s\n", temp.sex);
		gotoxy(48, 12);
		color(13);
		printf("年龄为:%d\n", temp.age);
		gotoxy(18, 15);
		color(13);
		printf("语文为:%.1f\n", temp.Ascore);
		gotoxy(48, 15);
		color(10);
		printf("数学为:%.1f\n", temp.Bscore);
		gotoxy(18, 18);
		color(10);
		printf("英语为:%.1f\n", temp.Cscore);
		gotoxy(48, 18);
		color(9);
		printf("总分为:%.1f\n", temp.Count);
		gotoxy(30, 6);
		color(14);
		printf("第%d位学生的信息", i);
		gotoxy(26, 22);
		color(14);
		printf("本程序会自动读取 请选择[ ]\b\b");
	label:
		ch = _getch();
		if (ch == 80)                 //下键的ASCII编码
			i++;
		else if (ch == 27)
			Main_interface();        //Esc的ASCII编码
		else if (ch == 72)           //上键的ASCII编码
		{
			fseek(fp, -192L, SEEK_CUR); //文件指针在当前位置向后移动192个字节,结构体 struct Student 所占的字节为:96
			i--;
		}
		else
			goto label;
		fread(&temp, sizeof(XIN), 1, fp);
	}
	fclose(fp);
	if (count == 0)                      //如果为0则说明未从文件中读取出内容文件为空
	{
		Bframe();
		gotoxy(19, 2);
		color(13);
		printf("=========== 查 看 信 息 界 面===========\n");
		color(12);
		gotoxy(25, 8);
		printf("没 有 添 加 任 何 信 息 !");
		gotoxy(23, 15);
		color(13);
		printf("按Esc键返回主页面回车键添加 [ ]\b\b");
		char ch;
	label2:
		ch = _getch();
		if (ch == 27)
			Main_interface();
		else if (ch == 13)    //空格键的ASCII编码
			Write_in();
		else
			goto label2;
	}
	else
	{
		gotoxy(24, 22);
		color(10);
		printf("请按Esc返回本程序会自动读取 [ ]\b\b");                          //结束返回                          
	label3:
		ch = _getch();
		if (ch == 27)
			Main_interface();
		else
			goto label3;
	}
}

/**********************查找信息**********************/
void Lookup()
{
	FILE* fp;
	XIN temp;
	char Name[30];
	gotoxy(15, 2);
	color(11);
	printf("=========== 查 找 学 生 信 息 界 面===========\n");
	Bframe();
	color(14);
	gotoxy(20, 8);
	printf("请输入需要找查的学生名字:");
	scanf("%s", Name);
	gotoxy(27, 15);
	color(13);
	printf("按Esc键返回主页面[ ]\b\b");

	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x003");
		exit(1);
	}
	int Count = 0;
	fread(&temp, sizeof(XIN), 1, fp);
	while (!feof(fp))
	{
		system("cls");
		if (strcmp(temp.name, Name) == 0)                         //从文件中读取如果匹配则输出
		{
			Count = 1;
			Aframe();
			gotoxy(15, 2);
			color(13);
			printf("=========== 查 找 学 生 信 息 界 面===========\n");
			gotoxy(18, 9);
			color(13);
			printf("学号为:%s\n", temp.Student_id);
			gotoxy(48, 9);
			color(10);
			printf("名字为:%s\n", temp.name);
			gotoxy(18, 12);
			color(9);
			printf("性别为:%s\n", temp.sex);
			gotoxy(48, 12);
			color(13);
			printf("年龄为:%d\n", temp.age);
			gotoxy(18, 15);
			color(13);
			printf("语文为:%.1f\n", temp.Ascore);
			gotoxy(48, 15);
			color(10);
			printf("数学为:%.1f\n", temp.Bscore);
			gotoxy(18, 18);
			color(10);
			printf("英语为:%.1f\n", temp.Cscore);
			gotoxy(48, 18);
			color(9);
			printf("总分为:%.1f\n", temp.Count);
			gotoxy(30, 6);
			color(14);
			printf("教师“%s”的信息如下", Name);
			gotoxy(30, 22);
			color(14);
			printf("按Esc键退出 [ ]\b\b");
			char ch;
		label:
			ch = _getch();
			if (ch == 27)
			{
				Main_interface();
			}
			else
			{
				goto label;
			}
			break;
		}
		fread(&temp, sizeof(XIN), 1, fp);
	}
	if (Count == 0)
	{
		system("cls");
		gotoxy(15, 2);
		color(11);
		printf("=========== 查 找 学 生 信 息 界 面===========\n");
		Bframe();
		color(12);
		gotoxy(25, 8);
		//printf("                                               ");
		gotoxy(25, 8);
		printf("没有找到该学生的任何信息!");
		gotoxy(27, 13);
		color(13);
		printf("按Esc键返回主页面[ ]\b\b");
		char ch2;
	label2:
		ch2 = _getch();
		if (ch2 == 27)
			Main_interface();
		else
			goto label2;
	}
}

/**********************成绩排序**********************/
void Sort()
{
	FILE* fp;
	XIN temp;
	int Acount = 0;
	int Bcount = 0;
	int NUMBER = 0;        //通过循环统计有多少位学生,并以NUMBER的值创建一个动态数组
	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x004");
		exit(1);
	}
	fread(&temp, sizeof(XIN), 1, fp);
	while (!feof(fp))                     //feof用检测流上的文件结束符,其返回值有两种情况:如果遇到文件结束,函数值为非零值,否则函数值为0
	{
		Acount = 1;
		NUMBER++;
		fread(&temp, sizeof(XIN), 1, fp);
	}
	fclose(fp);

	if (Acount == 0)                      //用于判断文件中是否有信息,如果没有则提示
	{
		Bframe();                         //边框二号
		gotoxy(19, 2);
		color(13);
		printf("=========== 按 成 绩 排 序 界 面 ===========\n");
		color(12);
		gotoxy(25, 8);
		printf("没 有 添 加 任 何 信 息 !");
		gotoxy(23, 14);
		color(13);
		printf("按Esc键返回主页面回车键添加 [ ]\b\b");
		char ch;
	label2:
		ch = _getch();
		if (ch == 27)
			Main_interface();
		else if (ch == 13)    //空格键的ASCII编码
			Write_in();
		else
			goto label2;
	}

	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x005");
		exit(1);
	}
	XIN* information;
	information = (XIN*)malloc(sizeof(XIN) * NUMBER);
	int i = 0;                                //用于动态数组的下标
	fread(&temp, sizeof(XIN), 1, fp);
	while (!feof(fp))                     //feof用检测流上的文件结束符,其返回值有两种情况:如果遇到文件结束,函数值为非零值,否则函数值为0
	{
		strcpy(information[i].Student_id, temp.Student_id);  ////把读取出来的内容赋值给结构体数组information
		strcpy(information[i].name, temp.name);
		strcpy(information[i].sex, temp.sex);
		information[i].age = temp.age;
		information[i].Ascore = temp.Ascore;
		information[i].Bscore = temp.Bscore;
		information[i].Cscore = temp.Cscore;
		information[i].Count = temp.Count;
		fread(&temp, sizeof(XIN), 1, fp);
		i++;
	}
	fclose(fp);
	XIN Temp;
	for (int i = 0; i < NUMBER; i++)
	{
		for (int j = i + 1; j < NUMBER; j++)
		{
			if (information[i].Count < information[j].Count)
			{
				Temp = information[i];
				information[i] = information[j];
				information[j] = Temp;
			}
		}
	}
	for (int i = 0; i < NUMBER; i++)
	{
		system("cls");
		Aframe();
		gotoxy(19, 2);
		color(13);
		printf("=========== 查 看 信 息 界 面===========\n");
		gotoxy(18, 9);
		color(13);
		printf("学号为:%s\n", information[i].Student_id);
		gotoxy(48, 9);
		color(10);
		printf("名字为:%s\n", information[i].name);
		gotoxy(18, 12);
		color(9);
		printf("性别为:%s\n", information[i].sex);
		gotoxy(48, 12);
		color(13);
		printf("年龄为:%d\n", information[i].age);
		gotoxy(18, 15);
		color(13);
		printf("语文为:%.1f\n", information[i].Ascore);
		gotoxy(48, 15);
		color(10);
		printf("数学为:%.1f\n", information[i].Bscore);
		gotoxy(18, 18);
		color(10);
		printf("英语为:%.1f\n", information[i].Cscore);
		gotoxy(48, 18);
		color(9);
		printf("总分为:%.1f\n", information[i].Count);
		gotoxy(30, 6);
		color(14);
		printf("第%d位学生的信息", i + 1);
		gotoxy(26, 22);
		color(14);
		printf("本程序会自动读取 请选择[ ]\b\b");
		char ch;
	label:
		ch = _getch();
		if (ch == 80)                 //下键的ASCII编码,当按下键时什么也不做等待for循环继续
		{

		}
		else if (ch == 27)
			Main_interface();        //Esc的ASCII编码
		else if (ch == 72)           //上键的ASCII编码
		{
			i -= 2;
		}
		else
			goto label;
	}
	char ch;
	gotoxy(24, 22);
	color(10);
	printf("请按Esc返回本程序会自动读取 [ ]\b\b");                          //结束返回                          
label3:
	ch = _getch();
	if (ch == 27)
		Main_interface();
	else
		goto label3;
}

/**********************删除信息**********************/
void Delete()
{
	system("cls");
	FILE* fp;
	XIN temp;
	XIN* h, * p, * q;      //*h代表链表的头指针,*p代表链表上一个的指针.*q代表当前指针
	int Const = 0;
	char Name[30];
	gotoxy(15, 2);
	color(11);
	printf("=========== 删 除 学 生 信 息 界 面===========\n");
	Bframe();
	color(14);
	gotoxy(20, 8);
	printf("请输入需要删除的学生名字:");
	scanf("%s", Name);
	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x006");
		exit(1);
	}
	h = p = (XIN*)malloc(sizeof(XIN));
	fread(&temp, sizeof(XIN), 1, fp);
	while (!feof(fp))                     //feof用检测流上的文件结束符,其返回值有两种情况:如果遇到文件结束,函数值为非零值,否则函数值为0
	{
		if (strcmp(temp.name, Name) == 0)
		{
			Const = 1;
			fread(&temp, sizeof(XIN), 1, fp);
			continue;
		}
		else
		{
			q = (XIN*)malloc(sizeof(XIN));             //把读取出来的内容赋值给q指向的结构体
			strcpy(q->Student_id, temp.Student_id);
			strcpy(q->name, temp.name);
			strcpy(q->sex, temp.sex);
			q->age = temp.age;
			q->Ascore = temp.Ascore;
			q->Bscore = temp.Bscore;
			q->Cscore = temp.Cscore;
			q->Count = temp.Count;
			p->next = q;
			p = q;                                    
			fread(&temp, sizeof(XIN), 1, fp);
		}
	}
	p->next = NULL;                                    

	if ((fp = fopen("studentA.datd", "rb")) == NULL)
	{
		printf("打开文件失败,请确定是否创建了该文件! 错误代码:0x006");
		exit(1);
	}

	p = h->next;                             //使p指向链表的第一个节点
	while (p->next != NULL)
	{
		fwrite(p, sizeof(XIN), 1, fp);
		p = p->next;
	}
	fclose(fp);
	if (Const == 1)
	{
		system("cls");
		gotoxy(15, 2);
		color(13);
		printf("=========== 删 除 学 生 信 息 界 面===========\n");
		Bframe();
		color(10);
		gotoxy(31, 8);
		printf("删 除 成 功 !");
		gotoxy(27, 14);
		color(13);
		printf("按Esc键返回主页面[ ]\b\b");
		char ch;
	labelA:
		ch = _getch();
		if (ch == 27)
			Main_interface();
		else
			goto labelA;
	}
	else
	{
		system("cls");
		gotoxy(15, 2);
		color(13);
		printf("=========== 删 除 学 生 信 息 界 面===========\n");
		Bframe();
		color(12);
		gotoxy(25, 8);
		printf("没有找到该学生的信息!");
		gotoxy(27, 14);
		color(13);
		printf("按Esc键返回主页面[ ]\b\b");
		char ch;
	labelB:
		ch = _getch();
		if (ch == 27)
			Main_interface();
		else
			goto labelB;
	}
}
void Aframe()                                    //彩色框架 1号  蓝 紫  中偏大 
{
	int i, j;
	static int b, n;
	for (i = 8; i <= 69; i++)
	{
		b = 2, n = 2;
		for (j = 4; j <= 20; j++)
		{
			b++;
			n++;
			if (i == 8 || i == 69)
			{
				if (b % 2 == 0)
				{
					color(13);
				}
				else if (b % 1 == 0)
				{
					color(9);
				}
				gotoxy(i, j);
				printf("|");
			}
			if (j == 4 || j == 20)
			{

				if (b % 2 == 0)
				{
					color(13);
				}
				else if (b % 1 == 0)
				{
					color(9);
				}
				gotoxy(i, j);
				printf("=");
			}

		}
	}
}
void Bframe()                          //彩色边框 2 蓝 红 偏小 
{
	int i, j;
	static int b, n;
	for (i = 8; i <= 69; i++)
	{
		b = 2, n = 2;
		for (j = 4; j <= 12; j++)
		{
			b++;
			n++;
			if (i == 8 || i == 69)
			{
				if (b % 2 == 0)
				{
					color(12);
				}
				else if (b % 1 == 0)
				{
					color(9);
				}
				gotoxy(i, j);
				printf("|");
			}
			if (j == 4 || j == 12)
			{

				if (b % 2 == 0)
				{
					color(12);
				}
				else if (b % 1 == 0)
				{
					color(9);
				}
				gotoxy(i, j);
				printf("=");
			}

		}
	}
}
int color(int n)             //颜色 ----------------------- 
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n);
	return 0;
}
void gotoxy(int x, int y)    //位置 --------------------------
{
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}


}


运行结果如图:
C语言实现学生管理系统