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

#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();
}

转载于:https://www.cnblogs.com/tinyjian/p/6550715.html

1. 建立文件 (1)可以使用默认文件名或指定文件名将记录存储到文件 (2)设置适当的标志位,作为对记录进行操作的信息 (3)写同名文件将覆盖原来文件的内容 2.增加学生记录 (1) 可在已有记录后面追加新的记录  (2) 可以随时增加新的记录,它们仅保存在向量数组中 (3) 可以将一个文件读入,追加在已有记录之后 (4) 采取文件追加方式时,在没有保存到文件之前,将继续保持文件追加状态,以便实现连 续追加操作方式 3. 新建学生信息文件 (1) 用来新建学生信息记录 (2) 如果已经有记录存在,可以覆盖原记录或者在原记录后面追加,也可以将原有记录信息保存 到一个指定文件,然后重新建立记录 (3) 给出相应的提示信息 4. 显示记录 (1) 如果没有记录可供显示,给出提示信息 (2) 可以随时显示内存中的记录 (3) 显示表头 5. 文件存储 可以按默认名字或指定名字存储记录文件 6. 读取文件 (1) 可以按默认名字或指定名字将记录文件读入内存 (2) 可以将指定或默认文件追加到现有记录的尾部 (3) 可以将文件连续追加到现有记录并更新记录中的“名次”项 7. 删除记录 (1) 可以按“学号”、“姓名”或“名次”方式删除记录 (2) 标志将被删除的记录, 可以再次取消标志, 经确认后删除已经标志的记录 (3) 如果记录是空表, 删除时应给出提示信息并返回主菜单 (4) 如果没有要删除的信息, 输出“没有找到”的信息 (5) 更新其他记录的名次 (6) 删除操作仅限于内存, 只有执行存储操作时, 才能覆盖原记录 8. 修改记录 (1) 可以按“学号”、“姓名”或“名次”方式查找要修改的记录内容 (2) 给出将被修改记录的信息, 经确认后进行修改 (3) 如果记录已经是空表,应给出提示信息并返回主菜单 (4) 如果没有找到需要修改的信息, 输出“没有找到”的信息 (5) 更新其他记录的名次 (6) 修改操作仅限于内存, 只有执行存储操作时, 才能覆盖原记录 9. 查询记录 (1) 可以按“学号”、“姓名”或“名次”方式查询记录 (2) 能给出查询记录的信息 (3) 如果查询的信息不存在, 输出提示信息 10. 对记录进行排序 (1) 可以按”学号”进行升序和降序排列 (2) 可以按”姓名”进行升序和降序排列 (3) 可以按”名次”进行升序和降序排列 (4) 如果属于选择错误, 可以立即退出程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值