一个有很多我改不出来的bug的学生管理系统(虽然能运行)

#include<stdio.h>
#include<stdlib.h> 
#include<string.h>
//添加一个学生的信息(在链表尾部) 
void AddStuMSG(char arrNum[10], char arrStuName[10], int iStuScore); //这里函数传递的参数之间用逗号隔开 
//清空链表
void  FreeLinkData();
//在链表头前面添加学生节点 
void AddStuMSGToLinkHead(char arrNum[10], char arrStuName[10], int iStuScore); 
//打印数据
void ShowStuData(); 
//显示指令
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("9:显示所有学生的信息\n");
    printf("0:退出系统\n");
    printf("**********************************\n");
}
//创建学生节点
typedef struct _STU{
    char arrNum[10];//学号 
    char arrStuName[10];//姓名 
    int iStuScore;//分数
    struct _STU *pNext; 
}STUNODE;
//查找指定学生(在上一个学生的后面添加,返回上一学生的地址,参数是上一学生的学号) 
STUNODE* FindStuBuNum(char*arrNum);
//指定位置插入节点
void InsertNode(STUNODE*pTemp,char arrNum[10], char arrStuName[10], int iStuScore); 
//void InsertNode(stu)
//删除指定学生
void DeleteStuByNode(STUNODE*pNode); 
//保存信息进文件
void SaveStuToFile();
//读取文件中的学生信息
void ReadStuFromFile(); 
//声明链表的头和尾,也就是定义指针,分别装着第一和最后节点的地址 
STUNODE* g_pHead = NULL;//全局变量前面加个g
STUNODE* g_pEnd = NULL; 
int main (void){
    int iOrder = -1;//定义命令 
    char arrNum[10] = {0};//学号 
    char arrStuName[10] = {0};//姓名 
    int iStuScore = -1;//分数
    int nFlag = 1;
    void ReadStuFromFile();//系统一启动,就要读取上次的信息 
    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("9:打印所有学生信息\n");
    printf("0:退出系统\n");
    printf("**********************************\n");
    while(nFlag){
        printf("请输入指令:(10:查看指令)  ");
        scanf("%d",&iOrder);//输入命令
    switch(iOrder) {
        case 1://尾添加 
            //TODO:添加一个学生的信息 
            printf("输入学号:");
            scanf("%s",arrNum);
            printf("输入姓名:");
            scanf("%s",arrStuName);
            printf("输入分数:");
            scanf("%d",&iStuScore);//这里别忘了加取地址符号 
            AddStuMSG(arrNum,arrStuName,iStuScore); //调用添加信息函数 
            break;
        case 11://头添加 
            //TODO:添加一个学生的信息 
            printf("输入学号:");
            scanf("%s",arrNum);
            printf("输入姓名:");
            scanf("%s",arrStuName);
            printf("输入分数:");
            scanf("%d",&iStuScore);//这里别忘了加取地址符号
            AddStuMSGToLinkHead(arrNum,arrStuName,iStuScore);  
            break;
        case 111://在指定位置添加
            {STUNODE*pTemp = NULL ;//在case里面声明变量的时候要用{}把声明语句括起来否则报错!!!!!!!! 
            //查找指定学生 
            printf("输入指定位置的学号:");
            scanf("%s",arrNum);
            pTemp = FindStuBuNum(arrNum);
            //FindStuBuNum(arrNum);因为下面有NULL!=函数的判断,如果这里再引用一次的话就相当于引用了两次 
            if(NULL != pTemp){
                //TODO,插入 
            printf("输入学号:");
            scanf("%s",arrNum);
            printf("输入姓名:");
            scanf("%s",arrStuName);
            printf("输入分数:");
            scanf("%d",&iStuScore);//这里别忘了加取地址符号
            InsertNode(pTemp,arrNum,arrStuName,iStuScore);
            }
            }
            break;
        case 2://查找并显示指定学生的信息 
            {//输入一个学号
            printf("输入学号:");
            scanf("%s",arrNum);
            // 查找 
            STUNODE*pTemp = FindStuBuNum(arrNum);
            //打印
            if(NULL != pTemp){
                printf("学号:%s,姓名:%s,分数:%d\n",pTemp->arrNum,pTemp->arrStuName,pTemp->iStuScore);
            }
        }
            break;
        case 3://修改指定学生的信息 
        {
            printf("输入指定学生的学号:");
            scanf("%s",arrNum);
            // 查找 
            STUNODE*pTemp = FindStuBuNum(arrNum);
            if(NULL != pTemp){
                printf("a:修改学号,b:修改名字,c:修改分数");
                getchar();//拿掉回车 
                char Change = 0;
                scanf("%c",&Change);
                if(Change == 'a'){
                    printf("请输入修改后的学号:");
                    getchar();//拿掉回车 
                    //修改学号
                    scanf("%s",arrNum);
                    strcpy(pTemp->arrNum,arrNum);
                } 
                if(Change == 'b'){
                    printf("请输入修改后的名字:");
                    getchar();//拿掉回车 
                    //修改名字
                    scanf("%s",arrStuName);
                    strcpy(pTemp->arrStuName,arrStuName);
                } 
                if(Change == 'c'){
                    printf("请输入修改后的分数:");
                    getchar();//拿掉回车 
                    //修改分数
                    scanf("%d",&iStuScore);
                    pTemp->iStuScore = iStuScore;
                } 
                
                
            }
            }
            break;
        case 4://保存学生的信息
            SaveStuToFile();
            printf("保存成功\n");
            break;  
        case 5:
            ReadStuFromFile();
            break;
        case 6:{
            printf("输入要删除的学生的学号:");
            scanf("%s",arrNum);
            // 查找 
            STUNODE*pTemp = FindStuBuNum(arrNum);
            //删除这个节点 
            if(NULL != pTemp){
                //调用删除学生的函数 
                DeleteStuByNode(pTemp);
                printf("删除成功!");
            }
        }
            break; 
        case 7:
            //恢复,释放 
            FreeLinkData();
            //g_pHead = NULL;
            //g_pEnd = NULL;
            //回复,添加节点
            ReadStuFromFile();
            break;
        case 9:
            ShowStuData();//调用打印函数 
            break;
        case 0:
            nFlag = 0;//这个是之前没有接触过的 
            break;
        case 10:
            //查看指令 
            ShowOrder();
            break;
        default:
            printf("输入的指令不对\n");
            
    }
    }
    //保存
    SaveStuToFile(); 
    //释放链表 
    FreeLinkData(); 
    system("pause");
    return 0;
}
//DO:添加一个学生的信息(这里我又忘了把函数弄在主函数之外) 
void AddStuMSG(char arrNum[10], char arrStuName[10], int iStuScore){
    //1.检验参数的合法性 
    if(NULL == arrNum || NULL == arrStuName || iStuScore < 0){
        printf("学生信息输入错误\n");
        return ;
    } 
    //2.逻辑处理
    //创建一个节点
    STUNODE* pTemp = (STUNODE*)malloc(sizeof(STUNODE));
    //节点成员赋初始值
    strcpy(pTemp->arrNum ,arrNum); 
    strcpy(pTemp->arrStuName ,arrStuName);
    pTemp->iStuScore = iStuScore;
    pTemp->pNext = NULL;//不让指针变成野指针
    //接在链表上 
    if(NULL == g_pHead ||NULL == g_pEnd)//其实判断一个就ok,因为只要有一个是空,那么另外一个也会是空
     {//这里是一开始的情况,指针指向都是空
        g_pHead = pTemp;
        g_pEnd = pTemp;//只有一个节点,头和尾是一个地方    
     }else{
        //不是空,则直接在尾巴上添加就ok。也就是pEnd指向下一个 
        g_pEnd->pNext = pTemp;//链接 
        g_pEnd = pTemp;//尾巴向后移动 
     } 
}
//清空链表 
void  FreeLinkData(){
    //声明一个中间节点
    STUNODE*pTemp = g_pHead; 
    while(g_pHead != NULL){
        //记录节点 
        pTemp = g_pHead; 
        //向后移动一个 
        g_pHead = g_pHead->pNext;
        //删除节点
        free(pTemp); 
    }
}
//打印链表
void ShowStuData(){
    STUNODE *pTemp = g_pHead;
    while(pTemp != NULL){
        printf("学号:%s,姓名:%s,分数:%d\n",pTemp->arrNum,pTemp->arrStuName,pTemp->iStuScore);
        //向下走一步
        pTemp = pTemp->pNext; 
    }
}
//在链表头添加学生节点 
void AddStuMSGToLinkHead(char arrNum[10], char arrStuName[10], int iStuScore){
//检验参数的合法性 
if(NULL == arrNum || NULL == arrStuName || iStuScore < 0){
        printf("学生信息输入错误\n");
        return ;
    } 
    //创建一个节点
    STUNODE*pTemp = (STUNODE*)malloc(sizeof(STUNODE)); 
    //成员赋值
    strcpy(pTemp->arrNum ,arrNum); 
    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; 
    }
     
}
//查找指定学生
STUNODE*  FindStuBuNum(char*arrNum){
    //检验参数的合法性
    if(NULL == arrNum){
        printf("学号输入错误!\n");
        return NULL;
    } 
    //遍历链表
    //判断链表是否为空 
    if(NULL == g_pHead || NULL == g_pEnd){
        printf("链表为空\n");
        return NULL;
    }
    STUNODE*pTemp = g_pHead;
    while(pTemp != NULL){
        //用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数
        if(0 == strcmp(pTemp->arrNum,arrNum)){
        return pTemp;   
        }
        pTemp = pTemp->pNext;
    } 
    printf("查无此节点");
    return NULL;
} 
//指定位置插入节点
void InsertNode(STUNODE*pTemp,char arrNum[10], char arrStuName[10], int iStuScore){
    //创建节点
    STUNODE*pNewTemp = (STUNODE*)malloc(sizeof(STUNODE));
    //成员赋值 
    strcpy(pNewTemp->arrNum ,arrNum); 
    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;
    }

}
//删除指定学生 
void DeleteStuByNode(STUNODE*pNode){
    //1.只有一个节点
    if(g_pHead == g_pEnd){
        free(g_pHead);
        g_pHead = NULL;//把这一块空间交还给操作系统之后,指针里面装着非法空间,相当于留着后手,所以不行。所以要赋空。 
        g_pEnd = NULL;
    } 
    //只有两个节点,释放之后还要改变链表头和尾的位置 
    else if(g_pHead->pNext == g_pEnd){
        if(g_pHead == pNode){
            free(g_pHead);
            g_pHead = g_pEnd;
        }else{
            free(g_pEnd);
            g_pEnd = g_pHead;
            g_pHead->pNext = NULL;//删除之后 pNext装着非法地址 
        }
    }
    else{//大于两个
     STUNODE*pTemp = g_pHead;
     //看头节点是不是要删除的
     if(g_pHead == pNode){
        //记录头
        pTemp = g_pHead;
        //头向下走一个 
        g_pHead = g_pHead->pNext;
        free(pTemp);
        pTemp = NULL;//都已经释放了,就不要再留后手了
        return ;//结束 
     } 
     while(pTemp != NULL){
        if(pTemp->pNext == pNode){
            //进行删除 
            if(pNode == g_pEnd){//如果要删除的是尾 
                free(pNode);
                pNode = NULL;
                g_pEnd = pTemp;
                g_pEnd->pNext  = NULL; //尾节点下一个赋空 
                return ;
             }else{//中间节点
                //记住要删除的节点
                STUNODE*pNewTemp = pTemp->pNext;// 也可以把pTemp->pNext换成pNode 
                //前一节点指向要删除节点的下一个 
                pTemp->pNext = pNode->pNext;
                //释放节点
                free(pNewTemp); 
                pNewTemp = NULL;
                return ;
             }
         }
        pTemp = pTemp->pNext;
     }
    }
}
//保存信息进文件
void SaveStuToFile(){
    FILE*pFile = NULL;
    STUNODE*pTemp = g_pHead;
    char strBud[30] = {0};//存储一个学生的信息,全存到这个字符串里面 
    char strScore[10] = {0};//存储分数 
    //判断链表是否是空
    if(NULL == g_pHead){
        printf("没有学生\n");
        return ;
    } 
    //打开文件
    pFile = fopen("dat.txt","w+");
    if(NULL == pFile){
        printf("文件打开失败");
        return ;
    } 
    //操作文件指针
    while(pTemp){
        //学号赋值进去 
        strcpy(strBud,pTemp->arrNum);
        strcat(strBud,",");//后面那个参数是字符串,所以要用双引号 
        //姓名赋值进去 
        strcat(strBud,pTemp->arrStuName);//在后面接着连上 
        strcat(strBud,",");
        //分数
        itoa(pTemp->iStuScore,strScore,10);//十进制将int类型转换成字符串类型
        strcat(strBud,strScore);
        
        fwrite(strBud,1,strlen(strBud),pFile);
        fwrite("\r\n",1,strlen("\r\n"),pFile);
        pTemp = pTemp->pNext;//这一步尤为重要 
    }
    //关闭文件
     
    fclose(pFile);  
}
//从文件中读取学生信息 
void ReadStuFromFile(){
    FILE*pFile = fopen("dat.txt","r");
    if(NULL == pFile){
        printf("文件打开失败\n");
        return;
    }
    char strBuf[30] = {0};
    char strNum[10] = {0};
    char strStuName[10] = {0};
    char strStuScore[10] = {0};
    int nCount = 0; 
    //操作指针,读取函数
    while(NULL != fgets(strBuf,30,pFile)){//30代表最大读取量 fgets是一行一行去读 
        int i = 0;//每次开始的时候要清空循环控制变量 
        nCount = 0;
        int j = 0;
        for(i = 0;strBuf[i] != '\r';i++){
            int j = 0;
            if(0 == nCount)//没到','
            {
                strNum[i] = strBuf[i];
                if(',' == strBuf[i]){
                    strNum[i] = '\0';//不让这个位置变成逗号,而是\0 
                    nCount++;
                }
            }
            else if(1 == nCount)//第一个 ','
            {
                strStuName[j] = strBuf[i];
                j++;
                if(',' == strBuf[i]){
                    strStuName[i] = '\0';
                    nCount++;
                    j = 0;
                    continue;
                }
                
            }
            else //第二个',' 
            {
                strStuScore[j] = strBuf[i];
                j++;
            }
        }
        
        //插入到链表 
        char arrNum[10] = {0};//学号 
        char arrStuName[10];//姓名 
        int iStuScore;//分数
        AddStuMSG(arrNum,arrStuName,atoi(strStuScore));
    }
    
    fclose(pFile); 
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值