`
duoerbasilu
  • 浏览: 1481883 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

写了几天呀,留个纪念哈!!

艾玛,真水……抓狂


#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#define HEADER2 "          学号      姓名   英语   数学   C语言   总分  平均\n"
#define FORMAT  "    %8s    %7s   %4d   %4d   %4d    %4d   %.2f\n"
#define DATA  p->data.num,p->data.name,p->data.egrade,p->data.mgrade,p->data.cgrade,p->data.total,p->data.ave
int saveflag=0; /*是否需要存盘的标志变量*/
typedef struct student {
    char num[10];   /*学号*/
    char name[15]; /*姓名*/
    int cgrade;     /*C语言成绩*/
    int mgrade;     /*数学成绩*/
    int egrade;     /*英语成绩*/
    int total;      /*总分*/
    float ave;      /*平均分*/
};
typedef struct node{     //定义每条记录或结点的数据结构
    struct student data; /*数据域*/
    struct node *next;    /*指针域*/
}Node,*Link;   /*Node为node类型的结构变量,*Link为node类型的指针变量*/
void menu() {
    time_t now;
    now = time (NULL);
    printf("                          学生成绩管理系统 \n");
    printf("\n");
    printf("     *************************************************************\n");
    printf("     *                                                           *\n");
    printf("     *          1 输入成绩                 2 删除成绩            *\n");
    printf("     *                                                           *\n");
    printf("     *          3 查询成绩                 4 修改成绩            *\n");
    printf("     *                                                           *\n");
    printf("     *          5 排序成绩                 6 保存记录            *\n");
    printf("     *                                                           *\n");
    printf("     *          7 显示所有                 0 退出系统            *\n");
    printf("     *                                                           *\n");
    printf("     *************************************************************\n");
    printf("     *          8 切换登录模式             9 修改管理员信息      *\n");
    printf("     *************************************************************\n");
    printf("           Made by Ice, now time is %s\n ",ctime(&now));
    printf("\n请您选择操作命令(0~9):");    /*显示提示信息*/
}
int menu2(){
    int select;
    time_t now;
    now = time (NULL);
    system("cls");          //清屏
    printf("\n                                                                  来宾模式\n\n\n");
    printf("                          学生成绩管理系统 \n");
    printf("\n");
    printf("     *************************************************************\n");
    printf("     *                                                           *\n");
    printf("     *          1 查询成绩                 2 排序成绩            *\n");
    printf("     *                                                           *\n");
    printf("     *          3 显示所有                 0 退出系统            *\n");
    printf("     *                                                           *\n");
    printf("     *************************************************************\n");
    printf("     *          4 切换登录模式                                   *\n");
    printf("     *************************************************************\n");
    printf("           Made by Ice, now time is %s\n ",ctime(&now));
    printf("\n请您选择操作命令(0~4):");    /*显示提示信息*/
}
void printheader(){ /*格式化输出表头*/
    printf(HEADER2);
}
void printdata(Node *pp) {/*格式化输出表中数据*/
    Node* p;
    p=pp;
    printf(FORMAT,DATA);
}
void Wrong() {  /*输出按键错误信息*/
    printf("\n\n\n\n\n**********错误:输入不合法!!!**********\a\n");
    getch();
}
void Nofind(){ /*输出未查找此学生的信息*/
    printf("\n没有该学生!!\n");
}
void Disp(Link l){ /*显示单链表l中存储的学生记录,内容为student结构中定义的内容*/
    system("cls");
    Node *p;
    p=l->next; /*l存储的是单链表中头结点的指针,该头结点没有存储学生信息,指针域指向的后继结点才有学生信息*/
    if(!p) /*p==NULL,NUll在stdlib中定义为0*/
    {
        printf("\n目前无学生成绩记录!!\n");
        getch();
        return;
    }
    printf("\n\n");
    printheader(); /*输出表格头部*/
    while(p)    /*逐条输出链表中存储的学生信息*/
    {
        printdata(p);
        p=p->next; /*移动直下一个结点*/
    }
}
Node* Locate(Link l,char findmess[],char nameornum[]){
    Node *r;
    if(strcmp(nameornum,"num")==0) /*按学号查询*/
    {
        r=l->next;
        while(r)
        {
            if(strcmp(r->data.num,findmess)==0) /*若找到findmess值的学号*/
                return r;
            r=r->next;
        }
    }
    else if(strcmp(nameornum,"name")==0) /*按姓名查询*/
    {
        r=l->next;
        while(r)
        {
            if(strcmp(r->data.name,findmess)==0)    /*若找到findmess值的学生姓名*/
                return r;
            r=r->next;
        }
    }
    return 0; /*若未找到,返回一个空指针*/
}
void stringinput(char *t,int lens,char *notice){
   char n[255];
   do
   {
       printf(notice); /*显示提示信息*/
       scanf("%s",n); /*输入字符串*/
       if(strlen(n)>lens)printf("\n 超出长度!!!\n"); /*进行长度校验,超过lens值重新输入*/
   }while(strlen(n)>lens);
   strcpy(t,n); /*将输入的字符串拷贝到字符串t中*/
}
int numberinput(char *notice){
    int t=0;
    do
    {
        printf(notice); /*显示提示信息*/
        scanf("%d",&t); /*输入分数*/
        if(t>100||t<0) printf("\n 分数必须在0~100之间!!! \n"); //分数校验
    }while(t>100 || t<0);
    return t;
}
void Add(Link l){
    Node *p,*r,*s;
    char ch,flag=0,num[10];
    r=l;
    system("cls");
    Disp(l); /*先打印出已有的学生信息*/
    while(r->next!=NULL)
        r=r->next; /*将指针移至于链表最末尾,准备添加记录*/
    while(1) /*一次可输入多条记录,直至输入学号为0的记录结点添加操作*/
    {
        s=l->next;
        while(1)
        {
            stringinput(num,10,"学号(按0退出):"); /*格式化输入学号并检验*/
            flag=0;
            if(strcmp(num,"0")==0) /*输入为0,则退出添加操作,返回主界面*/
                return ;
            s=l->next;
            while(s) /*查询该学号是否已经存在,若存在则要求重新输入一个未被占用的学号*/
            {
                if(strcmp(s->data.num,num)==0)
                {
                    flag=1;
                    break;
                }
                s=s->next;
            }
            if(flag==1) /*提示用户是否重新输入*/
            {
                getchar();
                printf("=====>学号%s已存在,是否重新输入?(y/n)\a:",num);
                scanf("%c",&ch);
                if(ch=='y'||ch=='Y')
                    continue;
                else
                    return ;
            }
            else
                break;
        }
        p=(Node *)malloc(sizeof(Node));
        strcpy(p->data.num,num); /*将字符串num拷贝到p->data.num中*/
        stringinput(p->data.name,15,"Name:");
        p->data.cgrade=numberinput("C语言0-100]:");
        p->data.mgrade=numberinput("数学[0-100]:");
        p->data.egrade=numberinput("英语[0-100]:");
        p->data.total=p->data.egrade+p->data.cgrade+p->data.mgrade; /*计算总分*/
        p->data.ave=(float)(p->data.total/3); /*计算平均分*/
        p->next=NULL;
        while(r->next!=NULL)
            r=r->next;
        r->next=p;
        saveflag=1;
    }
}
void Qur(Link l){ /*按学号或姓名,查询学生记录*/
    system("cls");
    int select; /*1:按学号查,2:按姓名查,其他:返回主界面(菜单)*/
    char searchinput[20]; /*保存用户输入的查询内容*/
    Node *p;
    if(!l->next) /*若链表为空*/
    {
        printf("\n暂无学生记录!!!\n");
        return;
    }
    printf("\n     =====>1 通过学号查找 =====>2 通过姓名查找\n");
    printf("      请选择[1,2]:");
    scanf("%d",&select);
    if(select==1)   /*按学号查询*/
    {
        stringinput(searchinput,10,"请输入要查找的学号:");
        p=Locate(l,searchinput,"num");/*在l中查找学号为searchinput值的节点,并返回节点的指针*/
        if(p) /*若p!=NULL*/
        {
            printheader();
            printdata(p);
        }
        else
            Nofind();
    }
    else if(select==2) /*按姓名查询*/
    {
        stringinput(searchinput,15,"请输入学生姓名:");
        p=Locate(l,searchinput,"name");
        if(p)
        {
            printheader();
            printdata(p);
        }
        else
            Nofind();
    }
    else
        Wrong();
    system("PAUSE");
}
void Del(Link l){//删除学生记录:先找到保存该学生记录的节点,然后删除该节点
    int sel;
    Node *p,*r;
    char findmess[20];
    if(!l->next)
    {
        system("cls");
        printf("\n=====>暂无学生记录!!\n");
        getch();
        return;
    }
    system("cls");
    Disp(l);
    printf("\n        1 通过学号删除           2 通过姓名删除\n");
    printf("       请选择[1,2]:");
    scanf("%d",&sel);
    if(sel==1)
    {
        stringinput(findmess,10,"请输入学号:");
        p=Locate(l,findmess,"num");
        if(p)
        {
            r=l;
            while(r->next!=p)
            r=r->next;
            r->next=p->next;
            free(p); /*释放内存空间*/
            printf("\n删除成功!\n");
            saveflag=1;
        }
        else
            Nofind();
    }
    else if(sel==2) /*先按姓名查询到该记录所在的节点*/
    {
        stringinput(findmess,15,"请输入学生姓名:");
        p=Locate(l,findmess,"name");
        if(p)
        {
            r=l;
            while(r->next!=p)
            r=r->next;
            r->next=p->next;
            free(p);
            printf("\n删除成功!!!\n");
            saveflag=1;
        }
        else
        Nofind();
    }
    else
        Wrong();
    getch();
}
void Modify(Link l){//修改学生记录.先按输入的学号查询到该记录,然后提示用户修改学号之外的值,学号不能修改
    Node *p;
    char findmess[20];
    if(!l->next)
    {
        system("cls");
        printf("\n没有该生记录!\n");
        getch();
        return;
    }
    system("cls");
    printf("修改学生记录");
    Disp(l);
    stringinput(findmess,10,"请输入学号:"); /*输入并检验该学号*/
    p=Locate(l,findmess,"num"); /*查询到该节点*/
    if(p) /*若p!=NULL,表明已经找到该节点*/
    {
        printf("学号:%s,\n",p->data.num);
        printf("姓名:%s,",p->data.name);
        stringinput(p->data.name,15,"输入新姓名:");
        printf("C语言:%d,",p->data.cgrade);
        p->data.cgrade=numberinput("C语言[0-100]:");
        printf("数学:%d,",p->data.mgrade);
        p->data.mgrade=numberinput("数学[0-100]:");
        printf("英语:%d,",p->data.egrade);
        p->data.egrade=numberinput("英语[0-100]:");
        p->data.total=p->data.egrade+p->data.cgrade+p->data.mgrade;
        p->data.ave=(float)(p->data.total/3);
        printf("\n=====>修改成功!\n");
        saveflag=1;
    }
    else
        Nofind();
    getch();
}
void Sort(Link l){
    system("cls");
    Link ll;
    Node *p,*rr,*s;
    int i=0;
    if(l->next==NULL)
    {
        printf("\n暂无学生记录!\n");
        return ;
    }
    ll=(Node*)malloc(sizeof(Node)); /*用于创建新的节点*/
    ll->next=NULL;
    printf("当前状态:\n");
  //  puts("错误不在这!");
    Disp(l); /*显示排序前的所有学生记录*/
  //  system("PAUSE");
    p=l->next;
    while(p) /*p!=NULL*/
    {
        s=(Node*)malloc(sizeof(Node)); /*新建节点用于保存从原链表中取出的节点信息*/
        s->data=p->data; /*填数据域*/
        s->next=NULL;    /*指针域为空*/
        rr=ll;
/*rr链表于存储插入单个节点后保持排序的链表,ll是这个链表的头指针,每次从头开始查找插入位置*/
        while(rr->next!=NULL && rr->next->data.total>=p->data.total)
        {
            rr=rr->next;
        } /*指针移至总分比p所指的节点的总分小的节点位置*/
        if(rr->next==NULL)/*若新链表ll中的所有节点的总分值都比p->data.total大时,就将p所指节点加入链表尾部*/
            rr->next=s;
        else /*否则将该节点插入至第一个总分字段比它小的节点的前面*/
        {
            s->next=rr->next;
            rr->next=s;
        }
        p=p->next; /*原链表中的指针下移一个节点*/
    }
    l->next=ll->next; /*ll中存储是的已排序的链表的头指针*/
    p=l->next;           /*已排好序的头指针赋给p,准备填写名次*/
    while(p!=NULL) /*当p不为空时,进行下列操作*/
    {
        i++;       /*结点序号*/
        p=p->next;   /*指针后移*/
    }
    printf("\n*********************************************\n");
//  puts("错误不在这!");
    Disp(l);
    saveflag=1;
    printf("\n    =====>排序完成!!\n");
    system("PAUSE");
}
void Save(Link l){   //数据存盘,若用户没有专门进行此操作且对数据有修改,在退出系统时,会提示用户存盘
    FILE* fp;
    Node *p;
    int count=0;
    fp=fopen("student.txt","wb");/*以只写方式打开二进制文件*/
    p=l->next;
    while(p)
    {
        if(fwrite(p,sizeof(Node),1,fp)==1)
        {
            p=p->next;
            count++;
        }
        else break;
    }
    if(count>0)
    {
        printf("\n\n\n\n\n        保存完毕,当前有%d名学生记录\n",count);
        saveflag=0;
    }
    else
        printf("空文件,保存失败!!\n");
    fclose(fp); //关闭此文件
    getch();
}
int login(){
    FILE *fp1,*fp2;
    int state;
    char str1[20],str2[20],str_z[20],str_m[20];
    if((fp1=fopen("admin.txt","rb"))==NULL)
    {
        printf("本系统无管理员,请创建!\n\n请输入管理员账号:");
        scanf("%s",str_z);
        printf("请输入密码:");
        scanf("%s",str_m);
        fp2=fopen("admin.txt","wb");
        fprintf(fp2,"%s%c",str_z,'\n');
        fprintf(fp2,"%s%c",str_m,' ');
        fclose(fp2);
    }
    fp1=fopen("admin.txt","rb");
    fscanf(fp1,"%s",str1);
    fscanf(fp1,"%s",str2);
    fclose(fp1);
    while(1)
    {
        printf("请选择你的登录方式:\n\n");
        printf("1.管理员模式       0.来宾模式\n");
        printf("请你选择:(0-1)");
        scanf("%d",&state);
        if(state==0)
            return 0;
        else if(state==1)
        {
            printf("请输入账号:");
            scanf("%s",str_z);
            printf("请输入密码:");
            scanf("%s",str_m);
            if(strcmp(str1,str_z)==0&&strcmp(str2,str_m)==0)
                return 1;
            else
            {
                printf("账号或密码错误!!\n");
                system("PAUSE");
                system("cls");
            }
        }
        else
        {
            printf("输入不合法!!!\a\n");
            system("PAUSE");
            system("cls");
        }
    }
}
void Modify_admin(){
    FILE *fp;
    char str_z[20],str_m[20];
    fp=fopen("admin.txt","wb");
    printf("请输入管理员账号:");
    scanf("%s",str_z);
    printf("请输入密码:");
    scanf("%s",str_m);
    fprintf(fp,"%s%c",str_z,'\n');
    fprintf(fp,"%s%c",str_m,' ');
    fclose(fp);
    printf("管理员信息更新完毕!!\a\n");
    getch();
}
int main(){
    system("color 0e");//主屏函数
    Link L;      /*定义链表*/
    FILE *fp;    /*文件指针*/
    int select,State=0;  /*保存选择结果变量*/
    char ch,admin[20],admin_p[20];     /*保存(y,Y,n,N)*/
    int count=0; /*保存文件中的记录条数(或结点个数)*/
    Node *p,*r;  /*定义记录指针变量*/
    L=(Node*)malloc(sizeof(Node));
    L->next=NULL;
    r=L;
    fp=fopen("student.txt","ab+");
    Loop:{
        State=login();
    }
    while(!feof(fp))
    {
        p=(Node*)malloc(sizeof(Node));
        if(fread(p,sizeof(Node),1,fp)==1) /*一次从文件中读取一条学生成绩记录*/
        {
            p->next=NULL;
            r->next=p;
            r=p;                            /*r指针向后移一个位置*/
            count++;
        }
    }
    fclose(fp); /*关闭文件*/
    if(State==1)
    {
    while(1)
    {
        system("cls");
        printf("\n                                                                  管理员模式\n\n\n");
        menu();
        p=r;
        scanf("%d",&select);
        if(select==0)
        {
            if(saveflag==1) /*若对链表的数据有修改且未进行存盘操作,则此标志为1*/
            {
                getchar();
                printf("\n记录已修改,是否保存当前记录?(y/n):");
                scanf("%c",&ch);
                if(ch=='y'||ch=='Y')
                    Save(L);
            }
            printf("谢谢您的使用!!\n");
            break;
        }
        switch(select)
        {
        case 1:Add(L);break;            /*增加学生记录*/
        case 2:Del(L);break;           /*删除学生记录*/
        case 3:Qur(L);break;           /*查询学生记录*/
        case 4:Modify(L);break;        /*修改学生记录*/
        case 5:Sort(L);break;        /*排序学生记录*/
        case 6:Save(L);break;        /*保存学生记录*/
        case 7:Disp(L);system("PAUSE");break;         /*显示学生记录*/
        case 8:system("cls");goto Loop;
        case 9:Modify_admin();break;
        default: Wrong();getch();break;        /*按键有误,必须为数值0-9*/
        }
    }
    }
    else
    {
        while(1)
        {
            system("cls");
            menu2();
            scanf("%d",&select);
            if(select==0)
            {
                printf("谢谢您的使用!!\n");
                exit(1);
            }
            switch(select)
            {
                case 1:Qur(L);break;           /*查询学生记录*/
                case 2:Sort(L);break;        /*排序学生记录*/
                case 3:Disp(L);system("PAUSE");break;         /*显示学生记录*/
                case 4:system("cls");goto Loop;
                default: Wrong();getch();break;        /*按键有误,必须为数值0-9*/
            }
        }
    }
    return 0;
}



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics