学生管理系统目前分为“增添学生成绩”,“修改学生的成绩”,“删除学生的成绩”,“查找学生的成绩”,“对学生成绩进行排序,且弄出来全体学生的前三名”,“管理员系统”,“以及在开始的时候是否要选择读取文件”"打开文件",“保存文件”等操作。

管理员系统详细在另一篇文章

功能如下:

void manage(PStu headNode);                                        //进入管理员系统 
void notmanage();                                                  //学生系统(只含有查找等相关功能) 
void Login(char *useName,char *useWord,PStu headNode);             //管理员密码操作 
int isLogin(char *useName,char *useWord,PStu headNode);            //判断账号和密码是否错误 
void menu(PStu headNode);                                          //菜单(选择一)(保存的文件为try2.txt); 
void menu2();                                                      //菜单(选择二)(保存的文件为try2.txt) 
void savefile2(PStu headNode);                                     //与菜单二相结合的保存文件 
void add(PStu headNode);                                           //录入学生的成绩(头插和尾插)
void printfList(PStu headNode);                                    //输出学生的成绩 
void deleteNodeByAppion(PStu headNode ,char *num);                 //根据学号进行删除
void ideleteNodeByAppion(PStu headNode ,char *name);               //根据姓名进行删除 
PStu gaiNode(PStu headNode);                                       //修改相关的信息
int longNode(PStu headNode);                                       //求链表的长度 
PStu chaNode(PStu headNode,int t,int j);                           //查找学生的信息
PStu chaNode2(PStu headNode,char *num);                            //学生系统中借助学号进行一个自己各科成绩查询的函数 
void maopao(PStu headNode);                                        //根据总成绩(iscore)进行一个排序(冒泡排序)
void maopao3/*学生系统*/(PStu headNode);                           //学生系统的冒泡排序(返回前三名的地址) 
void maopao2(PStu headNode);                                       //根据学号进行排序 
void open_file(PStu headNode);                                     //打开文件       (打开的文件为try1.txt) 
void open_file2(PStu headNode);                                     //打开文件(学生系统)(打开的文件为管理员保存的try2.txt) 
void savefile(PStu headNode);                                      //关闭文件 
//void savefile2(PStu headNode);                                   //关闭文件                    
void filemade(PStu headNode);                                      //管理员方式的选择
void bye();                                                        //程序的结束

1.首先要创建头节点

//创建头链表 
PStu createlist()
{
	PStu headNode = (PStu)malloc(sizeof(Stu));   //变量使用前的的初始化 
	headNode->next = NULL;
	return headNode;
};

2.增添学生成绩(头插法和尾插法(详解在之前的文章里面))

//头插法 
void add(PStu headNode)
{
	 PStu pNew;
	 pNew = (PStu)malloc(sizeof(Stu));
	 printf("\n\n\n\t\t\t\t\t   添加的学生下信息:\n\n\t\t\t\t\t\t学号:");
	 scanf("%s",pNew->num);
	 printf("\n\t\t\t\t\t\t姓名:");
	 scanf("%s",pNew->name);
	 printf("\n\t\t\t\t\t\t数学:");
	 scanf("%d",&pNew->imath);                            
	 printf("\n\t\t\t\t\t\t英语:");
	 scanf("%d",&pNew->iEnglish);
	 printf("\n\t\t\t\t\t\tC语言:");
	 scanf("%d",&pNew->ic);
	 
	 pNew->next = headNode->next;           
	 headNode->next = pNew;
    
}
//尾插法 
void add(PStu headNode)
{
    PStu temp =headNode;//地址一样 
	while(temp->next )
	{
		temp = temp->next;
	}
	if(temp)
	{		
	
		PStu s = (PStu)malloc(sizeof(Stu));
	    temp->next = s;
		temp = s;
	    printf("\n\n\n\t\t\t\t\t   添加的学生下信息:\n\n\t\t\t\t\t\t学号:");
	    scanf("%s",s->num);
	    printf("\n\t\t\t\t\t\t姓名:");
	    scanf("%s",s->name);
	    printf("\n\t\t\t\t\t\t数学:");	    
	    scanf("%d",&s->imath);                                    
	    printf("\n\t\t\t\t\t\t英语:");
	    scanf("%d",&s->iEnglish);
	    printf("\n\t\t\t\t\t\tC语言:");
	    scanf("%d",&s->ic);
	    temp->next = NULL;
	}
}

