数据结构实验 第一单元 学生成绩管理系统(链表版)

#define _TABLE_STU_PRINT_LEVEL_LINE printf("**************************************************\n");
#define _TABLE_STU_PRINT_COL_TITLE printf("学号      姓名     数学   语文   英语   化学    物理  \n");
#define _TABLE_STU_PRINT_LINE printf("%-10s%-9s%-7.1f%-7.1f%-7.1f%-7.1f%-6.1f\n",stu->num,stu->name,stu->math,stu->cn,stu->eng,stu->che,stu->phy);

typedef struct 
{
	char num[11];
	char name[11];
	float math;
	float cn;
	float eng;
	float che;
	float phy;
}Student;

typedef struct stuNode
{
	Student data;
	struct stuNode *next;
}StuLinkedList;


//置空表
void InitStuList(StuLinkedList *L)
{
	L->next = NULL;
}
//获取表长
int GetStuListLength(StuLinkedList *L)
{
	StuLinkedList *p;
	int len = 0;
	p = L->next;
	while (p != NULL)
	{
		len++;
		p = p->next;
	}
	return len;
}

//取结点,查找链表中的第pos个位置(从1开始计数)的元素。未找到返回NULL。
StuLinkedList* GetStuListElem(StuLinkedList *L, int pos)
{
	//获取表长
	int now = 0;
	StuLinkedList *p = L->next;
	//超出范围
	if (pos > GetStuListLength(L) || pos<1)
		return NULL;
	//查找。。
	while (p != NULL)
	{
		now++;
		if (now == pos)
		{
			return p;
		}
		else
		{
			p = p->next;
		}
	}
	return NULL;
}

//带头结点的单链表。查找指定学号的学生所在结点,未找到返回NULL
StuLinkedList* LocateStuListElemByNum(StuLinkedList* L, char num[])
{

	StuLinkedList* p = L->next;
	while (p != NULL)
	{
		if (strcmp(p->data.num, num) == 0)
		{
			return p;
		}
		else
		{
			p = p->next;
		}
	}
	return NULL;

}

//获取学生所在的位置。从1开始计数。
int GetStuPosByNum(StuLinkedList* L,char num[])
{
	StuLinkedList* p = L->next;
	int pos = 0;
	while (p != NULL)
	{
		pos++;
		if (strcmp(p->data.num, num) == 0)
		{
			return pos;
		}
		else
		{
			p = p->next;
		}
	}
	return -1;
}

//带头结点的单链表。插入元素。pos:插入位置。key插入值,成功返回1,插入失败返回0。
int InsertStuList(StuLinkedList *L, int pos, Student key)
{
	StuLinkedList *p, *newNode;
	int len = GetStuListLength(L);
	//新建结点
	newNode = new struct stuNode;
	newNode->data = key;
	newNode->next = NULL;
	//检查插入范围
	if (pos >= 1 && pos <= len + 1)
	{
		//插入到1~len之间
		p = GetStuListElem(L, pos - 1);
		if (p == NULL)
		{
			//必为空表中插入第一个元素
			L->next = newNode;
			return 1;
		}
		newNode->next = p->next;
		p->next = newNode;
		return 1;
	}
	else
	{
		return 0;
	}
}

//带头结点的单链表。删除pos这个位置的元素,并且将这个元素的值保存在e中。删除成功返回1,失败返回0。
int DelStuListElem(StuLinkedList *L, int pos, Student *e)
{
	StuLinkedList *p, *pre;
	int len = GetStuListLength(L);
	if (pos<1 || pos> len)
		return 0;
	//得到该位置的元素
	p = GetStuListElem(L, pos);
	if (p == NULL)
		return 0;
	//得到该位置的前一个元素
	pre = GetStuListElem(L, pos - 1);
	if (pre == NULL)
	{
		//说明pos是第一个位置
		pre = L;
	}
	if (e != NULL)
		*e = p->data;
	pre->next = p->next;
	return 1;
}

