在c语言中使用链表完成学生成绩管理系统(密码登录系统的采纳,加入了隐藏与删除功能,添加了指针域与数据域两种不同的排序)

这篇具有很好参考价值的文章主要介绍了在c语言中使用链表完成学生成绩管理系统(密码登录系统的采纳,加入了隐藏与删除功能,添加了指针域与数据域两种不同的排序)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

void menu()
{
	printf("**********************************************************\n");
	printf("1数据的创建 \t2数据的插入\t3数据的删除\n4数据的更改\t5求数据最大值\t6数据的排序\n7输出数据\t8退出\t\
9清屏\n");
	printf("********************************************************\n");
}

#二、每个函数的简绍与思路
##1:密码登录的验证思路:

(1)在主函数main里定义一个标志 flat2=0;如果flat2!=0,就代表密码登录成功,可以进入系统!

(2)在具体函数mima()之中,使用了控制台函数_getch();其头文件为#include<conio.h>,该函数可以隐藏输出,注意:_getch()是隐藏单个字符,且需要一个存储空间,可以使用数组结合循环来使用,例子a[i]=_getch();此时在终端上不会显示内容,所以结合printf语句让用户明白我们输入的多少!并且加入判断,回车是结束输入的功能并且给此时空间赋值一个’\0’!

定义一个j是保证最大的失误范围若超过系统退出!

(3)删除功能是:当输入回车时,阻止继续输入*,(使用continue);,并且给此时空间赋值一个’\0’,

在进行printf(“\b”);鼠标箭头回退,printf(" “);输入空格覆盖 “*”;在让鼠标回退printf(”\b");
代码如下

void mima(int* flag2)
{
	int j = 6;
	char mima[20];
	int i = 0;
	while (1)
	{
		i = 0;
		printf("请输入用户名:");
		char name[16];
		scanf("%s", name);
		printf("请输入密码:");

		while (1)
		{
			mima[i] = _getch();
			if (mima[i] == '\r')
			{
				mima[i] = '\0';
				break;
			}
			else if (mima[i] == '\b')
			{
				mima[i] = '\0';
				printf("\b");
				printf(" ");
				printf("\b");
				i--;
				continue;
			}
			else
			{
				printf("*");
				i++;
				if (i == 19)
				{
					printf("密码已达到最大长度!\n");
					break;
				}
			}

		}
		if (strcmp(name, "小明") == 0)
		{
			if (strcmp(mima, "2082716421") == 0)
			{
				*flag2 = 2;
				printf("输入正确!\n");
				break;
			}
			else
			{
				j--;
				printf("账户或密码错误!\n");
				printf("你还有%d次机会\n", j);

				if (j == 0)
				{
					printf("已达到输入密码最多次数\n");
					break;
				}
			}
		}
		else
		{
			j--;
			printf("查询不到用户!\n");
			printf("你还有%d次机会\n", j);
			if (j == 0)
			{
				printf("已达到输入密码最多次数\n");
				break;
			}
		}
	}
}

##创建链表

使用了一个单链表,链表思路如下:

(1)首先创建一个结构体;

typedef struct Date

{

int age[6];

char name[16];

int length;

}lp;//创建这个结构体是为了高效进行数据域交换的冒泡排序

typedef struct student

{

lp data;

struct student *next;

}Lp;(注意一般结构体里是不许赋初值的)

头节点head(这个是大基,不要动他,以后的操作函数传它,用它去进行插入,删除,输出等功能)且数据域不要存放东西,因为后续插入等操作要用到!,赋值链节p,p=head;新链节 q(指针);开辟他的空间,并使用p->next=q;在让p=q;q在去开辟空间重复上述功能!
注意的是,如果在函数内开辟空间,涉及到函数传参问题
思路1:使用函数指针且返回的是头节点。

