C实现的一个简单的学生成绩管理系统
/*學生成績管理系統
*/
//#include "StdAfx.h"
#include "stdio.h"?? /*標準輸入輸出函數庫*/
#include "stdlib.h" /*標準函數庫*/
#include "string.h" /*字符串函數庫*/
#include "conio.h"??? /*屏幕操作函數庫*/
#define HEADER1 "????? ----------------------------STUDENT---------------------------------- \n"
#define HEADER2 "???? |??? number???? |????? name???? |Comp|Math|Eng |?? sum | ave |mici | \n"
#define HEADER3 "???? |---------------|---------------|----|----|----|--------|-------|-----| "
#define FORMAT "??????? |??? %-10s |%-15s|%4d|%4d|%4d| %4d?? | %.2f |%4d |\n"
#define DATA p->data.num,p->data.name,p->data.egrade,p->data.mgrade,p->data.cgrade,p->data.total,p->data.ave,p->data.mingci
#define END???? "?????? --------------------------------------------------------------------- \n"
int saveflag=0; /*是否需要存盤的標志變量*/
/*定義與學生有關的數據結構*/
struct?? student??? /*標記為student*/
{
?char num[10];?? /*學號*/
?char name[15]; /*姓名*/
?int cgrade;???? /*C語言成績*/
?int mgrade;???? /*數學成績*/
?int egrade;???? /*英語成績*/
?int total;????? /*總分*/
?float ave;????? /*平均分*/
?int mingci;??? /*名次*/
} ;
/*定義每條記錄或結點的數據結構,標記為:node*/
typedef struct node
{
?struct student data; /*數據域*/
?struct node *next;??? /*指針域*/
}Node,*Link;?? /*Node為node類型的結構變量,*Link為node類型的指針變量*/
void menu() /*主菜單*/
{
?system("cls");?? /*調用DOS命令,清屏.與clrscr()功能相同*/
?cprintf("???????????????? The Students' Grade Management System \n");
?cprintf("???? *************************Menu********************************\n");
?cprintf("???? * 1 input?? record???????????? 2 delete record???????????? *\n");
?cprintf("???? * 3 search record???????????? 4 modify record???????????? *\n");
?cprintf("???? * 5 insert record???????????? 6 count record???????????? *\n");
?cprintf("???? * 7 sort??? reord????????????? 8 save?? record???????????? *\n");
?cprintf("???? * 9 display record???????????? 0 quit?? system???????????? *\n");
?cprintf("???? *************************************************************\n");
?/*cprintf()送格式化輸出至文本窗口屏幕中*/
}
void printheader() /*格式化輸出表頭*/
{
?printf(HEADER1);
?printf(HEADER2);
?printf(HEADER3);
}
void printdata(Node *pp) /*格式化輸出表中數據*/
{
?Node* p;
?p=pp;
?printf(FORMAT,DATA);
}
void Wrong() /*輸出按鍵錯誤信息*/
{
?printf("\n\n\n\n\n***********Error:input has wrong! press any key to continue**********\n");
?getchar();
}
void Nofind() /*輸出未查找此學生的信息*/
{
?printf("\n=====>Not find this student!\n");
}
void Disp(Link l) /*顯示單鏈表l中存儲的學生記錄,內容為student結構中定義的內容*/
{
?Node *p;
?p=l->next; /*l存儲的是單鏈表中頭結點的指針,該頭結點沒有存儲學生信息,指針域指向的后繼結點才有學生信息*/
?if(!p) /*p==NULL,NUll在stdlib中定義為0*/
?{
??printf("\n=====>Not student record!\n");
??getchar();
??return;
?}
?printf("\n\n");
?printheader(); /*輸出表格頭部*/
?while(p)??? /*逐條輸出鏈表中存儲的學生信息*/
?{
??printdata(p);
??p=p->next; /*移動直下一個結點*/
??printf(HEADER3);
?}
?getchar();
}
/*************************************************************
作用:用于定位鏈表中符合要求的節點,并返回指向該節點的指針
參數:findmess[]保存要查找的具體內容; nameornum[]保存按什么查找;
在單鏈表l中查找;
**************************************************************/
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; /*若未找到,返回一個空指針*/
}
/*輸入字符串,并進行長度驗證(長度<lens)*/
void stringinput(char *t,int lens,char *notice)
{
?char n[255];
?do{
??printf(notice); /*顯示提示信息*/
??scanf("%s",n); /*輸入字符串*/
??if(strlen(n)>lens)printf("\n exceed the required length! \n"); /*進行長度校驗,超過lens值重新輸入*/
?}while(strlen(n)>lens);
?strcpy(t,n); /*將輸入的字符串拷貝到字符串t中*/
}
/*輸入分數,0<=分數<=100)*/
int numberinput(char *notice)
{
?int t=0;
?do{
??printf(notice); /*顯示提示信息*/
??scanf("%d",&t); /*輸入分數*/
??if(t>100 || t<0) printf("\n score must in [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;
?s=l->next;
?system("cls");
?Disp(l); /*先打印出已有的學生信息*/
?while(r->next!=NULL)
??r=r->next; /*將指針移至于鏈表最末尾,準備添加記錄*/
?while(1) /*一次可輸入多條記錄,直至輸入學號為0的記錄結點添加操作*/
?{
??while(1) /*輸入學號,保證該學號沒有被使用,若輸入學號為0,則退出添加記錄操作*/
??{
???stringinput(num,10,"input number(press '0'return menu):"); /*格式化輸入學號并檢驗*/
???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("=====>The number %s is not existing,try again?(y/n):",num);
???scanf("%c",&ch);
???if(ch=='y'||ch=='Y')
????continue;
???else
????return;
???}
???else
???{break;}
??}
??p=(Node *)malloc(sizeof(Node)); /*申請內存空間*/
??if(!p)
??{
???printf("\n allocate memory failure "); /*如沒有申請到,打印提示信息*/
???return ;???????????? /*返回主界面*/
??}
??strcpy(p->data.num,num); /*將字符串num拷貝到p->data.num中*/
??stringinput(p->data.name,15,"Name:");
??p->data.cgrade=numberinput("C language Score[0-100]:"); /*輸入并檢驗分數,分數必須在0-100之間*/
??p->data.mgrade=numberinput("Math Score[0-100]:");?? /*輸入并檢驗分數,分數必須在0-100之間*/
??p->data.egrade=numberinput("English Score[0-100]:"); /*輸入并檢驗分數,分數必須在0-100之間*/
??p->data.total=p->data.egrade+p->data.cgrade+p->data.mgrade; /*計算總分*/
??p->data.ave=(float)(p->data.total/3); /*計算平均分*/
??p->data.mingci=0;
??p->next=NULL; /*表明這是鏈表的尾部結點*/
??r->next=p; /*將新建的結點加入鏈表尾部中*/
??r=p;
??saveflag=1;
?}
?return ;
}
void Qur(Link l) /*按學號或姓名,查詢學生記錄*/
{
?int select; /*1:按學號查,2:按姓名查,其他:返回主界面(菜單)*/
?char searchinput[20]; /*保存用戶輸入的查詢內容*/
?Node *p;
?if(!l->next) /*若鏈表為空*/
?{
??system("cls");
??printf("\n=====>No student record!\n");
??getchar();
??return;
?}
?system("cls");
?printf("\n???? =====>1 Search by number =====>2 Search by name\n");
?printf("????? please choice[1,2]:");
?scanf("%d",&select);
?if(select==1)?? /*按學號查詢*/
?{
??stringinput(searchinput,10,"input the existing student number:");
??p=Locate(l,searchinput,"num");/*在l中查找學號為searchinput值的節點,并返回節點的指針*/
??if(p) /*若p!=NULL*/
??{
???printheader();
???printdata(p);
???printf(END);
???printf("press any key to return");
???getchar();
??}
??else
???Nofind();
??getchar();
?}
?else if(select==2) /*按姓名查詢*/
?{
??stringinput(searchinput,15,"input the existing student name:");
??p=Locate(l,searchinput,"name");
??if(p)
??{
???printheader();
???printdata(p);
???printf(END);
???printf("press any key to return");
???getchar();
??}
??else
???Nofind();
??getchar();
?}
?else
??Wrong();
?getchar();
}
/*刪除學生記錄:先找到保存該學生記錄的節點,然后刪除該節點*/
void Del(Link l)
{
?int sel;
?Node *p,*r;
?char findmess[20];
?if(!l->next)
?{ system("cls");
?printf("\n=====>No student record!\n");
?getchar();
?return;
?}
?system("cls");
?Disp(l);
?printf("\n??????? =====>1 Delete by number?????? =====>2 Delete by name\n");
?printf("?????? please choice[1,2]:");
?scanf("%d",&sel);
?if(sel==1)
?{
??stringinput(findmess,10,"input the existing student number:");
??p=Locate(l,findmess,"num");
??if(p) /*p!=NULL*/
??{
???r=l;
???while(r->next!=p)
????r=r->next;
???r->next=p->next;/*將p所指節點從鏈表中去除*/
???free(p); /*釋放內存空間*/
???printf("\n=====>delete success!\n");
???getchar();
???saveflag=1;
??}
??else
???Nofind();
??getchar();
?}
?else if(sel==2) /*先按姓名查詢到該記錄所在的節點*/
?{
??stringinput(findmess,15,"input the existing student name");
??p=Locate(l,findmess,"name");
??if(p)
??{
???r=l;
???while(r->next!=p)
????r=r->next;
???r->next=p->next;
???free(p);
???printf("\n=====>delete success!\n");
???getchar();
???saveflag=1;
??}
??else
???Nofind();
??getchar();
?}
?else
??Wrong();
?getchar();
}
/*修改學生記錄。先按輸入的學號查詢到該記錄,然后提示用戶修改學號之外的值,學號不能修改*/
void Modify(Link l)
{
?Node *p;
?char findmess[20];
?if(!l->next)
?{ system("cls");
?printf("\n=====>No student record!\n");
?getchar();
?return;
?}
?system("cls");
?printf("modify student recorder");
?Disp(l);
?stringinput(findmess,10,"input the existing student number:"); /*輸入并檢驗該學號*/
?p=Locate(l,findmess,"num"); /*查詢到該節點*/
?if(p) /*若p!=NULL,表明已經找到該節點*/
?{
??printf("Number:%s,\n",p->data.num);
??printf("Name:%s,",p->data.name);
??stringinput(p->data.name,15,"input new name:");
??printf("C language score:%d,",p->data.cgrade);
??p->data.cgrade=numberinput("C language Score[0-100]:");
??printf("Math score:%d,",p->data.mgrade);
??p->data.mgrade=numberinput("Math Score[0-100]:");
??printf("English score:%d,",p->data.egrade);
??p->data.egrade=numberinput("English Score[0-100]:");
??p->data.total=p->data.egrade+p->data.cgrade+p->data.mgrade;
??p->data.ave=(float)(p->data.total/3);
??p->data.mingci=0;
??printf("\n=====>modify success!\n");
??Disp(l);
??saveflag=1;
?}
?else
??Nofind();
?getchar();
}
/*插入記錄:按學號查詢到要插入的節點的位置,然后在該學號之后插入一個新節點。*/
void Insert(Link l)
{
?Link p,v,newinfo; /*p指向插入位置,newinfo指新插入記錄*/
?char ch,num[10],s[10]; /*s[]保存插入點位置之前的學號,num[]保存輸入的新記錄的學號*/
?int flag=0;
?v=l->next;
?system("cls");
?Disp(l);
?while(1)
?{ stringinput(s,10,"please input insert location after the Number:");
?flag=0;v=l->next;
?while(v) /*查詢該學號是否存在,flag=1表示該學號存在*/
?{
??if(strcmp(v->data.num,s)==0) {flag=1;break;}
??v=v->next;
?}
?if(flag==1)
??break; /*若學號存在,則進行插入之前的新記錄的輸入操作*/
?else
?{ getchar();
?printf("\n=====>The number %s is not existing,try again?(y/n):",s);
?scanf("%c",&ch);
?if(ch=='y'||ch=='Y')
?{continue;}
?else
?{return;}
?}
?}
?/*以下新記錄的輸入操作與Add()相同*/
?stringinput(num,10,"input new student Number:");
?v=l->next;
?while(v)
?{
??if(strcmp(v->data.num,num)==0)
??{
???printf("=====>Sorry,the new number:'%s' is existing !\n",num);
???printheader();
???printdata(v);
???printf("\n");
???getchar();
???return;
??}
??v=v->next;
?}
?newinfo=(Node *)malloc(sizeof(Node));
?if(!newinfo)
?{
??printf("\n allocate memory failure "); /*如沒有申請到,打印提示信息*/
??return ;???????????? /*返回主界面*/
?}
?strcpy(newinfo->data.num,num);
?stringinput(newinfo->data.name,15,"Name:");
?newinfo->data.cgrade=numberinput("C language Score[0-100]:");
?newinfo->data.mgrade=numberinput("Math Score[0-100]:");
?newinfo->data.egrade=numberinput("English Score[0-100]:");
?newinfo->data.total=newinfo->data.egrade+newinfo->data.cgrade+newinfo->data.mgrade;
?newinfo->data.ave=(float)(newinfo->data.total/3);
?newinfo->data.mingci=0;
?newinfo->next=NULL;
?saveflag=1; /*在main()有對該全局變量的判斷,若為1,則進行存盤操作*/
?/*將指針賦值給p,因為l中的頭節點的下一個節點才實際保存著學生的記錄*/
?p=l->next;
?while(1)
?{
??if(strcmp(p->data.num,s)==0) /*在鏈表中插入一個節點*/
??{
???newinfo->next=p->next;
???p->next=newinfo;
???break;
??}
??p=p->next;
?}
?Disp(l);
?printf("\n\n");
?getchar();
}
/*統計該班的總分第一名和單科第一,和各科不及格人數*/
void Tongji(Link l)
{
?Node *pm,*pe,*pc,*pt; /*用于指向分數最高的節點*/
?Node *r=l->next;
?int countc=0,countm=0,counte=0; /*保存三門成績中不及格的人數*/
?if(!r)
?{ system("cls");
?printf("\n=====>Not student record!\n");
?getchar();
?return ;
?}
?system("cls");
?Disp(l);
?pm=pe=pc=pt=r;
?while(r)
?{
??if(r->data.cgrade<60) countc++;
??if(r->data.mgrade<60) countm++;
??if(r->data.egrade<60) counte++;
??if(r->data.cgrade>=pc->data.cgrade)??? pc=r;
??if(r->data.mgrade>=pm->data.mgrade)??? pm=r;
??if(r->data.egrade>=pe->data.egrade)??? pe=r;
??if(r->data.total>=pt->data.total)????? pt=r;
??r=r->next;
?}
?printf("\n------------------------------the TongJi result--------------------------------\n");
?printf("C Language<60:%d (ren)\n",countc);
?printf("Math????? <60:%d (ren)\n",countm);
?printf("English?? <60:%d (ren)\n",counte);
?printf("-------------------------------------------------------------------------------\n");
?printf("The highest student by total?? scroe?? name:%s totoal score:%d\n",pt->data.name,pt->data.total);
?printf("The highest student by English score?? name:%s totoal score:%d\n",pe->data.name,pe->data.egrade);
?printf("The highest student by Math??? score?? name:%s totoal score:%d\n",pm->data.name,pm->data.mgrade);
?printf("The highest student by C?????? score?? name:%s totoal score:%d\n",pc->data.name,pc->data.cgrade);
?printf("\n\npress any key to return");
?getchar();
}
/*利用插入排序法實現單鏈表的按總分字段的降序排序,從高到低*/
void Sort(Link l)
{
?Link ll;
?Node *p,*rr,*s;
?int i=0;
?if(l->next==NULL)
?{ system("cls");
?printf("\n=====>Not student record!\n");
?getchar();
?return ;
?}
?ll=(Node*)malloc(sizeof(Node)); /*用于創建新的節點*/
?if(!ll)
?{
??printf("\n allocate memory failure "); /*如沒有申請到,打印提示信息*/
??return ;???????????? /*返回主界面*/
?}
?ll->next=NULL;
?system("cls");
?Disp(l); /*顯示排序前的所有學生記錄*/
?p=l->next;
?while(p) /*p!=NULL*/
?{
??s=(Node*)malloc(sizeof(Node)); /*新建節點用于保存從原鏈表中取出的節點信息*/
??if(!s) /*s==NULL*/
??{
???printf("\n allocate memory failure "); /*如沒有申請到,打印提示信息*/
???return ;???????????? /*返回主界面*/
??}
??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->data.mingci=i;?? /*將名次賦值*/
??p=p->next;?? /*指針后移*/
?}
?Disp(l);
?saveflag=1;
?printf("\n??? =====>sort complete!\n");
}
/*數據存盤,若用戶沒有專門進行此操作且對數據有修改,在退出系統時, 會提示用戶存盤*/
void Save(Link l)
{
?FILE* fp;
?Node *p;
?int count=0;
?fp=fopen("c:\\student","wb");/*以只寫方式打開二進制文件*/
?if(fp==NULL) /*打開文件失敗*/
?{
??printf("\n=====>open file error!\n");
??getchar();
??return ;
?}
?p=l->next;
?while(p)
?{
??if(fwrite(p,sizeof(Node),1,fp)==1)/*每次寫一條記錄或一個節點信息至文件*/
??{
???p=p->next;
???count++;
??}
??else
??{
???break;
??}
?}
?if(count>0)
?{
??getchar();
??printf("\n\n\n\n\n=====>save file complete,total saved's record number is:%d\n",count);
??getchar();
??saveflag=0;
?}
?else
?{system("cls");
?printf("the current link is empty,no student record is saved!\n");
?getchar();
?}
?fclose(fp); /*關閉此文件*/
}
void main()
{
?Link l;????? /*定義鏈表*/
?FILE *fp;??? /*文件指針*/
?int select;???? /*保存選擇結果變量*/
?char ch;???? /*保存(y,Y,n,N)*/
?int count=0; /*保存文件中的記錄條數(或結點個數)*/
?Node *p,*r;?? /*定義記錄指針變量*/
?l=(Node*)malloc(sizeof(Node));
?if(!l)
?{
??printf("\n allocate memory failure "); /*如沒有申請到,打印提示信息*/
??return ;???????????? /*返回主界面*/
?}
?l->next=NULL;
?r=l;
?fp=fopen("C:\\student","ab+"); /*以追加方式打開一個二進制文件,可讀可寫,若此文件不存在,會創建此文件*/
?if(fp==NULL)
?{
??printf("\n=====>can not open file!\n");
??exit(0);
?}
?while(!feof(fp))
?{
??p=(Node*)malloc(sizeof(Node));
??if(!p)
??{
???printf(" memory malloc failure!\n");??? /*沒有申請成功*/
???exit(0);?????? /*退出*/
??}
??if(fread(p,sizeof(Node),1,fp)==1) /*一次從文件中讀取一條學生成績記錄*/
??{
???p->next=NULL;
???r->next=p;
???r=p;??????????????????????????? /*r指針向后移一個位置*/
???count++;
??}
?}
?fclose(fp); /*關閉文件*/
?printf("\n=====>open file sucess,the total records number is : %d.\n",count);
?menu();
?while(1)
?{
??system("cls");
??menu();
??p=r;
??printf("\n????????????? Please Enter your choice(0~9):");??? /*顯示提示信息*/
??scanf("%d",&select);
??if(select==0)
??{
???if(saveflag==1) /*若對鏈表的數據有修改且未進行存盤操作,則此標志為1*/
???{ getchar();
???printf("\n=====>Whether save the modified record to file?(y/n):");
???scanf("%c",&ch);
???if(ch=='y'||ch=='Y')
????Save(l);
???}
???printf("=====>thank you for useness!");
???getchar();
???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:Insert(l);break;??????? /*插入學生記錄*/
??case 6:Tongji(l);break;?????? /*統計學生記錄*/
??case 7:Sort(l);break;??????? /*排序學生記錄*/
??case 8:Save(l);break;??????? /*保存學生記錄*/
??case 9:system("cls");Disp(l);break;???????? /*顯示學生記錄*/
??default: Wrong();getchar();break;??????? /*按鍵有誤,必須為數值0-9*/
??}
?}
}
總結
以上是生活随笔為你收集整理的C实现的一个简单的学生成绩管理系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 去掉xsl运行的飞鸽传书办法
- 下一篇: C 库