//带头结点的单链表。建立链表。尾插法。
StuLinkedList* CreateStuListR(Student stus[], int n)
{
	StuLinkedList *L = new StuLinkedList, *p, *pre;
	int i;
	L->next = NULL;
	pre = L;
	for (i = 0; i<n; i++)
	{
		p = new struct stuNode;
		p->data = stus[i];
		p->next = NULL;
		pre->next = p;
		pre = p;
	}
	return L;
}

//带头结点的单链表。建立链表。头插法。
StuLinkedList* CreateStuList(Student stus[], int n)
{
	StuLinkedList *L = new StuLinkedList, *p, *pre;
	int i;
	L->next = NULL;
	pre = L;
	for (i = 0; i<n; i++)
	{
		p = new struct stuNode;
		p->data = stus[i];
		p->next = L->next;
		L->next = p;
	}
	return L;
}

//释放链表
void DeleteList(StuLinkedList* &L)
{
	StuLinkedList *p = L->next, *del;

	while (p != NULL)
	{
		//delete并不会改变p的值
		//它只是将p指向的那块内存释放了
		del = p;
		p = p->next;
		delete del;
	}
	delete L;
	L = NULL;
}

//带头结点的单链表。按照结点顺序,以字符方式输出链表。
void PrintStuList(StuLinkedList *L)
{
	StuLinkedList *p = L->next;
	Student *stu;
	putchar('\n');
	_TABLE_STU_PRINT_LEVEL_LINE
	_TABLE_STU_PRINT_COL_TITLE
	while (p != NULL)
	{
		//将stu按照顺序型输出
		stu = &(p->data);
		_TABLE_STU_PRINT_LINE
		p = p->next;
	}
	_TABLE_STU_PRINT_LEVEL_LINE
	printf("\n");
}

void PrintSingleStu(Student stuObj)
{
	Student *stu = &stuObj;
	_TABLE_STU_PRINT_LEVEL_LINE
	_TABLE_STU_PRINT_COL_TITLE
	_TABLE_STU_PRINT_LINE
	_TABLE_STU_PRINT_LEVEL_LINE
}


Student* ToArray(StuLinkedList* L, int *length)
{
	int len = GetStuListLength(L), i = 0;
	Student* dt = new Student[len];
	StuLinkedList *p = L->next;
	while (p != NULL)
	{
		dt[i++] = p->data;
		p = p->next;
	}
	*length = len;
	return dt;
}


//获取用户输入学生信息,封装成结构体
Student GetStuByInput()
{
	Student stu;
	printf("请输入学生学号:"); scanf("%s", stu.num);
	printf("请输入学生姓名:"); scanf("%s", stu.name);
	printf("请输入数学成绩:"); scanf("%f", &(stu.math));
	printf("请输入语文成绩:"); scanf("%f", &(stu.cn));
	printf("请输入英语成绩:"); scanf("%f", &(stu.eng));
	printf("请输入化学成绩:"); scanf("%f", &(stu.che));
	printf("请输入物理成绩:"); scanf("%f", &(stu.phy));
	return stu;
}


//返回修改后的学生
Student GetModifiedStu(Student sourceStu)
{
	char str[20];
	double dInp;
	Student stu;
	stu = sourceStu;
	PrintSingleStu(sourceStu);
	printf("请填写一下修改项\n");
	printf("修改学号,输入/不修改:"); scanf("%s", str);
	if (!(str[0] == '/' && str[1]==0) )
	{
		strcpy(stu.num, str);
	}
	printf("修改姓名,输入/不修改:"); scanf("%s", str);
	if (!(str[0] == '/' && str[1] == 0))
	{
		strcpy(stu.name, str);
	}
	printf("修改数学成绩,不修改输入-1:"); scanf("%lf", &dInp);
	if (dInp >0)
	{
		stu.math = dInp;
	}
	printf("修改语文成绩,不修改输入-1:"); scanf("%lf", &dInp);
	if (dInp > 0)
	{
		stu.cn = dInp;
	}
	
	printf("修改英语成绩,不修改输入-1:"); scanf("%lf", &dInp);
	if (dInp > 0)
	{
		stu.eng = dInp;
	}
	printf("修改化学成绩,不修改输入-1:"); scanf("%lf", &dInp);
	if (dInp >0)
	{
		stu.che = dInp;
	}
	printf("修改物理成绩,不修改输入-1:"); scanf("%lf", &dInp);
	if (dInp>=0)
	{
		stu.phy = dInp;
	}

	return stu;
}