3.删除学生的成绩(借助学号进行删除)

void deleteNodeByAppion(PStu headNode ,char *num)
{
	PStu posNode = headNode->next;
    PStu posNodefront = headNode;
    if(posNode==NULL)
	   printf("无法删除链表为空\n");
	else
	{
		while(strcmp(posNode->num,num))                             //strcmp比较值相等时返回值为0  字符串数组比较需要strcmp 
		{
			posNodefront = posNode ;
			posNode = posNodefront->next;
		    if(posNode==NULL)
		    {
			     printf("\n没有找到相关信息,无法删除\n");
			     return;
		    }
		}
		posNodefront->next = posNode->next;
		free(posNode);
	}
}

4.查找学生的成绩

借助for循环依次往后移动链表的位置,再借助strcmp比较两者字符串是否相等,如果相等strcmp返回0,退出循环,然后输出该节点的数据域的信息

下面这段代码借助学号进行查询

PStu chaNode2(PStu headNode,char *num)    
{
	PStu v = headNode;
	int i;
	while(strcmp(v->num,num))
	{         
		v = v->next;
	}
	printf("学号      姓名     数学     英语     C语言     总分\n");
	return v;
}

下面这段代码可以任意查询(相较于上个循环,这让循环更加的灵活,自主性更强,随意查询你想要查询的信息)

PStu chaNode(PStu headNode,int t,int j)
{
	PStu k = headNode;
	int i;
	int w = t;
	if(k == NULL)
	{
		printf("未存入学生信息!!!");
	}
	while(w<1&&w>j)
	{
		getchar();
		printf("\n不存在该生信息!\n");
		printf("请重新输入:");
	    scanf("%d",&w);
		getchar(); 
	}
	if(w>=1&&w<=j)
	{
		for(i = 1;i <= w;i++)
	   {
		k = k->next;
	   }
	   printf("学号      姓名     数学     英语     C语言     总分\n");
	   return k;
	}
}

5.修改学生的成绩

根据循环找到你需要修改的节点,然后进行替换,字符串使用strcpy,数字直接进行赋值

PStu gaiNode(PStu headNode) 
{
	PStu p = headNode;
	int a,i,c,math,English;
	char num[20],name[20];
	printf("你想修改哪一位同学的相关信息:");
	scanf("%d",&a);
	getchar();
	for(i = 1;i <= a;i++)
	{
		p = p->next;
	}
	printf("请选择你要更改的信息 :\n");
	printf("A学号 B.姓名 C.数学成绩 D.英语成绩 E.C语言成绩 \n");
    //getchar();    
    char w = getchar();
    getchar();
    if(w == 'A'||w == 'a')
	{
		printf("请输入修改后的学生学号: ");
		scanf("%s",num);
		getchar();
		strcpy(p->num,num);
	}
	if(w == 'B' || w == 'b')
	{
		printf("请输入修改后的学生姓名: ");
		scanf("%s",name);
		getchar();
		strcpy(p->name,name);
	}
	if(w == 'C'||w == 'c')
	{
		printf("请输入修改后的学生数学成绩: ");
		scanf("%d",&math);
		p->imath = math;
	}
	if(w == 'D'||w == 'd')
	{
		printf("请输入修改后的学生英语成绩: ");
		scanf("%d",&English);
		p->iEnglish = English;
	}
	if(w == 'E'||w == 'e')
	{
		printf("请输入修改后的学生C语言成绩: ");
		scanf("%d",&c); 
		p->ic = c;
	}
	return p;
}

 6. 对链表的数据进行冒泡排序

