基于linux下的学生管理系统1


作为c语言学习阶段的最终检验,一个管理系统的好坏能比较直接的反应初学者的基础扎实与否。
一个完整且经用的学生管理系统的组成无非就是以下几个方面的知识点
(作者自我介绍:在校大学生一枚,暑假学习了将近一个月的c语言,想作一篇自我总结,一开始成就感还是有的,(后面肯定是挫折感了)看着一个能运行并履行功能的程序,有一种创造者的欣喜,第一次做有很多不足的地方,犯了许多错误,虽然最终不太会影响程序的运行,但存在隐患,文章末尾总结)

知识点介绍:

1:C语言的基础部分,顺序结构,循环结构,选择结构
2:C语言的数据结构部分:结构体,单链表,双链表,内核链表
3:文件操作:如何打开文件,写入文件。
我们再来看一看学生管理系统的基本要求
1:能够储存信息到文件中(最重要的要求)
2:能够对学生信息进行增删改查以及排序等功能
3:能对至少两类用户使用,如老师以及学生
4:程序无问题,以上要求都能实现

程序介绍:

/*

  •  程序名:简易学生管理系统
    
  •  功能 :对学生的增删改查
    
  •  负责人:王瑜
    

*/

#ifndef DLIST_H
#define DLIST_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//功能:安全检查宏
//@x:要检查的变量
//@opt:操作符: ==,<,>
//@y:要检查的值; 	if(NULL == p) {  printf("p is null\n"); return -1; }
//@z:返回值			SYSERR(NULL,==,p,"p is null",-1);
//					if(index < 0) {  printf("index must >= 0",-1); }
//					SYSERR(index,<,0,"index must >= 0",-1);
//
//					如果函数定义是: void fun(int *p);  没有返回值
//					if(NULL == p)
//					{
//						printf("p is null\n");
//						return;
//					}
//					SYSERR(NULL,==,p,"p is null\n",);

#define SYSERR(x, opt, y, message, z)                                           \
	if (x opt y)                                                                \
	{                                                                           \
		printf("%s %d %s : error %s\n", __FILE__, __LINE__, __func__, message); \
		return z;                                                               \
	}

/*链表节点定义:*/
typedef struct node
{
	struct node *before; //前向指针
	void *data;			 //数据指针,链表更通用
	struct node *after;	 //后向指针
} node_t;				 //node_t是struct node的类型别名
typedef struct student
{
	char name[16];
	int cla;
	int sno;
	int age;
	char sex[8];
	int score;
	int chinese;
	int math;
	int total;
	char admin[16];
	int rank;
} stu_t;
//功能:创建链表
//参数:无
//返回值:已创建链表的头节点地址
node_t *create_dlist();

//功能:向双循环链表头部插入数据
//@head:要插入的链表头节点
//@data:要插入链表的数据
//@size:数据的字节大小
//返回值为插入成功与否: 0表示成功,非0表示失败
int insert_hdlist(node_t *head, void *data, int size);

//功能:向双向循环链表尾部插入数据
int insert_tdlist(node_t *head, void *data, int size);

//功能:按值从链表中查找某节点
//@head:从哪个链表去查找
//@data:要查找的数据
//@cmpfun:比较函数指针,在调用时必须使用具体的函数名:返回类型必须为int,且有两个参数,
//两个参数必须为void *型
//返回值:如果查找到返回此节点,如果未找到返回NULL;
typedef int (*cmpfun_t)(void *data1, void *data2); //比较函数指针类型
node_t *find_vdlist(node_t *head, void *data, cmpfun_t cmpfun);

//功能:用于遍历显示链表中所有节点的函数
//@head:要显示的链表
//@showfun:显示函数指针,要怎么显示,在调用时必须使用具体的函数名:返回类型必须为void,有1个参数,
//这个参数的类型必须为void *
typedef void (*showfun_t)(void *data); //显示函数指针类型
void show_hdlist(node_t *head, showfun_t showfun);
void show_tdlist(node_t *head, showfun_t showfun);

//功能:删除第一个数据节点
//@head:要从哪个链表删除
int delete_hdlist(node_t *head);
//功能:删除链表尾部节点
int delete_tdlist(node_t *head);
//功能:按值删除,只会删除指定值第一次出现的节点
//@head:要从哪个链表删除
//@cmpfun:比较函数指针
//返回值:删除成功返回0,失败返回非0值
int delete_vdlist(node_t *head, void *data, cmpfun_t cmpfun);