//成功返回1
int ModifyStuByNum(StuLinkedList *L,Student stu)
{
	if (L == NULL)
		return 0;
	StuLinkedList *stuLink = LocateStuListElemByNum(L, stu.num);
	if (stuLink != NULL)
	{
		stuLink->data = stu;
		return 1;
	}
	else
	{
		return 0;
	}
}

//成功返回1
int DelStuByNum(StuLinkedList *L,char num[])
{

	if (L == NULL)
		return 0;
	int stuPos = GetStuPosByNum(L, num);
	return DelStuListElem(L, stuPos, NULL);


}


//全局变量
StuLinkedList *global_List = CreateStuList(NULL, 0);


//返回0,表示退出系统;返回非0,则继续循环。
int Menu()
{
	system("cls");
	printf("                   欢迎使用学生成绩管理系统\n");
	printf("          1.查看所有学生             2.添加学生信息\n");
	printf("          3.修改学生信息             4.删除所有学生\n");
	printf("          5.退出管理系统                         \n");
	printf("          当前学生数量:%d \n", GetStuListLength(global_List));
	printf("          请输入操作编号:");
	int oprNum;
	scanf("%d%*c", &oprNum);
	//清除菜单选项,
	system("cls");
	switch (oprNum)
	{
	case 1:
		PrintStuList(global_List);
		system("pause");
		return 1;
	case 2:
	{
		Student stu = GetStuByInput();
		int res = InsertStuList(global_List, 1+GetStuListLength(global_List), stu);
		if (res)
		{
			printf("添加成功,按任意键返回到主菜单!\n");
		}
		else
		{
			printf("添加失败!!按任意键返回到主菜单!\n");
		}
		system("pause");
	}
		return 1;
	case 3:
	{
		char num[20];
		StuLinkedList *stuL;
		Student stu;
		int res;
		//1. 显示学生列表
		PrintStuList(global_List);
		//2. 获取欲修改的学生的学号
		printf("请输入要修改的学生的学号:");
		gets(num);
		stuL = LocateStuListElemByNum(global_List, num);
		if (stuL == NULL)
		{
			printf("未找到该学生!按任意键返回到主菜单!\n");
			system("pause");
			return 1;
		}
		stu = stuL->data;
		//3. 输入修改信息
		stu = GetModifiedStu(stu);
		//4. 执行修改命令
		res = ModifyStuByNum(global_List,stu);
		if (res == 1)
		{
			printf("修改成功,按任意键返回到主菜单!\n");
		}
		else
		{
			printf("修改失败!!按任意键返回到主菜单!\n");
		}
		system("pause");
		return 1;
	}
	case 4: 
	{
		//1. 获取欲删除的学生学号
		char num[20];
		Student stu;
		int res;
		//1.1 显示学生列表
		PrintStuList(global_List);
		//1.2 获取欲删除的学生的学号
		printf("请输入要删除的学生的学号:");
		gets(num);
		res = DelStuByNum(global_List,num);
		if (res)
		{
			printf("删除成功,按任意键返回到主菜单!\n");
		}
		else
		{
			printf("删除失败!!按任意键返回到主菜单!\n");
		}
		system("pause");
	}
		return 1;
	case 5: 
		return 0;
		break;
	default:
		printf("您输入的编号格式错误!请重新输入");
		system("pause");
		return 1;
	}
}

void Welcome()
{

	printf("                   欢迎使用学生成绩管理系统\n");
	printf("                   作者:软件1402班 何健伟\n");
	printf("                   学号:201416080228\n");
	printf("                   日期:2015年11月27日\n");
	system("pause");
}

void GoodBye()
{
	printf("            .......谢谢您的使用!.......\n");
	system("pause");
}
void TestStudentOpr()
{
	
	Welcome();
	while (Menu());
	GoodBye();
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值