C语言 学生管理系统

链表操作实战之学生管理系统,由于使用VS2017IDE,有一些写法采用C++


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>

using namespace std;

typedef struct STU
{
	char arrStuNum[20]; // 学号
	char arrStuName[20]; // 姓名
	int iStuScore;       // 学生分数
	struct STU *next;
}STUNODE;

// 声明链表的头和尾
STUNODE* g_pHead = NULL;
STUNODE* g_pEnd = NULL;

// 添加一个学生的信息(从表尾)
void AddStuMSG(char *arrStuNum, char *arrStuName, int iStuScore);
// 添加一个学生的信息(从表头)
void AddStuLinkHead(char *arrStuNum, char *arrStuName, int iStuScore);
// 添加一个学生的信息(从指定位置)
void insertNode(STUNODE *pTemp, char *arrStuNum, char *arrStuName, int iStuScore);
// 清空链表
void FreeLinkData();
// 打印数据
void ShowStuData();
// 显示指令
void ShowOrder();
// 根据学号查找指定学生,返回结点的地址
STUNODE* FindStuByNum(char* arrStuNum);
// 删除指定的学生
void DeleteStuNode(STUNODE* pNode);
// 保存学生信息
void SaveStuFile();
// 读取文件中学生的信息
void ReadStuFile();

int main()
{
	// 显示操作界面
	ShowOrder();
	int nOrder=-1;
	char arrStuNum[20] = { '\0' };
	char arrStuName[20] = { '\0' };
	int iStuScore = -1;
	bool flag = true;
	STUNODE* ptemp;

	// 读取文件中学生信息
	ReadStuFile();
	printf("加载数据库数据成功\n");
	while (flag)
	{
		printf("请输入指令,输入0查看指令:\n");
		scanf_s("%d", &nOrder);
		switch (nOrder)
		{
		case 1:
			// 添加一个学生的信息(尾添加)
			printf("输入学号:");
			cin >> arrStuNum;
			printf("输入姓名:");
			cin >> arrStuName;
			printf("输入分数:");
			cin >> iStuScore;
			AddStuMSG(arrStuNum, arrStuName, iStuScore);
			break;
		case 11:
			// 添加一个学生的信息(头添加)
			printf("输入学号:");
			cin >> arrStuNum;
			printf("输入姓名:");
			cin >> arrStuName;
			printf("输入分数:");
			cin >> iStuScore;
			AddStuLinkHead(arrStuNum, arrStuName, iStuScore);
			break;
		case 111:
			// 添加一个学生的信息(从指定位置)
			printf("请输入要添加位置之前的学生的学号:\n");
			cin >> arrStuNum;
			ptemp = FindStuByNum(arrStuNum);
			if (ptemp == NULL)
				printf("无此学生信息\n");
			printf("输入学号:");
			cin >> arrStuNum;
			printf("输入姓名:");
			cin >> arrStuName;
			printf("输入分数:");
			cin >> iStuScore;
			insertNode(ptemp, arrStuNum, arrStuName, iStuScore);
			break;

		case 2:
			// 根据学号查找学生信息
			printf("请输入要查找学生的学号:\n");
			cin >> arrStuNum;
			ptemp = FindStuByNum(arrStuNum);
			if (ptemp != NULL)
				printf("学号:%s,姓名:%s,分数%d\n", ptemp->arrStuNum, ptemp->arrStuName, ptemp->iStuScore);
			else
				printf("无此学生信息\n");
			break;
		case 3:
			// 修改指定学生的信息
			// 根据学号查找学生信息
			printf("请输入要修改学生原来的学号:\n");
			cin >> arrStuNum;
			ptemp = FindStuByNum(arrStuNum);
			if (ptemp != NULL)
			{
				// 修改学号
				printf("输入修改的学号:\n");
				cin >> arrStuNum;
				strcpy_s(ptemp->arrStuNum, arrStuNum);

				// 修改名字
				printf("输入修改的姓名:\n");
				cin >> arrStuName;
				strcpy_s(ptemp->arrStuName, arrStuName);

				// 修改分数
				printf("输入修改的分数:\n");
				cin >> iStuScore;
				ptemp->iStuScore = iStuScore;
			}
			else
				printf("无此学生信息\n");
			break;
		case 4:
			// 保存学生信息
			SaveStuFile();
			printf("成功写入文件\n");
			break;
		case 5:
			// 从文件读取数据到链表
			ReadStuFile();
			break;
		case 6:
			// 根据学号,删除指定的学生信息
			printf("请输入要删除学生的学号\n");
			cin >> arrStuNum;
			ptemp = FindStuByNum(arrStuNum);
			if (ptemp != NULL)
				DeleteStuNode(ptemp);
			break;
		case 7:
			// 从文件恢复删除的学生的信息
			FreeLinkData();
			g_pHead = NULL;
			g_pEnd = NULL;
			ReadStuFile();
			break;

		case 8:
			// 显示链表内容
			ShowStuData();
			break;

		case 9:
			// 退出程序
			flag = false;
			break;
		case 0:
			// 显示指令
			ShowOrder();
			break;
		default:
			printf("输入指令不正确\n");
			break;
		}
	}
	
	// 释放链表
	FreeLinkData();
		
	

    return 0;
}