Lp* Creatlist(Lp* head)
{
	head = (Lp*)malloc(sizeof(Lp));//头节点不要在数据域存数据
	Lp* p = head, * q = NULL;
	head->data.length = 0;//确定链表的长度
	while (1)
	{
		q = (Lp*)malloc(sizeof(Lp));
		p->next = q;
		p = q;
		printf("请输入%d位学生姓名:", head->data.length + 1);
		scanf("%s", p->data.name);
		if (strcmp(p->data.name, "结束输入") == 0)
		{
			break;
		}
		printf("请输入%d位学生六科成绩:", head->data.length + 1);
		for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
		{
			scanf("%d", &p->data.a[i]);
		}
		head->data.length++;

	}
	p->next = NULL;
	return head;
}

思路2: 传二级指针对一级指针的修改。

void creatlianbiao(ch** head, int* a)
{
	*a = 0;//检验链接的长度
	*head = (ch*)malloc(sizeof(ch));//开辟链表头的空间
	ch* p = NULL, * q = NULL; 
	p = *head;
	while (1)
	{
		printf("请输入姓名:");
		scanf("%s", p->a.name);
		if (strcmp(p->a.name, "退出") == 0)
		{
			break;
		}	
		printf("请输入成绩:");
		scanf("%d", & p->a.cj);
		(*a)++;
		q = (ch*)malloc(sizeof(ch));
		p->next = q;
		p = q;
	}
	p->next = NULL;
}
//思路如此,这个是一个姓名对应一个值
//这个没有插入等操作所以为了省空间头节点数据域存放了数据

##检验链表的开辟是否成功(遍历链表)
主要思路就是当p->next==NULL时,跳出循环;

void Outputlist(Lp* head)
{
	Lp* p; p = head->next;//头节点没有数据所以是head->next;
	while (p->next != NULL)
	{
		printf("%s:\t", p->data.name);
		for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
		{
			printf("%d\t", p->data.a[i]);
		}
		printf("\n");
		p = p->next;
	}
}

##3插入与删除,改变链表功能
思路:这三者基本一样,区别的是:插入需要找到目标后对其后或之前进行插入(会导致首节点,或末节点插入有些许困难),删除就是找到目标位置进行指针跳过这个指向后一节操作!而改变是在找到目标情况下进行修改具体如下
(1)插入:采用了查询姓名+首个成绩来找值,并在其后进行操作,这里分别给出插入某个人数据后面的和首位置得方法

Lp* Insertmenu(Lp* head)
{
	int a=0;
	Lp* Insertlist(Lp * head);
	Lp* Inserfirsttlist(Lp * head);
	void Outputlist(Lp * head);//声明函数
	printf("***************************\n");
	printf("1,插入首位\t2插入某个人数据后面\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择插入的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Inserfirsttlist(head); break;
		case 2:head = Insertlist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}
//插入链首的
Lp* Inserfirsttlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	printf("你进入的是插入首链节选择!\n");
	Lp* p, * q;
	Lp* m = head->next;//存放首个数据域的节点
	p = head;
	q = (Lp*)malloc(sizeof(Lp));//开辟空间
	printf("请输入插入的学生姓名:");
	scanf("%s", q->data.name);
	printf("请输入%该学生六科成绩:");
	for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
	{
		scanf("%d", &q->data.a[i]);
	}
	head->data.length++;//测长度
	p->next = q;
	q->next = m;
	return head;
}
//插入某个数据的后面的
Lp* Insertlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请初始化在进行其他操作!");
		return head;
	}//检验是否位为空条件
	char name[16];
	int a;
	printf("请输入要插入那个人的姓名+首个成绩:");
	scanf("%s", name);
	scanf("%d", &a);
	Lp* p = head->next, * q;//头节点为指针域为空
	Lp* m = head->next->next;//紧跟着存放p的后继位!方便插入
	int k = 0;//检验是否找到数据
	while (p->next != NULL)
	{
		if (strcmp(p->data.name, name) == 0 && p->data.a[0] == a)
		{
			printf("已成功找到要插入数据\n");
			q = (Lp*)malloc(sizeof(Lp));
			printf("请输入学生姓名:");
			scanf("%s", q->data.name);
			printf("请输入学生六科成绩:");
			for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
			{
				scanf("%d", &q->data.a[i]);
			}
			head->data.length++;//长度
			p->next = q;
			q->next = m;
			k++;
			break;//找到后直接跳出循环
		}
		else
		{
			p = p->next;
			m = m->next;
		}//保持链表向后进行
	}
	if (k == 0)
	{
		printf("未找到数据\n");
	}
	return head;
}

