学生管理系统1.0(C语言)
题目: 设计一个学生的管理系统,需要的功能有,添加、修改、删除、查找及按成绩进行从低到高的排序等功能。
首先,确定程序的主要思路,一个学生的个人信息包括:名字、ID卡号、性别、成绩和年龄,这些信息可以用构造体进行定义,再用一个数组来存放这些学生信息,通过管理这个数组对学生的信息进行增、删、改、查等基本操作。
如下便是建立的学生个人信息的构造体,其中char name[NAME_MAX];是一个字符串数组,其中NAME_MAX我在宏定义了:#define NAME_MAX 20
typedef struct Student
{
char name[NAME_MAX];//学生姓名
int identify;//学生个人ID
short age;//学生个人年龄
char sex;//学生个人性别
float grade;//学生个人成绩
}STUDENT;//将struct Student 变量重命名为 STUDENT
这样我们的个人学生的信息构造体就建立好了,但是一个学生管理系统,不仅仅只有一个学生的个人信息,我们需要建立一个数组来进行学生信息的管理
typedef struct Class
{
STUDENT *data;//学生总共的数据
int size;//学生的编号
int space;//存放学生数据的空间
}CLASS;
这样就建立了我们的第二个构造体类型,它包含一个STUDENT类型的数组,学生的编号以及存放学生数据的空间大小。空间大小是未知的,我们并不知道一共有多少个学生。当然也可以直接定义一个比较大的空间来存放学生信息,但是空间的浪费比较严重,如果发生学生的人员信息超过了我们自己定义的空间大小,我们还需要对数据进行更改。所以,这里我们讲的是关于空间动态增长的方法,这个方法会在下面进行细说。
int main()
{
CLASS system;//定义CLASS变量,用来存放学生的信息
int num = 0;//循环开关
initialize(&system,10);
do
{
interface();
num=input_order();
choose(&system,num);
}while(num!=0);
return 0;
}
首先在主函数里面定义一个GLASS类型的变量system,这个变量定义栈区,并且没有被初始化,那么首先我们要将变量进行初始化,使结构体里的内容全部为0。那么怎么对这个构造体进行初始化赋值呢,首先需要在堆区开辟一个空间,先让这个空间开辟10个CLASS类型的大小,采用calloc函数进行开辟空间及初始化赋值。参数为变量system的地址和想要开辟空间的大小。
在main函数里我的循环体采用的是do while循环,循环开关为num,当输入num=0时,退出循环,结束程序。
//CLASS system 的初始化
void initialize(CLASS *system,int space)
{
if ( system == NULL)
{
printf("error in data \n");
return;
}
system->data = (STUDENT *)calloc(sizeof(STUDENT),space);
system->size = 1;
system->space = space;
//printf("%d\n",system->space);
}
当system变量作为参数传递的时候,首先要先对它的指向进行判断,防止发生段错误,因为NULL是不允许修改的,所以判断system的地址不指向NULL,再进行接下来的操作,每个传入system的函数,尽量都要先判断一下它的指向。
把在堆区开扩的10个STUDENT类型大小的空间赋值给system->data,这样在堆区我们就开好了10个存放学生个人信息的空间,并且将size初始化为1,因为size变量表示的是学生的序号,方便我们下面的查询及删除函数的定义,因为学生序号一般以1为开始,为了方便,初始化为1。然后把开辟的空间大小赋值给system->space,记录下我们开辟的空间大小。
//界面函数
void interface()
{
printf("___________________学生界面管理系统1.0__________________\n");
putchar(10);
printf("0.退出学生界面管理系统\n");
printf("1.添加学生的个人信息\n");
printf("2.删除学生的个人信息\n");
printf("3.修改学生的个人信息\n");
printf("4.查找学生的个人信息\n");
printf("5.按照成绩对学生的个人信息进行排序\n");
putchar(10);
printf("________________________________________________________\n");
}
初始的界面函数
int input_order()
{
int num=0;
printf("请输入您想要执行的操作序号\n");
scanf("%d",&num);
return num;
}
输入函数,输入函数的返回值,在main函数里赋值给一个num的变量,以这个输入数值来控制这个循环体系。
//switch 函数进行选择
void choose (CLASS *system,int num)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
switch (num)
{
case 0:
printf("您已退出学生管理操作系统,感谢您的使用\n");
return;
case 1:
ADD_system(system);//添加学生个人信息函数i
break;
case 2:
DEL_system(system);//删除学生的个人信息函数
break;
case 3:
AMEND_system(system);//修改学生的个人信息函数
break;
case 4:
find_system(system);
break;
case 5:
SORT_system(system);
break;
default:
printf("你的输入有误,请重新输入\n");
num = 1;
}
}
采用switch函数,根据输入的num的不同,进入到不同的函数里面,进行操作。其中,当输入的数字不在0~5的范围内,我们需要让程序重新进入循环,为了避免出错,我这里对num重新进行赋值。
//添加学生个人信息
void ADD_system(CLASS *system)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
printf("请输入学生的姓名\n");
scanf("%s",system->data[(system->size)-1].name);
getchar();
printf("请输入学生的年龄\n");
scanf("%hd",&system->data[(system->size)-1].age);
getchar();
printf("请输入学生的ID\n");
scanf("%d",&system->data[(system->size)-1].identify);
getchar();
printf("请输入学生的成绩\n");
scanf("%f",&system->data[(system->size)-1].grade);
getchar();
printf("请输入学生的性别\n");
scanf("%c",&system->data[(system->size)-1].sex);
system->size++;
if (system->size==system->space)
{
newspace(system);//当人员把初始开辟的空间占满后,重新开辟空间
}
}
//重新开辟新的空间
void newspace(CLASS *system)
{
if (system==NULL)
{
printf("error in data\n");
return;
}
int spatial = (system->space)*2;
STUDENT *temp = (STUDENT *)realloc(system->data,sizeof(STUDENT)*spatial);
system->data = temp;
system->space = spatial;
}
在这几个操作的函数里面,比较麻烦是添加学生信息的这个函数,因为当你输入10个学生信息的时候,编译器会提醒你,你这个堆区申请的空间已经存储满了,会给你报一个段错误,那么为了保证有足够的空间去存放我们的学生个人信息,我们需要对这个堆区的空间进行扩存,当录入学生的个数等于我们所开辟的空间时,我们将采用realloc函数来重新分配空间的大小,那么我们要再开辟多大的大小空间才能保证内存空间不会太过浪费呢?
我采用的是将空间扩成原来的2倍的方法,等到这个新开辟的空间又存放满了,再开辟新空间的2倍,这样在及节省了内存空间,又不会经常去扩容空间,发生数据丢失的情况。
因为原先我们采用calloc函数在堆区开辟了10个STUDENT类型的空间,重新分配的话,我们可以使用realloc函数进行空间的重分配。
首先定义一个STUDENT类型的数组,把新开辟的空间地址给这个temp,然后把在这个地址给到system->date,注意尽量不要直接赋值给system->data。
剩下的删除信息、查找信息、修改信息、排序成绩就比较简单了,这里面值得注意的就是我们size初始化的数值为1,它所对应的system->data[size-1]这个数组的元素。
下面是代码的全部信息:
#include <stdio.h>
#include <stdlib.h>
#define NAME_MAX 20
typedef struct Student
{
char name[NAME_MAX];//学生姓名
int identify;//学生个人ID
short age;//学生个人年龄
char sex;//学生个人性别
float grade;//学生个人成绩
}STUDENT;//将struct Student 变量重命名为 STUDENT
typedef struct Class
{
STUDENT *data;//学生总共的数据
int size;//学生的编号
int space;//存放学生数据的空间
}CLASS;//将struct Class的变量名重命名为CLASS
void interface();//界面函数
void initialize(CLASS *system,int space);//函数(变量的初始化)
int input_order();//输入指令函数
void choose(CLASS *system,int num);//选择操作指令函数
void ADD_system(CLASS *system);//添加学生的个人信息
void newspace(CLASS *system);//当添加学生信息和空间大小一样时,开辟新的空间
void DEL_system(CLASS *system);//删除学生的个人信息
void AMEND_system(CLASS *system);//修改学生的个人信息
void find_system(CLASS *system);//查找学生的个人信息
void SORT_system(CLASS *system);
int main()
{
CLASS system;//定义CLASS变量,用来存放学生的信息
int num = 0;//循环开关
initialize(&system,10);
do
{
interface();
num=input_order();
choose(&system,num);
}while(num!=0);
return 0;
}
//CLASS system 的初始化
void initialize(CLASS *system,int space)
{
if ( system == NULL)
{
printf("error in data \n");
return;
}
system->data = (STUDENT *)calloc(sizeof(STUDENT),space);
system->size = 1;
system->space = space;
//printf("%d\n",system->space);
}
//界面函数
void interface()
{
printf("___________________学生界面管理系统1.0__________________\n");
putchar(10);
printf("0.退出学生界面管理系统\n");
printf("1.添加学生的个人信息\n");
printf("2.删除学生的个人信息\n");
printf("3.修改学生的个人信息\n");
printf("4.查找学生的个人信息\n");
printf("5.按照成绩对学生的个人信息进行排序\n");
putchar(10);
printf("________________________________________________________\n");
}
//输入函数
int input_order()
{
int num=0;
printf("请输入您想要执行的操作序号\n");
scanf("%d",&num);
return num;
}
//switch 函数进行选择
void choose (CLASS *system,int num)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
switch (num)
{
case 0:
printf("您已退出学生管理操作系统,感谢您的使用\n");
return;
case 1:
ADD_system(system);//添加学生个人信息函数i
break;
case 2:
DEL_system(system);//删除学生的个人信息函数
break;
case 3:
AMEND_system(system);//修改学生的个人信息函数
break;
case 4:
find_system(system);
break;
case 5:
SORT_system(system);
break;
default:
printf("你的输入有误,请重新输入\n");
num = 1;
}
}
//添加学生个人信息
void ADD_system(CLASS *system)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
printf("请输入学生的姓名\n");
scanf("%s",system->data[(system->size)-1].name);
getchar();
printf("请输入学生的年龄\n");
scanf("%hd",&system->data[(system->size)-1].age);
getchar();
printf("请输入学生的ID\n");
scanf("%d",&system->data[(system->size)-1].identify);
getchar();
printf("请输入学生的成绩\n");
scanf("%f",&system->data[(system->size)-1].grade);
getchar();
printf("请输入学生的性别\n");
scanf("%c",&system->data[(system->size)-1].sex);
system->size++;
if (system->size==system->space)
{
newspace(system);//当人员把初始开辟的空间占满后,重新开辟空间
}
}
//重新开辟新的空间
void newspace(CLASS *system)
{
if (system==NULL)
{
printf("error in data\n");
return;
}
int spatial = (system->space)*2;
STUDENT *temp = (STUDENT *)realloc(system->data,sizeof(STUDENT)*spatial);
system->data = temp;
system->space = spatial;
}
//删除学生的个人信息
void DEL_system(CLASS *system)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
int num = 0;
printf ("请输入要删除的学生序号\n");
scanf("%d",&num);
for (int i = 0; i <= system->size-num ;i++)
{
system->data[num-1+i]=system->data[num+i];
}
system->size--;
}
//修改学生的个人信息函数
void AMEND_system(CLASS *system)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
int num=0;
printf("请输入您想修改的学生序号\n");
scanf("%d",&num);
printf("请输入学生的姓名\n");
scanf("%s",system->data[(num)-1].name);
getchar();
printf("请输入学生的年龄\n");
scanf("%hd",&system->data[(num)-1].age);
getchar();
printf("请输入学生的ID\n");
scanf("%d",&system->data[(num)-1].identify);
getchar();
printf("请输入学生的成绩\n");
scanf("%f",&system->data[(num)-1].grade);
getchar();
printf("请输入学生的性别\n");
scanf("%c",&system->data[(num)-1].sex);
}
//查找学生的个人信息函数
void find_system(CLASS *system)
{
if (system == NULL)
{
printf("error in data\n");
return;
}
int num=0;
printf("请输入您想修改的学生序号\n");
scanf("%d",&num);
printf ("%d号 学生姓名:%s ,学生年龄:%hd ,学生ID:%d ,学生性别: %c ,学生成绩:%f\n",num, system->data[num-1].name,system->data[num-1].age,
system->data[num-1].identify,system->data[num-1].sex,system->data[num-1].grade);
}
//按成绩对学生进行排序
void SORT_system(CLASS *system)
{
if ( system == NULL)
{
printf("error in data\n");
return;
}
int i = 0;
int time = 0;
for (i=0;i<(system->size)-2;i++)
{
for (time = 0;time<(system->size)-2-i;time++)
{
if(system->data[time].grade>system->data[time+1].grade)
{
STUDENT temp = system->data[time];
system->data[time]=system->data[time+1];
system->data[time+1]=temp;
}
}
}
}
虽然代码能够完成程序,但是还是有不小的改良的空间,也就刚刚能实现基本的数据操作。如果你有什么更好的想法或者是建议,可以分享给我那就再好不过。
如果对这个代码有什么疑问,可以在下面留言告诉我,大家一起交流,一起进步。