// 添加一个学生的信息
void AddStuMSG(char *arrStuNum, char *arrStuName, int iStuScore)
{
	// 检验参数的合法性
	if (arrStuNum == NULL || arrStuName == NULL || iStuScore < 0)
	{
		printf("学生信息输入错误\n");
		return;
	}

	STUNODE *pTemp;
	pTemp = (STUNODE*)malloc(sizeof(STUNODE));
	strcpy_s(pTemp->arrStuNum, arrStuNum);
	strcpy_s(pTemp->arrStuName, arrStuName);
	pTemp->iStuScore = iStuScore;
	pTemp->next = NULL;

	// 接在链表上
	if (g_pHead == NULL || g_pEnd == NULL)
	{
		g_pHead = pTemp;
		
	}
	else
	{
		g_pEnd->next = pTemp;
		
	}
	g_pEnd = pTemp;
}
// 从表头添加一个学生信息
void AddStuLinkHead(char *arrStuNum, char *arrStuName, int iStuScore)
{
	// 检验参数的合法性
	if (arrStuNum == NULL || arrStuName == NULL || iStuScore<0)
	{
		printf("学生信息输入错误\n");
		return;
	}
	// 添加节点
	STUNODE* pTemp = (STUNODE*)malloc(sizeof(STUNODE));
	strcpy_s(pTemp->arrStuNum, arrStuNum);
	strcpy_s(pTemp->arrStuName, arrStuName);
	pTemp->iStuScore = iStuScore;
	pTemp->next = NULL;

	if (g_pHead == NULL || g_pEnd == NULL)
	{
		
		g_pEnd = pTemp;
	}
	else
	{
		pTemp->next = g_pHead;
		
	}
	g_pHead = pTemp;

}
// 从任意位置添加一个学生信息
void insertNode(STUNODE *pTemp, char *arrStuNum, char *arrStuName, int iStuScore)
{
	// 创建节点
	STUNODE* ptemp = (STUNODE*)malloc(sizeof(STUNODE));
	strcpy_s(ptemp->arrStuNum, arrStuNum);
	strcpy_s(ptemp->arrStuName, arrStuName);
	ptemp->iStuScore = iStuScore;
	ptemp->next = NULL;
	// 在尾部插入
	if (pTemp == g_pEnd)
	{
		g_pEnd->next = ptemp;
		g_pEnd = ptemp;
	}
	else
	{
		ptemp->next = pTemp->next;
		pTemp->next = ptemp;
	}
}
//清空链表,从前往后清楚
void FreeLinkData()
{
	STUNODE* pTemp = g_pHead;
	while (g_pHead != NULL)
	{
		pTemp = g_pHead;
		// 向后移动一个
		g_pHead = g_pHead->next;
		free(pTemp);
	}
}

// 显示链表
void ShowStuData()
{
	STUNODE* pTemp = g_pHead;
	if (!pTemp)
	{
		printf("没有录入学生信息\n");
	}
	while (pTemp)
	{
		printf("学号:%s, 姓名:%s, 分数%d\n", pTemp->arrStuNum, pTemp->arrStuName, pTemp->iStuScore);
		pTemp = pTemp->next;

	}

}
// 显示指令
void ShowOrder()
{
	printf("********************学生信息管理系统********************\n");
	printf("********************本系统操作指令如下******************\n");
	printf("***              1. 增加一个学生信息(从表尾)         ***\n");
	printf("***             11. 增加一个学生信息(从表头)         ***\n");
	printf("***            111. 增加一个学生信息(从指定位置)     ***\n");
	printf("***              2. 查找指定学生的信息(姓名/学号)  ***\n");
	printf("***              3. 修改指定学生的信息               ***\n");
	printf("***              4. 保存业主的信息到文件中           ***\n");
	printf("***              5. 读取文件中的业主的信息           ***\n");
	printf("***              6. 删除指定学生的信息               ***\n");
	printf("***              7. 恢复删除的学生的信息             ***\n");
	printf("***              8. 显示所有的学生的信息             ***\n");
	printf("***              9. 退出系统                         ***\n");
	printf("********************************************************\n");
}

