学习B站up主C3程序猿的视频后总结分享【学生管理系统】_哔哩哔哩_bilibili【学生管理系统】https://www.bilibili.com/video/BV1uW411Q7Cf?spm_id_from=333.999.0.0
#include#include #include //学生结点 typedef struct _STU { char arrStuName[20]; char arrStuNum[100]; int iStuScore; struct _STU* pNext; }STUNODE; //声明链表的头和尾 STUNODE* g_pHead = NULL;//全局变量用g_ STUNODE* g_pEnd = NULL; void menu();//主菜单 void AddStuMSG(char* arrStuNum, char* arrStuName, int iStuScore);//添加一个学生的信息(尾添加) void FreelinkData();//清空链表 void ShowStuData();//打印数据 void AddStuMSGTolinkHead();//链表头添加一个结点(头添加) STUNODE* FindStuByNum(char* arrStuNum);//查找指定学生信息 void InsertNode(STUNODE* pTemp, char* arrStuNum, char* arrStuName, int iStuScore);//特定位置插入结点 先连接再断开 void DeleteStuNode(STUNODE* pNode);//删除指定学生信息 void SaveStuToFile();//保存学生信息到文件中 void ReadStuFromFile();//读取文件中的文件信息 void FixStuByNum(STUNODE* pTemp,int target,char* strFixedData);//修改指定学生信息(学号,目标修改数据,用于替换的数) int main() { int iOrder = -1; char arrStuNum[20] = { '' }; char arrStuName[20] = { '' }; int iStuScore = -1; int flag = 1; //打印菜单 menu(); while(flag) { printf("请输入指令n"); scanf("%d", &iOrder); switch (iOrder) { case 0: //todo退出程序 flag = 0; break; case 1: //todo 尾添加一个学生信息 printf("请输入学生姓名:"); scanf("%s", arrStuName); printf("请输入学号:"); scanf("%s", arrStuNum); printf("请输入学生分数:"); scanf("%d", &iStuScore); AddStuMSG(arrStuNum, arrStuName, iStuScore); fflush(stdin); break; case 2: //todo 头添加一个学生信息 printf("请输入学生姓名:"); scanf("%s", arrStuName); printf("请输入学号:"); scanf("%s", arrStuNum); printf("请输入学生分数:"); scanf("%d", &iStuScore); AddStuMSGTolinkHead(arrStuNum, arrStuName, iStuScore); fflush(stdin); break; case 3: { //在switch中添加临时变量需要加花括号 //todo 指定位置添加学生信息 STUNODE* pTemp = NULL; printf("请输入所插入位置之前的学号:"); scanf("%s", arrStuNum); pTemp = FindStuByNum(arrStuNum); fflush(stdin); if (NULL != FindStuByNum(arrStuNum)) { //todo 插入新学生信息结点 printf("请输入学生姓名:"); scanf("%s", arrStuName); printf("请输入学号:"); scanf("%s", arrStuNum); printf("请输入学生分数:"); scanf("%d", &iStuScore); InsertNode(pTemp, arrStuNum, arrStuName, iStuScore); // 1 lsr 2107010111 100 2 mzw 2107010112 101 3 2107010112 lyd 2107010113 102 测试数据 } fflush(stdin); break; } case 4: { //todo 打印指定学生的信息 STUNODE* pTemp = NULL; //输入一个学号 printf("请输入需要查找学生的学号:"); scanf("%s", arrStuNum); //查找 pTemp = FindStuByNum(arrStuNum); //打印 if (NULL != pTemp) { printf("姓名:%s,学号:%s,分数:%dn", pTemp->arrStuName, pTemp->arrStuNum, pTemp -> iStuScore); } break; } case 5: //todo 修改指定学生的信息 { int target = -1; //学号:1, 姓名 : 2,成绩:3. char strStuNum[20] = { 0 }; char strFixedData[20] = {0}; STUNODE* pTemp = NULL; printf("请输入想要修改学生的学号:"); scanf("%s", strStuNum); pTemp = FindStuByNum(strStuNum); if (pTemp == NULL) { break; } else { printf("请输入你想要修改的数据(1:学生学号,2:学生姓名,3:学生成绩):"); scanf("%d", &target); printf("请输入你想要修改后的数据:"); scanf("%s", strFixedData); FixStuByNum(pTemp, target,strFixedData); printf("修改成功n"); } } break; case 6: //todo 保存学生信息到文件中 SaveStuToFile(); break; case 7: //todo 读取文件中的文件信息 ReadStuFromFile(); break; case 8: { //todo 删除指定学生信息 STUNODE* pTemp=NULL; //输入一个学号 printf("请输入要删除学生的学号:"); scanf("%s", arrStuNum); //查找 pTemp = FindStuByNum(arrStuNum); //删除这个节点 if (NULL != pTemp) { //调用删除函数 DeleteStuNode(pTemp); } break; } case 9: //todo 恢复删除学生的信息 //清空链表 FreelinkData(); g_pHead = NULL; g_pEnd = NULL; //恢复结点 ReadStuFromFile();//从文件中恢复结点 printf("恢复成功n"); break; case 10: //打印学生数据 ShowStuData(); break; case 11: //再次打印菜单 menu(); break; default: printf("无效指令!n"); } } //释放链表 FreelinkData(); return 0; } void menu() { printf("********************学生信息管理系统**********************n"); printf("*********************本系统 *** 作如下***********************n"); printf("*** 1.增加一个学生信息(尾添加) ***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("*** 10.显示所有学生的信息 ***n"); printf("*** 11.再次打印菜单 ***n"); printf("*** 0.退出系统 ***n"); printf("**********************************************************n"); } //do添加一个学生的信息 void AddStuMSG(char* arrStuNum, char* arrStuName, int iStuScore) //分数,学生名,学号 **数组做参数,其实是一个指针 { //第一步 检验参数的合法性 if (NULL == arrStuNum || NULL == arrStuName || iStuScore < 0) { printf("学生信息输入错误n"); return; } //第二步 逻辑处理 //1.创建一个结点 STUNODE* pTemp = malloc(sizeof(STUNODE)); //2.对结点内成员赋值 //pTemp->arrStuNum=arrStuNum; 这种写法是错误的,因为传进来的参数是地址。 strcpy(pTemp->arrStuNum, arrStuNum); strcpy(pTemp->arrStuName, arrStuName); pTemp->iStuScore = iStuScore; pTemp->pNext = NULL; //赋值完成 //3.将结点接在链表上(**使用尾连接) if (NULL == g_pHead || NULL == g_pEnd) //添加的第一个结点 { g_pHead = pTemp; g_pEnd = pTemp; } else //直接在尾巴添加 { g_pEnd->pNext = pTemp; //链接结点 g_pEnd = pTemp; //尾巴向后移动 } } //do清空链表 void FreelinkData() { STUNODE* pTemp = g_pHead; while (g_pHead != NULL) { pTemp = g_pHead; //记录结点 g_pHead = g_pHead->pNext; //头结点后移 free(pTemp); //删除结点 } } //do打印数据 void ShowStuData() { STUNODE* pTemp = g_pHead; printf("学生姓名 学号 分数n"); while (pTemp != NULL) { printf("%-15s%-12s%-10dn", pTemp->arrStuName, pTemp->arrStuNum, pTemp->iStuScore); pTemp = pTemp->pNext; } } //do链表头添加一个结点(头添加) void AddStuMSGTolinkHead(char* arrStuNum, char* arrStuName, int iStuScore) { STUNODE* pTemp = malloc(sizeof(STUNODE)); //检测参数的合法性 if (NULL == arrStuName || NULL==arrStuName || iStuScore < 0) { printf("学生信息输入错误n"); return; } strcpy(pTemp->arrStuNum, arrStuNum); strcpy(pTemp->arrStuName, arrStuName); pTemp->iStuScore = iStuScore; pTemp->pNext = NULL; if (NULL == g_pHead || NULL == g_pEnd)//链表为空的时候 { g_pHead = pTemp; g_pEnd = pTemp; } else { pTemp->pNext = g_pHead;//新结点的下一个指向头 g_pHead = pTemp; } } //do 查找指定学生信息 STUNODE* FindStuByNum(arrStuNum) { STUNODE* pTemp = g_pHead; if (NULL == arrStuNum)//检测输入 { printf("学号输入错误n"); return NULL; } if (NULL == g_pHead || NULL == g_pEnd)//链表为空 { printf("学号输入错误n"); return NULL; } else {//遍历链表 while (pTemp != NULL) { if (0==strcmp(pTemp->arrStuNum, arrStuNum)) { return pTemp; } pTemp = pTemp->pNext; } } printf("未查找到该生信息n"); return NULL; } //do 特定位置插入结点 void InsertNode(STUNODE* pTemp, char* arrStuNum, char* arrStuName, int iStuScore) { //创建结点 STUNODE* pNewTemp = malloc(sizeof(STUNODE)); //成员赋值 strcpy(pNewTemp->arrStuNum, arrStuNum); strcpy(pNewTemp->arrStuName, arrStuName); pNewTemp->iStuScore = iStuScore; pNewTemp->pNext = NULL; //赋值完成 if (pTemp = g_pEnd)//判断是不是尾结点 { g_pEnd->pNext = pNewTemp; g_pEnd = pNewTemp; } else { pNewTemp->pNext = pTemp->pNext; pTemp->pNext = pNewTemp; } } //do 删除指定学生信息 void DeleteStuNode(STUNODE* pNode) { //只有一个结点 if (g_pHead == g_pEnd) { free(g_pHead); g_pEnd = NULL; g_pHead = NULL; printf("信息删除成功!n"); return; } else if(g_pHead->pNext==g_pEnd)//两个结点 { if (g_pHead == pNode) { free(g_pHead); g_pHead = g_pEnd; printf("信息删除成功!n"); return; } else { free(g_pEnd); g_pEnd = g_pHead; g_pHead->pNext = NULL;//防止指针仍指向原地址导致错误 printf("信息删除成功!n"); return; } } else//常规情况(结点数>=3) { STUNODE* pTemp = g_pHead; if (g_pHead == pNode)//判断头 { pTemp = g_pHead;//记录头 g_pHead = g_pHead->pNext; free(pTemp); pTemp=NULL; printf("信息删除成功!n"); return; } while(pTemp != NULL) { if (pTemp->pNext == pNode)//头结点为目标结点的情况在之前已经判断过,此处从第二个结点开始判断 { //删除 if (g_pEnd == pNode)//判断尾 { free(pNode); pNode = NULL; g_pEnd = pTemp; printf("信息删除成功!n"); return; } else { //记录要删除的节点 STUNODE* p = pTemp->pNext; // pTemp->pNext = pNode->pNext;//连接 free(p); p=NULL; printf("信息删除成功!n"); return; } } pTemp = pTemp->pNext; } } } //do 保存学生信息到文件中 void SaveStuToFile() { STUNODE* pTemp = g_pHead; FILE* pFile = NULL; char strBuf[60] = { 0 }; char strScore[10] = { 0 }; //判断链表是否为空 if (NULL == g_pHead) { printf("链表为空,未录入学生信息!n"); return; } //打开文件 pFile = fopen("dat.dat", "wb+");//打开的文件地址,打开方式(此处为可读可写) if (NULL == pFile) { printf("文件打开失败n"); return; } // *** 作文件指针 while (pTemp)//遍历链表 { //学号赋值 strcpy(strBuf, pTemp->arrStuNum); strcat(strBuf, ".");//分隔文件中的元素,便于查看和读取 //姓名赋值 strcat(strBuf, pTemp->arrStuName);//在字符串末尾连接 strcat(strBuf, "."); //分数赋值 _itoa(pTemp->iStuScore, strScore,10); //组合字符串 strcat(strBuf, strScore); fwrite(strBuf,1,strlen(strBuf),pFile);//程序中的字符串,目标数量,单个目标所占字节,指针 fwrite("rn", 1, strlen("rn"), pFile); pTemp = pTemp->pNext; } //关闭文件 fclose(pFile); } //do 读取文件中的文件信息 void ReadStuFromFile() { FILE* pFile = fopen("dat.dat", "rb+"); char strBuf[60] = { 0 }; char strStuNum[20] = { 0 }; char strStuName[20] = { 0 }; char strStuScore[10] = { 0 };//不要忘记读入以后转化为整形 if (NULL == pFile) { printf("文件打开失败n"); return; } // *** 作指针,读取文件 while (NULL != fgets(strBuf, 60, pFile))//一次读取一行,参数:文件中内容存放的地方,字符数组大小,文件地址 注意EOF返回值 { int i = 0; int iCount = 0; int j = 0; for (i = 0; strBuf[i] != 'r'; i++)//行写入 { if (0 == iCount)//没有读到'.' { strStuNum[i] = strBuf[i]; if('.'==strBuf[i]) { strStuNum[i] = ''; iCount++; } } else if (1 == iCount)//读到第一个'.' { strStuName[j] = strBuf[i]; if('.' == strBuf[i]) { strStuName[j] = ''; iCount++; j = 0; continue;//跳过循环,防止运行下面的j++ } j++; } else//读到第二个'.' { strStuScore[j] = strBuf[i]; j++; } } //插入到链表 AddStuMSG(strStuNum, strStuName, atoi(strStuScore)); } fclose(pFile); } //do 修改指定学生信息(目标结点,目标修改数据,用于替换的数) void FixStuByNum(STUNODE* pTemp, int target, char* strFixedData) { if (target == 3) { pTemp->iStuScore = atoi(strFixedData); } else if (target == 2) { strcpy(pTemp->arrStuName, strFixedData); } else { strcpy(pTemp->arrStuNum, strFixedData); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)