(2)删除(其实可以写一个函数完成,但是为了对称采用此方法)

Lp* Deletemenu(Lp* head)
{
	void Outputlist(Lp * head);//声明
	int a = 0;
	printf("***************************\n");
	printf("1,删除首位\t2删除某个人数据后面\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择删除的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Deletefirstlist(head); break;
		case 2:head = Deletelist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}
Lp* Deletefirstlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	Lp* p = head;//用来跳过首个有数据的链结
	Lp* q = head->next->next;//注意这里不在是开辟空间啦,这是有数据的链结后的链结
	p->next = q;
	head->data.length--;
	return head;
}
Lp* Deletelist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	Lp* p = head;
	Lp* q = head->next;//p后的链结
	printf("请输入要插入那个人的姓名+首个成绩:");
	char name[16];
	int a;
	int k = 0;//检验是否找到数据
	scanf("%s", name);
	scanf("%d", &a);
	while (p->next != NULL)
	{
		if (strcmp(q->data.name, name) == 0 && q->data.a[0] == a)//这里不能用p->next来因为无法对目标数据进行处理
		{
			printf("已成功找到要插入数据\n");
			p ->next = q->next;
			k++;
			head->data.length--;
			break;
		}
		else
		{
			p = p->next;
			q = q->next;
		}
	}
	if (k == 0)
	{
		printf("未找到数据\n");
	}
	return head;
}

(3)改变链表数据(查到目标数据进行修改,可以借鉴这个进行另一种删除)

Lp* Chooselist(Lp* head)
{
	if (head == NULL)
	{
		printf("请初始化在进行其他功能!");
		return head;
	}
	Lp* p = head->next;
	printf("请输入你要修改学生的姓名+首个成绩:");
	char name[16];
	scanf("%s", name);
	int a;
	scanf("%d", &a);
	int k = 0;
	while (p->next != NULL)
	{
		if (strcmp(p->data.name, name) == 0 && p->data.a[0] == a)
		{
			printf("查询到你要修改的数据\n");
			printf("请输出要修改的数据的姓名:");
			scanf("%s", p->data.name);
			printf("请输入学生六科成绩:");
			for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
			{
				scanf("%d", &p->data.a[i]);
			}
			break;
		}
		else
		{
			p = p->next;
		}
	}
	return head;
}

##求最值问题(按照总分大小进行比,但是写的是average不要介意呦!)

因为在排序中要用到总值函数所以设立两个函数!
注意:一定要给average赋初值(当时一直以为是排序问题,没想到出错在这)

Lp* Maxlist(Lp* head)
{
	//这里在结构体里加了一个 int average 来进行比较
	Lp* p = head->next;//因为头节点数据域为空
	while (p->next != NULL)
	{
		for (int i = 0; i < sizeof(p->data.a) / sizeof(p->data.a[0]); i++)
		{
			p->data.average += p->data.a[i];
		}
		p = p->next;
	}
	return head;
}
void Maxoutput(Lp* head)
{
	Lp* p;
	p = head->next;
	Lp *max=NULL;
	max = p;
	while (p->next != NULL)
	{
		if (p->data.average > max->data.average)
		{
			max = p;
		}
		p = p->next;
	}
	printf("%s:", max->data.name);
	for (int i = 0; i < sizeof(p->data.a) / sizeof(p->data.a[0]); i++)
	{
		printf("%d\n", max->data.a[i]);
	}
	printf("\n");
}

##排序问题!!(服了,折腾我这么长时间)

排序算法(1,是进行数据域的交换,2是指针域的交换)

1数据域交换的思路:(采用的冒泡,这里区别的是在交换数据,直接把节点的数据域进行交换,推荐两个结构体)原来排序是i<n-1;这里直接改成p->next->next != NULL,并且内循环是q->next->next!=NULL;相比于下标这里没有了每次在内循环减一操作,