// 根据学号查找指定学生,返回结点的地址
STUNODE* FindStuByNum(char* arrStuNum)
{
	STUNODE* pTemp = g_pHead;
	// 检查参数的合法性
	if (arrStuNum == NULL)
	{
		printf("学号输入错误!\n");
		return NULL;
	}
	// 判断链表是否为空
	if (g_pHead == NULL || g_pEnd == NULL)
	{
		printf("链表为空\n");
		return NULL;
	}
	// 遍历链表
	while (pTemp)
	{
		// 字符串匹配函数
		if(strcmp(pTemp->arrStuNum, arrStuNum) == 0)
			return pTemp;
		pTemp = pTemp->next;
	}
	printf("查无此结点\n");
	return NULL;
}

// 删除指定节点
void DeleteStuNode(STUNODE* pNode)
{
	// 只有一个节点
	if (g_pHead == g_pEnd)
	{
		free(g_pHead);
		g_pHead = NULL;
		g_pEnd = NULL;
	}

	// 只有两个节点
	else if (g_pHead->next == g_pEnd)
	{
		if (g_pHead == pNode)
		{
			free(g_pHead);
			g_pHead = g_pEnd;
		}
		else
		{
			
			free(g_pEnd);
			g_pHead->next = NULL;
			g_pEnd = g_pHead;

		}
	}
	//  节点数>=3
	else
	{
		STUNODE *pTemp = g_pHead;
		// 删除位置在头节点
		if (g_pHead == pNode)
		{
			pTemp = g_pHead;
			g_pHead = g_pHead->next;
			free(pTemp);
			pTemp = NULL;
			return;
		}
		while (pTemp)
		{
			if (pTemp->next == pNode)
			{
				if (pNode == g_pEnd)
				{
					
					free(pNode);
					g_pEnd = pTemp;
					g_pEnd->next = NULL;
					return;
				}
				else
				{
					// 记住节点
					STUNODE *p = pNode;
					pTemp->next = pNode->next;
					free(p);
					return;
				}
			}
			pTemp = pTemp->next;
		}
	}
		
}

void SaveStuFile()
{
	FILE* pFile = NULL;
	STUNODE* pTemp = g_pHead;
	char strBuf[30] = { 0 };
	char strScore[10] = { 0 };
	// 判断链表是否为空
	if (g_pHead == NULL)
	{
		printf("没有学生\n");
		return;
	}
	// 打开文件
    fopen_s(&pFile,"dat.dat", "wb+");
	if (pFile == NULL)
	{
		printf("没有学生\n");
		return;
	}
	// 操作文件指针
	while (pTemp)
	{
		// 复制学号
		strcpy_s(strBuf, pTemp->arrStuNum);
		strcat_s(strBuf, " ");
		// 姓名
		strcat_s(strBuf, pTemp->arrStuName);
		strcat_s(strBuf, " ");
		// 分数
		_itoa_s(pTemp->iStuScore, strScore, 10);
		strcat_s(strBuf, strScore);
		fwrite(strBuf, 1, strlen(strBuf), pFile);
		fwrite("\r\n", 1, strlen("\r\n"), pFile);
		pTemp = pTemp->next;

	}
	// 关闭文件
	fclose(pFile);
}

// 从文件读取数据到链表
void ReadStuFile()
{
	FILE* pFile;
	fopen_s(&pFile, "dat.dat", "rb+");
	char strBuf[30] = { 0 };
	char strStuNum[20] = { 0 };
	char strStuName[20] = { 0 };
	char strScope[10] = { 0 };
	int nCount=0;
	int j = 0;
	if (pFile == NULL)
	{
		printf("文件打开失败\n");
		return;
	}
	// 操作指针, 读取函数
	while (fgets(strBuf, 30, pFile))
	{
		//printf("%s\n", strBuf);
		for (int i = 0; strBuf[i] != '\r'; i++)
		{
			if (nCount == 0)
			{
				strStuNum[i] = strBuf[i];
				if (strBuf[i] == ' ')
				{
					strStuNum[i] = '\0';
					nCount++;
					j = 0;
				}
			}
			else if (nCount == 1)
			{
				
				strStuName[j++] = strBuf[i];
				if (strBuf[i] == ' ')
				{
					j = 0;
					nCount++;
				}
			}
			else
			{
				strScope[j++] = strBuf[i];
				
			}
		}
		nCount = 0;
		strStuName[strlen(strStuName) - 1] = '\0';
		AddStuMSG(strStuNum, strStuName, atoi(strScope));
	}
	
	fclose(pFile);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值