相比于正常的数字冒泡排序,链表的思路大概是一样的,设置一个链表指针变量t外循环从头遍历链表,设置另外一个链表指针u内循环从头遍历连表,如果左边的数据和右边的数据相互比较,进行一个交换

PStu t;
	PStu u;
	char name_[30],num_[30];
for(t = headNode->next;t!= NULL;t = t->next)
	 {
	 	for(u = headNode->next;u->next != NULL;u = u->next)
	 	{
	 		if(u->iscore < u->next->iscore)
	 		{
	 			 交换的代码段
			}
		 }
	 }

注意的是字符串比较使用strcmp,数字使用的是等号赋值,设置一个中间变量就ok了

7.打开文件,在头文件中要定义#include<io.h>,因为里面包含着read,write等函数,接下来打开文件,用FILE*定义文件指针,然后用fopen打开文件,然后判断一下文件是否打开,使用fscanf读取文件对应的信息,然后依次赋值给相应的链表节点对应的数据,最后一定要记得关闭文件

这个错误提示使用的时候需要注明头文件

#include<errno.h>    //如果文件为空,则进行相关的报错显示
PStu r = headNode;
	FILE *fp,*fp_;
	char filename[100],num_[30],name_[30];
	int imath_,iEnglish_,ic_,iscore_;
	PStu p = headNode;
	    fp= fopen("你保存文件的地址","r+");
	if(fp_== NULL )
   	 {
		printf("打开文件失败");
		printf("error:%s\n", strerror(errno));            //错误原因的显示 
		printf("%s可能不存在  \n",filename);
	 }
	while(fscanf(fp,"%s%s%d%d%d",num_,name_,&imath_,&iEnglish_,&ic_ )!= EOF)
	{
		 PStu node = (PStu)malloc(sizeof(Stu)); 
		 r->next = node;
		 需要赋值的数据.....
         .....
		 r = node;		 
	} 
	r->next = NULL;        //尾指针域置空
	fclose(fp);            //关闭文件

8.保存文件,首先打开自己需要保存的文件,然后fprintf将数据打印到文件上,然后关闭文件

void savefile(PStu headNode)     
{
	PStu iu = headNode->next;
	FILE *fp;
	fp = fopen("保存的文件的地址","w+");
	if(fp == NULL )
	{
		printf("打开文件失败\n");
		printf("error:%s\n",strerror(errno));
		printf("请按任意键退出!");
		getch();
		exit(1);
	}
	while(iu)
	{
		fprintf(fp,"%s	%s	%d	%d	%d	%d\n",iu->num ,iu->name,iu->imath ,iu->iEnglish ,iu->ic,iu->iscore);
		iu = iu->next;
	}
	printf("文件已经成功保存!");
	getch();
	fclose(fp);            //关闭文件
}

9.返回班级前三名的成绩并且可以查看自己的各项成绩,思路比较简单。

void notmanage(PStu headNode)
{
	system("cls");
	char num[20];
	PStu List = headNode;
	printf("\n\n\n\n\n\n\n\n\t\t\t\t\t");
	printf("由于您是学生,所以您只能进行“查询成绩和排名 ”\n\t\t\t\t\t");
	printf("查看自己的各科成绩\n\t\t\t\t\t");
	printf("2.查看班级前三名的总分(保护个人隐私)\n\t\t\t\t\t");     //看看自己和别人的差距 
	printf("请输入您的选择:");
	char a = getchar();
	getchar();
	open_file2(List);
	if(a == '1')
	  {   
		system("cls");
		printf("请输入您的学号:");
		gets(num);
		PStu z = chaNode2(List,num);
		if(z == NULL)
		{
			printf("查无此人!!!");
		}
		else
		{
			z->iscore = z->imath + z->iEnglish + z->ic;
		    printf("%s  %s    %d     %d     %d     %d",z->num,z->name,z->imath,z->iEnglish,z->ic,z->iscore);
	    }
	  }
	else if(a == '2')
	{
		open_file2(List);                  //打开文件 
		
	    maopao3(List);                     //这个函数里面直接输出了前三的相关信息                                     
	}
}