//功能:对链表按指定方式排序
//@head:对哪个链表进行排序,
//@cmpfun:比较函数指针,排序的方式,函数指针
//返回值:排序成功返回0,失败返回非0值
int maopao_sortdlist(node_t *head, cmpfun_t cmpfun);

//功能:销毁链表,销毁后head为NULL
//返回值:销毁成功返回0,失败返回非0
int destroy_dlist(node_t **head);
int length_dlist(node_t *head);
/*功能:添加学生信息到链表
 * 返回值:void
 * 参数:head头结点
 */
void add_info(node_t *head);
/*
 *参数:head
 *功能:实现显示信息
 */
void show_info(node_t *head); //调用显示函数show_fun以及遍历查找

void find_info(node_t *head); //查找函数
//node_t *find_t(node_t *head,void *data,cmpfun_t cmpfun);
void modify_info(node_t *head);					//修改学生函数入口
void del_info(node_t *head);					//删除信息函数入口
void lodastu(node_t *head);						//加载文本信息到链表
int savestu(node_t *head);						//保存信息到文本
void stu_modify_info(node_t *head, stu_t stu1); //修改函数

#endif`

***接下来就是.c文件

`#include <stdio.h>***
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dlist.h"
#define SYSERR(x, opt, y, message, z)                                           \
	if (x opt y)                                                                \
	{                                                                           \
		printf("%s %d %s : error %s\n", __FILE__, __LINE__, __func__, message); \
		return z;                                                               \
	}

typedef void (*showfun_t)(void *data);
typedef int (*cmpfun_t)(void *data1, void *data2);

//功能:创建链表
//参数:无
//返回值:已创建链表的头节点地址
node_t *create_dlist()
{
	node_t *head = (node_t *)malloc(sizeof(node_t));
	SYSERR(NULL, ==, head, "head is null", NULL);
	sleep(1);
	head->before = head->after = head;
	head->data = NULL;
	return head;
}

//功能:向双循环链表头部插入数据
//@head:要插入的链表头节点
//@data:要插入链表的数据
//@size:数据的字节大小
//返回值为插入成功与否: 0表示成功,非0表示失败
int insert_hdlist(node_t *head, void *data, int size)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	SYSERR(NULL, ==, data, "data is null", -1);
	node_t *newnode = (node_t *)malloc(sizeof(node_t));
	SYSERR(NULL, ==, newnode, "malloc error", -2);

	newnode->data = malloc(size);
	SYSERR(NULL, ==, newnode->data, "malloc error", -2);
	memcpy(newnode->data, data, size);
	newnode->before = head;

	newnode->after = head->after;
	head->after->before = newnode;
	head->after = newnode;
	return 0;
}

//功能:用于遍历显示链表中所有节点的函数
//@head:要显示的链表
//@showfun:显示函数指针,要怎么显示,在调用时必须使用具体的函数名:返回类型必须为void,有1个参数,
//这个参数的类型必须为void *
void show_hdlist(node_t *head, showfun_t showfun)
{
	SYSERR(NULL, ==, head, "head is null", );
	node_t *temp = head->after;
	while (temp != head && (temp->data != NULL))
	{
		showfun(temp->data);
		temp = temp->after;
	}
	printf("\n");
	sleep(1);
}

void show_tdlist(node_t *head, showfun_t showfun)
{
	SYSERR(NULL, ==, head, "head is null", );
	node_t *temp = head->before;
	while (temp != head && (temp->data != NULL))
	{
		showfun(temp->data);
		temp = temp->before;
	}
	printf("\n");
	sleep(1);
}

//功能:向双向循环链表尾部插入数据
int insert_tdlist(node_t *head, void *data, int size)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	SYSERR(NULL, ==, data, "data is null", -1);
	node_t *newnode = (node_t *)malloc(sizeof(node_t));
	SYSERR(NULL, ==, newnode, "malloc error", -2);

	newnode->data = malloc(size);
	SYSERR(NULL, ==, newnode->data, "malloc error", -2);
	memcpy(newnode->data, data, size);
	newnode->before = head->before;
	newnode->after = head;

	head->before->after = newnode;
	head->before = newnode;
	return 0;
}
//功能:循环遍历查找并返回找到的结点
node_t *find_vdlist(node_t *head, void *data, cmpfun_t cmpfun)
{
	SYSERR(NULL, ==, head, "head is null", NULL);
	SYSERR(head, ==, head->after, "list is null", NULL);
	SYSERR(NULL, ==, data, "data is null", NULL);
	node_t *temp = head->after;

	while ((temp != head) && (temp->data != NULL))
	{
		if (!cmpfun(temp->data, data))
			return temp;
		temp = temp->after;
	}
	return NULL;
}
/*node_t *find_t(node_t *head,void *data,cmpfun_t cmpfun)
{
	node_t *temp = head->after;

	while((temp != head) && (temp->data != NULL))
	{
		if(!cmpfun(temp->data,data))
			return temp;
		temp = temp->after;
	}
	return NULL;
}
*/

//功能:删除第一个数据节点
//@head:要从哪个链表删除
int delete_hdlist(node_t *head)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	SYSERR(head, ==, head->after, "list is null", -1);
	node_t *temp = head->after;
	head->after = temp->after;

	temp->after->before = temp->before;
	free(temp->data);
	free(temp);
	return 0;
}

//功能:按值删除,只会删除指定值第一次出现的节点
//@head:要从哪个链表删除
//@cmpfun:比较函数指针
//返回值:删除成功返回0,失败返回非0值
int delete_tdlist(node_t *head)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	SYSERR(head, ==, head->after, "list is null", -1);
	node_t *temp = head->before;
	temp->after->before = temp->before;

	temp->before->after = temp->after;
	free(temp->data);
	free(temp);
	return 0;
}

//功能:按值删除,只会删除指定值第一次出现的节点
//@head:要从哪个链表删除
//@cmpfun:比较函数指针
//返回值:删除成功返回0,失败返回非0值
int delete_vdlist(node_t *head, void *data, cmpfun_t cmpfun)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	SYSERR(head, ==, head->after, "list is null", -1);
	SYSERR(NULL, ==, data, "data is null", -1);
	node_t *temp = head->after;

	while (temp != head && (temp->data != NULL))
	{
		if (!cmpfun(temp->data, data))
		{
			temp->before->after = temp->after;
			temp->after->before = temp->before;
			free(temp->data);
			free(temp);
			return 0;
		}
		temp = temp->after;
	}
	return -1;
}

//功能:销毁链表,销毁后head为NULL
//返回值:销毁成功返回0,失败返回非0
int destroy_dlist(node_t **head)
{
	SYSERR(NULL, ==, *head, "head is null", -1);
	node_t *current, *after;
	current = after = (*head)->after;
	while (current != *head)
	{
		after = current->after;
		free(current->data);
		free(current);
		current = after;
	}

	free(*head);
	*head = NULL;
	return 0;
}

int length_dlist(node_t *head)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	node_t *temp = head->after;
	int i = 0;

	while (temp != head)
	{
		i++;
		temp = temp->after;
	}
	return i;
}

//冒泡排序
int maopao_sortdlist(node_t *head, cmpfun_t cmpfun)
{
	SYSERR(NULL, ==, head, "head is null", -1);
	node_t *inext, *jnext;
	void *temp = NULL;
	int flag;

	for (inext = head->after; inext != head; inext = inext->after)
	{
		flag = 0;
		for (jnext = head->after; jnext->after != head; jnext = jnext->after)
		{
			if (cmpfun(jnext->data, jnext->after->data) > 0)
			{
				temp = jnext->data;
				jnext->data = jnext->after->data;
				jnext->after->data = temp;
				flag = 1;
			}
		}
		if (!flag)
			break;
	}
	return 0;
}

具有通用性的链表(如上)

链表部分介绍完了,对于链表的操作基本已经全部实现了,我们就可以用链表来进行学生信息的操作
老师模块需要对学生增删改查排序,其中比较需要注意的是删以及排序,学生管理需要每个学生进行排名,以及需要一个账号密码,账号得唯一,不然就很复杂了,所以我们用学号作为账号,密码先初始化为123456。
先看头文件

#ifndef __TEA_H__
#define __TEA_H__
#include "dlist.h"
void welcome(); //欢迎页面
void menu();    //菜单页面
//参数:data:结点数据
void show_all(void *data);      //全部显示
void show_cla(void *data);      //班级
void show_age(void *data);      //显示年龄
void show_sno(void *data);      //显示学号
void show_score(void *data);    //显示c成绩
void show_chinese(void *data);  //显示语文成绩
void show_math(void *data);     //显示数学成绩
void show_total(void *data);    //显示总成绩
void show_sex(void *data);      //显示性别
void show_allscore(void *data); //显示所有成绩
void show_stu_name(void *data);
int cmp_stu_sno(void *data1, void *data2);     //比较学生的学号
int cmp_stu_cla(void *data1, void *data2);     //比较学生的班级
int cmp_stu_score(void *data1, void *data2);   //比较学生的c语言成绩
int cmp_stu_chinese(void *data1, void *data2); //比较学生的语文成绩
int cmp_stu_math(void *data1, void *data2);    //比较学生的数学成绩
int cmp_stu_total(void *data1, void *data2);   //比较学生的总成绩
int cmp_stu_name(void *data1, void *data2);    //比较学生的姓名
#endif

以下是函数部分

#include "dlist.h"
#include "tea.h"

static int sno = 0;
static int RANK = 0;
/******
 * 作用:获取学号
 * ****/
int getcid()
{
	return sno > 99999 ? 1 : ++sno;
}
void welcome() //欢迎页面
{
	system("clear");
	printf("---------------------------------------------------------\n");
	printf("\t\t欢迎使用学生管理系统\n");
	printf("---------------------------------------------------------\n");
	sleep(1);
}

void menu() //菜单页面
{
	system("clear");
	printf("*********************系统功能菜单*************************       \n");
	printf("|     *********************************************    |\n");
	printf("|     * 1.增加学生信息    * *   2.显示学生信息         |  \n");
	printf("|     *********************************************    |\n");
	printf("|     * 3.查询学生信息    * *   4.修改学生信息   *     |\n");
	printf("|     *********************************************    | \n");
	printf("|     * 5.删除学生信息    * *   6.退出系统       *     |\n");
	printf("|     *********************************************    | \n");
	printf("**********************************************************       \n");
}

void show_all(void *data) //全部显示
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 姓名%s 班级%d 年龄%d 性别%s c语言成绩%d 语文成绩%d 数学成绩%d 总成绩%d 密码%s\n", stup->rank, stup->sno, stup->name, stup->cla, stup->age, stup->sex, stup->score, stup->chinese, stup->math, stup->total, stup->admin);
}
void show_cla(void *data) //显示班级
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 姓名%s 学号%d 班级%d\n", stup->rank, stup->name, stup->sno, stup->cla);
}
void show_age(void *data) //显示年龄
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 姓名%s 学号%d 年龄%d\n", stup->rank, stup->name, stup->sno, stup->age);
}

void show_sno(void *data) //显示学号
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 姓名%s 学号%d\n", stup->rank, stup->name, stup->sno);
}
void show_score(void *data) //显示c成绩
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 姓名%s 学号%d c语言成绩%d\n", stup->rank, stup->name, stup->sno, stup->score);
}
void show_chinese(void *data) //显示语文成绩
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 语文成绩%d\n", stup->rank, stup->sno, stup->chinese);
}

void show_math(void *data) //显示数学成绩
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 数学成绩%d\n", stup->rank, stup->sno, stup->math);
}
void show_total(void *data) //显示总成绩
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 总成绩%d\n", stup->rank, stup->sno, stup->total);
}
void show_sex(void *data) //显示性别
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 性别%s\n", stup->rank, stup->sno, stup->sex);
}
void show_allscore(void *data) //显示所有成绩
{
	stu_t *stup = (stu_t *)data;
	stup->total = stup->score + stup->chinese + stup->math;
	stup->rank = ++RANK;
	printf("排名%d 学号%d 数学成绩%d 语文成绩%d c语言成绩%d 总成绩%d\n", stup->rank, stup->sno, stup->math, stup->chinese, stup->score, stup->total);
}

void show_stu_name(void *data)
{
	stu_t *stup = (stu_t *)data;
	printf("%s ", stup->name);
}

int cmp_stu_sno(void *data1, void *data2) //比较学生的学号
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu1->sno - stu2->sno;
}

int cmp_stu_cla(void *data1, void *data2) //比较学生的班级
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu2->cla - stu1->cla;
}

int cmp_stu_score(void *data1, void *data2) //比较学生的c语言成绩
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu2->score - stu1->score;
}

int cmp_stu_chinese(void *data1, void *data2) //比较学生的语文成绩
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu2->chinese - stu1->chinese;
}

int cmp_stu_math(void *data1, void *data2) //比较学生的数学成绩
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu2->math - stu1->math;
}
int cmp_stu_total(void *data1, void *data2) //比较学生的总成绩
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return stu2->total - stu1->total;
}

int cmp_stu_name(void *data1, void *data2) //比较学生的姓名
{
	stu_t *stu1 = (stu_t *)data1;
	stu_t *stu2 = (stu_t *)data2;
	return strcmp(stu1->name, stu2->name);
}

/*功能:添加学生信息到链表
 * 返回值:void
 * 参数:head头结点
 */
void add_info(node_t *head)
{
	RANK++;
	printf("请输入学生的姓名\n");
	stu_t *s = (stu_t *)malloc(sizeof(stu_t));
	scanf("%s", s->name);
	printf("请输入学生的班级\n");
	scanf("%d", &s->cla);
	printf("学号自动输入\n");
	s->sno = getcid();
	printf("请输入学生的年龄\n");
	scanf("%d", &s->age);
	printf("请输入学生的性别 f/m \n");
	scanf("%s", s->sex);
	printf("请输入学生的c语言成绩\n");
	scanf("%d", &s->score);
	printf("请输入学生的语文成绩\n");
	scanf("%d", &s->chinese);
	printf("请输入学生的数学成绩\n");
	scanf("%d", &s->math);
	s->total = s->score + s->chinese + s->math;
	strcpy(s->admin, "123456");
	//判断学号是否重复,学号不允许重复
	node_t *res = find_vdlist(head, s, cmp_stu_sno);
	if (res != NULL)
	{
		stu_t *stup = (stu_t *)res->data;
		printf("输入的学生学号重复\n");
		printf(" conflict : %s %d %d\n", stup->name, stup->sno, stup->age);
		sleep(2);
		return;
	}
	insert_tdlist(head, s, sizeof(stu_t));
	printf("姓名%s 学号%d 年龄%d 性别%s c语言成绩%d 语文成绩%d 数学成绩%d 总成绩%d 密码%s\n", s->name, s->sno, s->age, s->sex, s->score, s->chinese, s->math, s->total, s->admin);
	sleep(1);
}

/*
 *参数:head
 *功能:实现显示信息
 */
void show_info(node_t *head)
{
	int ch;
	int flag = 1;
	system("clear");
	while (flag)
	{
		system("clear");
		RANK = 0;
		printf("|---------------------------------------------------------|\n");
		printf("|    1:全部现实               2:根据学号排序      |\n");
		printf("|    3:根据c语言排序                4:根据数学成绩排序  |\n");
		printf("|    5:根据语文成绩排序          6:根据总成绩排序    |\n");
		printf("|    7:根据班级排序            8:退出         |\n");
		printf("|---------------------------------------------------------|\n");
		scanf("%d", &ch);
		switch (ch)
		{
		case 1:
			show_hdlist(head, show_all);
			sleep(1);
			break;
		case 2:
			maopao_sortdlist(head, cmp_stu_sno);
			show_hdlist(head, show_sno);
			sleep(1);
			break;
		case 3:
			maopao_sortdlist(head, cmp_stu_score);
			show_hdlist(head, show_score);
			sleep(1);
			break;
		case 5:
			maopao_sortdlist(head, cmp_stu_chinese);
			show_hdlist(head, show_chinese);
			sleep(1);
			break;
		case 4:
			maopao_sortdlist(head, cmp_stu_math);
			show_hdlist(head, show_math);
			sleep(1);
			break;
		case 6:
			maopao_sortdlist(head, cmp_stu_total);
			show_hdlist(head, show_total);
			sleep(1);
			break;
		case 7:
			maopao_sortdlist(head, cmp_stu_cla);
			show_hdlist(head, show_cla);
			sleep(1);
			break;
		case 8:
			maopao_sortdlist(head, cmp_stu_sno);
			printf("返回主菜单\n");
			flag = 0;
			sleep(1);
			break;
		}
		sleep(1);
	}
}

/*
 *查找函数
 *参数:head
 */

void find_info(node_t *head)
{
	int ch = 0;
	node_t *templist = create_dlist(); //先通过find_stu:再通过templist去修改   templist->after->data此指针才保存了学生数据
	node_t *res = head;
	stu_t stu2;
	system("clear");
	printf("\t\t1:根据学号查询		2:根据姓名查询\n");
	scanf("%d", &ch);
	if (ch == 1)
	{
		printf("请输入你要查询的学生学号\n");
		scanf("%d", &stu2.sno);
		//2)循环查找;到查找结果为NULL时,另外还要不断移动头节点
		while ((res = find_vdlist(res, &stu2, cmp_stu_sno)) != NULL)
		{
			RANK = 0;
			//3)找到后要把找到的数据插入到链表中
			insert_tdlist(templist, res->data, sizeof(stu_t));
		}
		maopao_sortdlist(head, cmp_stu_sno);
	}
	else if (ch == 2)
	{
		printf("请输入你要查询的学生姓名\n");
		scanf("%s", stu2.name);
		while ((res = find_vdlist(res, &stu2, cmp_stu_name)) != NULL)
		{
			RANK = 0;
			insert_tdlist(templist, res->data, sizeof(stu_t));
		}
		maopao_sortdlist(head, cmp_stu_sno);
	}
	else
	{
		printf("操作有误,返回主菜单\n");
		return;
	}
	show_hdlist(templist, show_all);
	sleep(1);
	destroy_dlist(&templist);
}


void modify_info(node_t *head)
{
	printf("------update_stu : 按学号查找,修改姓名,年龄,性别,性别-------\n");
	stu_t stu1;
	printf("请输入学号\n");
	scanf("%d", &stu1.sno);
	node_t *res = find_vdlist(head, &stu1, cmp_stu_sno);
	//2.找到此节点后,再通过数据指针修改
	if (res != NULL)
	{

		stu_t *stup = (stu_t *)res->data; //能成功修改
		printf("1:修改年龄 2:修改姓名\n");
		printf("3:修改性别 4:修改班级\n");
		printf("5:修改成绩 6:返回主菜单\n");
		int ch = 0;
		scanf("%d", &ch);
		char name[16];
		switch (ch)
		{
		case 1:
			printf("请输入年龄\n");
			scanf("%d", &stup->age);
			sleep(1);
			show_age(stup);
			break;
		case 2:
			printf("请输入姓名\n");
			scanf("%s", name);
			strcpy(stup->name, name);
			sleep(1);
			show_age(stup);
			break;
		case 3:
			printf("请输入性别m/f\n");
			scanf("%s", stup->sex);
			sleep(1);
			show_sex(stup);
			break;
		case 4:
			printf("请输入班级\n");
			scanf("%d", &stup->cla);
			sleep(1);
			show_cla(stup);
			break;
		case 5:
			printf("请输入c语言成绩\n");
			scanf("%d", &stup->age);
			printf("请输入数学成绩\n");
			scanf("%d", &stup->math);
			printf("请输入语文成绩\n");
			scanf("%d", &stup->chinese);
			show_allscore(stup);
			sleep(1);
			show_allscore(stup);
			break;
		case 6:
			printf("返回主菜单\n");
			return;
		}
	}
	else
		printf("not found %d号学生\n", stu1.sno);
	//3.显示所有学生数据
	show_hdlist(head, show_all);
}


void del_info(node_t *head)
{
	printf("---------------------------------------------------------\n");
	printf("\t\t1:按学号删除  2:按班级删除\n");
	printf("\t\t3:按姓名删除  4:返回主菜单\n");
	printf("---------------------------------------------------------\n");
	int ret;
	int ch;
	scanf("%d", &ch);
	stu_t stu1;
	if (ch == 1)
	{
		printf("请输入你要删除的学生的学号\n");
		scanf("%d", &stu1.sno);
		ret = delete_vdlist(head, &stu1, cmp_stu_sno);
		if (!ret)
		{
			printf("delete ok\n");
			RANK = 0;
			show_hdlist(head, show_all);
			sleep(1);
		}
		else
		{
			printf("delete error\n");
			sleep(1);
		}
	}
	else if (ch == 3)
	{
		printf("请输入你要删除的学生的姓名\n");
		char name[16];
		scanf("%s", name);
		strcpy(stu1.name, name);
		while ((ret = delete_vdlist(head, &stu1, cmp_stu_name)) == 0)
			;
		printf("delete ok\n");
		RANK = 0;
		show_hdlist(head, show_all);
	}
	else if (ch == 2)
	{
		printf("请输入你要删除的班级\n");
		scanf("%d", &stu1.cla);
		while ((ret = delete_vdlist(head, &stu1, cmp_stu_cla)) == 0)
			;
		printf("delete ok\n");
		RANK = 0;
		show_hdlist(head, show_all);
	}
	else
		return;
}


void lodastu(node_t *head)
{
	int i = 0;
	FILE *fp;
	fp = fopen("student", "a+");
	stu_t *s = (stu_t *)malloc(sizeof(stu_t));
	while (EOF != (fscanf(fp, "%s %d %d %d %s %d %d %d %d %s %d", s->name, &s->cla, &s->sno, &s->age, s->sex, &s->score, &s->chinese, &s->math, &s->total, s->admin, &s->rank)))
	{
		i++;
		insert_tdlist(head, s, sizeof(stu_t));
	}
	if (i != 0)
	{
		maopao_sortdlist(head, cmp_stu_sno);
		node_t *p = head->after;
		while (p->after != head)
		{
			p = p->after;
		}
		stu_t *stu = (stu_t *)p->data;
		sno = stu->sno;
		//	printf("%d",stu->sno);
		sleep(1);
		printf("读取到%d条数据\n", i);
		sleep(1);
	}
	else
	{
		printf("数据库内容为空\n");
		sleep(1);
	}
}


int savestu(node_t *head)
{
	node_t *temp = head->after;
	FILE *fp = fopen("student", "w+");
	int i = 0;
	while (temp != head && (temp->data != NULL))
	{
		stu_t *s = temp->data;
		i++;
		fprintf(fp, "%s %d %d %d %s %d %d %d %d %s %d\n", s->name, s->cla, s->sno, s->age, s->sex, s->score, s->chinese, s->math, s->total, s->admin, s->rank);
		temp = temp->after;
		printf("正在保存第%d个学生的信息,请勿关机退出\n", i);
		sleep(1);
	}
	printf("保存成功\n");
	fclose(fp);
	printf("链表销毁\n");
	return 0;
}

因为写链表耗费了太多时间,所以写调用函数部分就写的比较快,所以省略了许多安全判断的部分,,基本没有判断传进来的是不是个空节点,也用的是休眠函数,为了检验程序运行而省事,没有调用pause的命令,大家也可以考虑用getchar()函数来暂停while的循环,一个不够用两个,希望大家把这当成反面教材。

核心内容结束

剩下的部分都是自由发挥的部分了,调用各个函数,组装你的程序,这一个过程是很有意思的。
当然,还是给大家看一下我的登录部分用来什么函数

#ifndef  __LOGON_H__
#define __LOGON_H__
int stu_admin(node_t *head);	//学生登陆验证
int tea_logon(node_t *head);	//老师登陆
int tea_admin();				//老师登陆验证
int logon_menu(node_t *head);   //登陆选择身份函数
void stu_modify_info(node_t *head,stu_t stu1);//修改函数
#endif

总结
1:注释量过于少,程序整体不够简洁,适当的注释量以及函数与函数之间空两三行能给人一种舒适感。
2:一个函数不宜写的过长,可以尝试将一部分功能装成另一个函数,及一个大功能函数调用几个小功能函数,函数能写成通用的尽可能写成通用函数
3:函数之间的参数需要格外注意,尽可能写点安全判断。
4:要考虑函数的健壮性,举个例子,让用户输入一个数字,用户输入的是一个字符串,这很容易引起函数的运行出现意外。如何防止??scanf函数也是具有返回值的,从这方面入手如何?
5:本程序皆没有完美达到上诉内容,我希望之所以上传这个也是想给自己留个印象,让自己以后写代码都不要忘记以上的总结。
6:如果有其他带有善意的提醒或者批评性建议,我洗耳恭听,时刻对编程保持敬畏。


版权声明:本文为Seamenwang原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。