也可以用下标法,这里我们长度已经给了,亦可以用,(下标法没写,这个简单)

两者区别是:一个需要长度,另一个不需要长度

2:指针域交换的思路:我们已经测量了长度,就可以避免了q->NULL的交换了,这里我们交换不是设置中间变量的简单交换,例如p=head->next;q=p->next;交换后要写成,p->next=q->next;

q->next=p;!不推荐使用临时变量去交换!

因为p 和q 在动,我们要在往后遍历时推荐设一个第三方变量 move并且由move去引导进行两两相邻的比较!

3总结:指针域交换适合数据域非常大的时候,数据域交换适合数据域较少的因为涉及到数据域的拷贝

Lp* Sortkaozhilist(Lp* head)
{
	printf("按照平均分从小到大的写法且按照拷贝数据域方法进行\n");
	Lp* Maxlist(Lp * head);//声明
	head = Maxlist(head);
	Lp* p = head->next;//控制外循环
	Lp* q = head->next;//控制内循环
	for (; p->next->next != NULL; p = p->next)
	{
		for (q=head->next;q->next->next != NULL; q = q->next)//这样写有个不好的,这是是全部进行比较,不是每次少一个但是这样写的好处是不用测量长度!在数据少这样写的快
			//这里我想了想设立了一个下标操作!这样写的好处是不用测量长度!
		{
				if (q->next != NULL || q != NULL)//防止越界
				{
					if (q->data.average > q->next->data.average)
					{
						lp t;//作为中间变量进行替换
						t = q->data;
						q->data = q->next->data;
						q->next->data = t;
					}
				}
		}
	}
	return head;
}
Lp* Sortzhizhenlist(Lp* head)
{
	printf("进行的是指针域的改变按照从大到小(适合大数据)\n");
	printf("并且是下标法的冒泡排序\n");
	printf("请检验下标的数据为:%d\n", head->data.length);
	Lp* Maxlist(Lp * head);//声明函数
	head = Maxlist(head);
	Lp* p = head->next;
	Lp* q = head->next->next;//p的后节点
	Lp* move=head;//因为p和q指针域发生变化,所以需要用move去遍历
	for (int i = 0; i < head->data.length-1; i++)
	{
		p = head->next;
		q = p->next;
		move = head;//初始化
		for (int j = 0; j < head->data.length - 1 - i; j++)
		{
			
			if (p->data.average <q->data.average)
			{
				p->next = q->next;//把p后面那个节点的指针域给p->next;
				q->next = p;//原本时p指向q,现在是q指向p
				move->next = q;//找到要移动的位置
			}//交换相邻指针域使最少的放在后面;
 
			move = move->next;//这样是每次往后进行相邻比较
			p = move->next;
			q = p->next;//往后移
		}
		  
	}
	return head;
}
Lp* sortmenu(Lp* head)
{
	void Outputlist(Lp * head);//声明
	int a = 0;
	printf("***************************\n");
	printf("1拷贝值排序(适合数据小的)\t2指针域排序(有点不同)\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择排序的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Sortkaozhilist(head); break;
		case 2:head = Sortzhizhenlist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}

##可运行总代码:

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h> 
typedef struct Data
{
	int a[6];
	char name[16];
	int average;
	int length;
}lp;//创建这个结构体是为了高效进行冒泡排序
typedef struct student
{
	lp data;
	struct student* next;
}Lp;
void mima(int* flag2)
{
	int j = 6;
	char mima[20];
	int i = 0;
	while (1)
	{
		i = 0;
		printf("请输入用户名:");
		char name[16];
		scanf("%s", name);
		printf("请输入密码:");

		while (1)
		{
			mima[i] = _getch();
			if (mima[i] == '\r')
			{
				mima[i] = '\0';
				break;
			}
			else if (mima[i] == '\b')
			{
				mima[i] = '\0';
				printf("\b");
				printf(" ");
				printf("\b");
				i--;
				continue;
			}
			else
			{
				printf("*");
				i++;
				if (i == 19)
				{
					printf("密码已达到最大长度!\n");
					break;
				}
			}

		}
		if (strcmp(name, "小明") == 0)
		{
			if (strcmp(mima, "2082716421") == 0)
			{
				*flag2 = 2;
				printf("输入正确!\n");
				break;
			}
			else
			{
				j--;
				printf("账户或密码错误!\n");
				printf("你还有%d次机会\n", j);

				if (j == 0)
				{
					printf("已达到输入密码最多次数\n");
					break;
				}
			}
		}
		else
		{
			j--;
			printf("查询不到用户!\n");
			printf("你还有%d次机会\n", j);
			if (j == 0)
			{
				printf("已达到输入密码最多次数\n");
				break;
			}
		}
	}
}
void menu()
{
	printf("**********************************************************\n");
	printf("1数据的创建 \t2数据的插入\t3数据的删除\n4数据的更改\t5求数据最大值\t6数据的排序\n7输出数据\t8退出\t\
9清屏\n");
	printf("********************************************************\n");
}
Lp* Creatlist(Lp* head)
{
	head = (Lp*)malloc(sizeof(Lp));//头节点不要在数据域存数据
	Lp* p = head, * q = NULL;
	head->data.length = 0;//确定链表的长度
	while (1)
	{
		q = (Lp*)malloc(sizeof(Lp));
		p->next = q;
		p = q;
		printf("请输入%d位学生姓名:", head->data.length + 1);
		scanf("%s", p->data.name);
		if (strcmp(p->data.name, "结束输入") == 0)
		{
			break;
		}
		printf("请输入%d位学生六科成绩:", head->data.length + 1);
		for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
		{
			scanf("%d", &p->data.a[i]);
		}
		head->data.length++;

	}
	p->next = NULL;
	return head;
}
Lp* Insertmenu(Lp* head)
{
	int a=0;
	Lp* Insertlist(Lp * head);
	Lp* Inserfirsttlist(Lp * head);
	void Outputlist(Lp * head);//声明函数
	printf("***************************\n");
	printf("1,插入首位\t2插入某个人数据后面\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择插入的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Inserfirsttlist(head); break;
		case 2:head = Insertlist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}
Lp* Inserfirsttlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	printf("你进入的是插入首链节选择!\n");
	Lp* p, * q;
	Lp* m = head->next;//存放首个数据域的节点
	p = head;
	q = (Lp*)malloc(sizeof(Lp));//开辟空间
	printf("请输入插入的学生姓名:");
	scanf("%s", q->data.name);
	printf("请输入%该学生六科成绩:");
	for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
	{
		scanf("%d", &q->data.a[i]);
	}
	head->data.length++;//测长度
	p->next = q;
	q->next = m;
	return head;
}
Lp* Insertlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请初始化在进行其他操作!");
		return head;
	}//检验是否位为空条件
	char name[16];
	int a;
	printf("请输入要插入那个人的姓名+首个成绩:");
	scanf("%s", name);
	scanf("%d", &a);
	Lp* p = head->next, * q;//头节点为指针域为空
	Lp* m = head->next->next;//紧跟着存放p的后继位!方便插入
	int k = 0;//检验是否找到数据
	while (p->next != NULL)
	{
		if (strcmp(p->data.name, name) == 0 && p->data.a[0] == a)
		{
			printf("已成功找到要插入数据\n");
			q = (Lp*)malloc(sizeof(Lp));
			printf("请输入学生姓名:");
			scanf("%s", q->data.name);
			printf("请输入学生六科成绩:");
			for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
			{
				scanf("%d", &q->data.a[i]);
			}
			head->data.length++;//长度
			p->next = q;
			q->next = m;
			k++;
			break;//找到后直接跳出循环
		}
		else
		{
			p = p->next;
			m = m->next;
		}//保持链表向后进行
	}
	if (k == 0)
	{
		printf("未找到数据\n");
	}
	return head;
}
Lp* Deletelist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	Lp* p = head;
	Lp* q = head->next;//p后的链结
	printf("请输入要插入那个人的姓名+首个成绩:");
	char name[16];
	int a;
	int k = 0;//检验是否找到数据
	scanf("%s", name);
	scanf("%d", &a);
	while (p->next != NULL)
	{
		if (strcmp(q->data.name, name) == 0 && q->data.a[0] == a)//这里不能用p->next来因为无法对目标数据进行处理
		{
			printf("已成功找到要插入数据\n");
			p ->next = q->next;
			k++;
			head->data.length--;
			break;
		}
		else
		{
			p = p->next;
			q = q->next;
		}
	}
	if (k == 0)
	{
		printf("未找到数据\n");
	}
	return head;
}
Lp* Deletefirstlist(Lp* head)
{
	if (head == NULL)
	{
		printf("请先初始化在进行其他操作");
		return head;
	}//判断是否初始化创建链表
	Lp* p = head;//用来跳过首个有数据的链结
	Lp* q = head->next->next;//注意这里不在是开辟空间啦,这是有数据的链结后的链结
	p->next = q;
	head->data.length--;
	return head;
}
Lp* Deletemenu(Lp* head)
{
	void Outputlist(Lp * head);//声明
	int a = 0;
	printf("***************************\n");
	printf("1,删除首位\t2删除某个人数据后面\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择删除的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Deletefirstlist(head); break;
		case 2:head = Deletelist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}
Lp* Chooselist(Lp* head)
{
	if (head == NULL)
	{
		printf("请初始化在进行其他功能!");
		return head;
	}
	Lp* p = head->next;
	printf("请输入你要修改学生的姓名+首个成绩:");
	char name[16];
	scanf("%s", name);
	int a;
	scanf("%d", &a);
	int k = 0;
	while (p->next != NULL)
	{
		if (strcmp(p->data.name, name) == 0 && p->data.a[0] == a)
		{
			printf("查询到你要修改的数据\n");
			printf("请输出要修改的数据的姓名:");
			scanf("%s", p->data.name);
			printf("请输入学生六科成绩:");
			for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
			{
				scanf("%d", &p->data.a[i]);
			}
			break;
		}
		else
		{
			p = p->next;
		}
	}
	return head;
}
Lp* Sortkaozhilist(Lp* head)
{
	printf("按照平均分从小到大的写法且按照拷贝数据域方法进行\n");
	Lp* Maxlist(Lp * head);//声明
	head = Maxlist(head);
	Lp* p = head->next;//控制外循环
	Lp* q = head->next;//控制内循环
	for (; p->next->next != NULL; p = p->next)
	{
		for (q=head->next;q->next->next != NULL; q = q->next)//这样写有个不好的,这是是全部进行比较,不是每次少一个但是这样写的好处是不用测量长度!在数据少这样写的快
			//这里我想了想设立了一个下标操作!这样写的好处是不用测量长度!
		{
				if (q->next != NULL || q != NULL)//防止越界
				{
					if (q->data.average > q->next->data.average)
					{
						lp t;//作为中间变量进行替换
						t = q->data;
						q->data = q->next->data;
						q->next->data = t;
					}
				}
		}
	}
	return head;
}
Lp* Sortzhizhenlist(Lp* head)
{
	printf("进行的是指针域的改变按照从大到小(适合大数据)\n");
	printf("并且是下标法的冒泡排序\n");
	printf("请检验下标的数据为:%d\n", head->data.length);
	Lp* Maxlist(Lp * head);//声明函数
	head = Maxlist(head);
	Lp* p = head->next;
	Lp* q = head->next->next;//p的后节点
	Lp* move=head;//因为p和q指针域发生变化,所以需要用move去遍历
	for (int i = 0; i < head->data.length-1; i++)
	{
		p = head->next;
		q = p->next;
		move = head;//初始化
		for (int j = 0; j < head->data.length - 1 - i; j++)
		{
			
			if (p->data.average <q->data.average)
			{
				p->next = q->next;//把p后面那个节点的指针域给p->next;
				q->next = p;//原本时p指向q,现在是q指向p
				move->next = q;//找到要移动的位置
			}//交换相邻指针域使最少的放在后面;
 
			move = move->next;//这样是每次往后进行相邻比较
			p = move->next;
			q = p->next;//往后移
		}
		  
	}
	return head;
}
Lp* sortmenu(Lp* head)
{
	void Outputlist(Lp * head);//声明
	int a = 0;
	printf("***************************\n");
	printf("1拷贝值排序(适合数据小的)\t2指针域排序(有点不同)\t3退出\t4输出\n");
	while (a != 888)
	{
		printf("请输入你要选择排序的功能:");
		scanf("%d", &a);
		switch (a)
		{
		case 1:head = Sortkaozhilist(head); break;
		case 2:head = Sortzhizhenlist(head); break;
		case 3: a = 888;//退出循环条件
			break;
		case 4:Outputlist(head); break;
		default:printf("请输入1—4的数据"); break;
		}
	}
	return head;
}
Lp* Maxlist(Lp* head)
{
	//这里在结构体里加了一个 int average 来进行比较
	Lp* p = head->next;//因为头节点数据域为空
	while (p->next != NULL)
	{
		//这里给p->data.average赋初值;
		p->data.average = 0;
		for (int i = 0; i < sizeof(p->data.a) / sizeof(p->data.a[0]); i++)
		{
			p->data.average += p->data.a[i];
		}
		p = p->next;
	}
	return head;
}
void Maxoutput(Lp* head)
{
	Lp* p;
	p = head->next;
	Lp *max=NULL;
	max = p;
	while (p->next != NULL)
	{
		if (p->data.average > max->data.average)
		{
			max = p;
		}
		p = p->next;
	}
	printf("%s:", max->data.name);
	for (int i = 0; i < sizeof(p->data.a) / sizeof(p->data.a[0]); i++)
	{
		printf("%d\n", max->data.a[i]);
	}
	printf("\n");
}
void Outputlist(Lp* head)
{
	Lp* p; p = head->next;//头节点没有数据所以是head->next;
	while (p->next != NULL)
	{
		printf("%s:\t", p->data.name);
		for (int i = 0; i < sizeof(head->data.a) / sizeof(head->data.a[0]); i++)
		{
			printf("%d\t", p->data.a[i]);
		}
		printf("\n");
		p = p->next;
	}
}
int main()
{
	//为了数据的检验方便没有设置及时清屏功能,请见谅
	int flag2 = 0;//检验密码登录系统的正确行
	/*mima(&flag2);*/
	flag2 = 1;
	Lp* head = NULL;
	if (flag2 != 0)
	{
		int Tc = 0;//选择菜单的退出
		menu();
		int choose = 0;//菜单选择的变量
		while (Tc == 0)
		{
			printf("请选择功能:");
			scanf("%d", &choose);
			switch (choose)
			{
			case 1:head = Creatlist(head); break;
			case 2: head = Insertmenu(head); break;
			case 3:head = Deletemenu(head); break;
			case 4:head = Chooselist(head); break;
			case 6:head = sortmenu(head); break;
			case 5:if (head = Maxlist(head))Maxoutput(head);break;
			case 7:Outputlist(head); break;
			case 8:Tc = 1; break;
			case 9:system("cls"); system("pause"); menu(); break;
			default:printf("请输入1—9选择功能");
			}
		}

	}
	return 0;
}

##学习之作
此为学习上的见解,若有错误或不同理解欢迎大家的批评与改正(第一次写,排版可能有问题,请见谅)文章来源地址https://www.toymoban.com/news/detail-856008.html

到了这里,关于在c语言中使用链表完成学生成绩管理系统(密码登录系统的采纳,加入了隐藏与删除功能,添加了指针域与数据域两种不同的排序)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言课程设计-学生成绩管理系统

    需求分析: 1.设计题目:学生成绩管理系统 2.系统功能需求分析:实现对学生各科成绩总分及平均分的排序,和成绩的查找 概要设计 1. 功能模块图 详细设计 1. 流程图 测试结果 :列出所有功能的运行界面,并作文字说明。 1.录入成绩:录入3个人的学号和各科成绩 2.每门课程

    2024年02月11日
    浏览(49)
  • C语言编程学生成绩管理系统

    目录 一、介绍 二、功能 1.录入学生 2.删除学生信息 3.修改学生信息 4.查询学生信息 5.所有学生信息 6.成绩排序  7.退出程序 三、代码 1.主函数 2.头文件 3.函数封装库         利用C语言,运用链表、指针、封装函数等基本知识实现一个学生管理系统。通过在终端对学生信息进

    2024年02月10日
    浏览(52)
  • C语言学生成绩管理系统(综合项目)

    1. 这个代码主要实现以下功能: 2. 用到的主要参数有:     1.整型变量int n;用于储存学生人数和之后的循环判断。     2.字符串char name[][];用于储存姓名。     3.浮点型变量float score[];用于储存成绩。     4.长整型变量long ID[Max];用于储存学号。 3.用到的子函数有: int  Menu(

    2024年02月11日
    浏览(43)
  • 学生成绩管理系统——C语言版(含源码)

    一、开发环境 操作系统:Ununtu 16 开发环境工具:vscode 开发语言:C语言 二、功能需求 制作学生管理系统 在系统中能够实现 录入学生信息、帮助菜单、列出学生信息、计算总成绩平均值、根据总成绩平均值完成排序、根据学号查询学生信息、清屏、退出等功能。 三、功能说

    2024年02月08日
    浏览(49)
  • 学生成绩管理系统(C语言)(数组结构体)

    学生成绩管理系统 利用结构体、排序查找算法以及模块化程序设计实现如下菜单驱动的学生成绩管理系统: 1) 首次批量输入每个学生的学号、姓名、和各科考试成绩。 2) 增添一个新学生的信息。 3) 增添一门新的学科的信息。 4) 按学生姓名或学号查询、修改、删除学生信

    2024年02月09日
    浏览(44)
  • C语言课程设计_学生成绩管理系统

    设计一个学生成绩排名系统。 1)  具备对成绩的管理功能(添加、删除、排序) 2)  具备对成绩的统计功能(最高分,最低分,平均分,及格率等) 3)  具备按学号、姓名、或课程名查询成绩的功能。 4)学生成绩应该保存在文件中。 备注:成绩记录以下信息:班级,学号,

    2024年02月11日
    浏览(46)
  • 学生成绩管理系统(C语言有结构体实现)

    本文章介绍了一个通过C语言实现的一个简单的学生管理系统,该系统要是使用结构体数组来管理学生成绩数据的,通过该系统的练习能够对结构体的相关知识有更好的理解,提高逻辑思维能力。 系统运行,打开如下界面。列出系统帮助菜单(即命令菜单),提示输入命令 开

    2024年02月06日
    浏览(79)
  • C语言学生成绩信息管理系统(超详细版)

    主题:一个简易成绩管理系统 功能介绍: 1.以文本形式存储学生信息 2.对以存信息进行   1. 插入 2. 修改3. 删除  4.查询  5.成绩数字特征 目录 一:分析 二:查询  三:菜单 四:初始化函数 五:插入函数 六:修改函数 七:删除函数 八:数字特征 九:显示函数 要进行 插入

    2024年02月12日
    浏览(43)
  • ChatGPT实现用C语言写一个学生成绩管理系统

    随着ChatGPT爆火,大家都在使用ChatGPT来帮助自己提高效率,对于程序员来说使用它来写代码怎么样呢?今天尝试让ChatGPT,写了一个学生成绩管理系统。 问题是:使用C语言写一个学生成绩管理系统,要求使用链表,实现增删改查功能。 下面是ChatGPT写的代码,用时不到30秒,速

    2023年04月13日
    浏览(51)
  • C语言课程设计:学生成绩信息管理系统(排序、平均分、总分)详解

    1、需求分析 利用C语言编写一个可以对学生成绩信息进行管理的系统 0、退出系统 1、录入学生信息和成绩 2、打印学生信息 3、统计学生人数 4、查找学生信息 5、修改学生信息 6、删除学生信息 7、排序学生成绩 8、生成学生信息文件 9、读取文件学生信息 10、输出各科成绩不

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包