1. 程式人生 > >史上最詳細c語言學生管理系統(完整的原始碼)

史上最詳細c語言學生管理系統(完整的原始碼)

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


struct student
{
char sno[12];
char name[9];

char sex[5];
struct score
{
double China;
double shuxue;
double English;
double sum;
double average;
} fenshu;
int age;
struct student *next;
};
typedef struct student ID;//宣告結構體同義詞,方便使用
int total;//學生管理系統的實際人數
//各函式的宣告
ID* Create(); //建立學生管理系統
void Save(ID *head); //儲存學生資訊檔案
ID * Read(); //讀取學生資訊檔案
void Display(ID * head); //顯示學生資訊檔案
ID* Add(ID* head); //新增學生資訊
ID* Change(ID* head); //修改學生資訊
void Search(ID *head); //按照姓名或者型別查詢學生
ID* Delete(ID *head); //刪除學生資訊
void Sort(ID *head);
/************************************************
*函式名: main(主函式)
*功能:顯示主選單
*返回值:NULL
*************************************************/
void main()
{
ID*head=NULL;//連結串列頭結點
int choice;//使用者選單選擇
while(1)
{
system("cls");//清屏
printf("\n");
printf("*************簡易學生管理系統*************\n\n");
printf("\t1.建立簡易學生管理系統\n\n");
printf("\t2.顯示學生檔案資訊\n\n");
printf("\t3.新增新學生\n\n");
printf("\t4.修改學生的資訊\n\n");
printf("\t5.查詢學生\n\n");
printf("\t6.刪除學生\n\n");
printf("\t7.排序學生\n\n");
printf("\t8.退出簡易學生管理系統\n\n");
printf("\n\n");
printf("請輸入你的選擇(1~8):");
scanf("%d",&choice);//選擇功能
getchar();//吸收回車符
switch(choice)
        {
         case 1: head=Create(); //建立學生管理系統子函式
            break;
         case 2: head=Read();   //讀取學生管理系統檔案子函式
                 if(head!=NULL) 
                     Display(head);  //顯示學生管理系統
            break;
         case 3: head=Read();   //讀取學生管理系統檔案子函式
                 if(head!=NULL) 
                     head=Add(head); //新增新生
             break;
         case 4:  head=Read();  
                 if(head!=NULL) 
                     head=Change(head); //修改新生
            break;
         case 5:  head=Read();
                 if(head!=NULL) 
                     Search(head); //查詢學生
            break;
         case 6:  head=Read();  
                 if(head!=NULL) 
                     head=Delete(head); //刪除學生
            break;
         case 7: head=Read(); 
                 if(head!=NULL) 
                     Sort(head); //排序學生
            break;
         case 8: exit(0);       //退出
            break;
         default: printf("\n你輸入錯了,請你重新輸入\n");
                  getch();
        }
    }
}
/***********************************************
*函式名:Create(建立)
*功能:建立一個單鏈表,把資料放在連結串列裡面,一旦需要儲存,就呼叫save函式儲存在檔案中
*返回值:ID *(結構體連結串列頭節點指標)
***********************************************/
ID* Create()
{   
    int k=0;

    FILE *fp;       //定義一個檔案指標,接收fopen的返回值,用於最後的關閉檔案
    ID *head,*p1,*tail,*p3; 
             
    
    if ((fp=fopen("student.txt","r"))==NULL)      //如果檔案不存在就建立
    {
        head=p1=tail=NULL;
        while(1)                //這個迴圈可以實現多次新增新學生資訊
    {
     bb1:  p1= (ID*)malloc(sizeof(ID)); //給p1分配一個動態儲存空間
           p1->next=NULL;
           printf("請輸入姓名(當你不想錄入時,在姓名處輸入*,結束錄入):\n");
           fflush(stdin);
           scanf("%8s",p1->name);       //輸入姓名
  p1->name[8]=0;
          if(strcmp(p1->name,"*")==0)   //判斷輸入的是否為*號,是則結束函式
          {
            if(total==0)                //當記錄人數為0時不建立學生檔案
            {
             printf("你輸入了0條記錄,單鏈表沒有建立...\n");
             free(p1);                  //釋放p1空間
             return (head);         //把head返回
            }
            else
            {
                break;                  //跳出while迴圈
            }
          }
          fflush(stdin);
          printf("請輸入學號: \n");
          scanf("%11s",p1->sno);
     
          p3=head;      //讓p3從頭開始遍歷
          while(p3!=NULL)       //當p3不為空時
          {
                if((strcmp(p1->name,p3->name)==0)&&(strcmp(p1->sno,p3->sno)==0))
        {
                free(p1);
                    printf("你重複輸入了。\n");
                goto bb1;
        }
                p3=p3->next;
          }
             //使得每個欄位都能有效結束
 
          p1->sno[11]=0;
 
 fflush(stdin);
 printf("請輸入學生性別:");
 scanf("%4s",p1->sex);
 fflush(stdin);
 printf("請輸入學生年齡:");
 scanf("%d",&p1->age);
 fflush(stdin);
 printf("請輸入學生科目成績(語文,數學,英語):");
 scanf("%lf%lf%lf",&p1->fenshu.China,&p1->fenshu.shuxue,&p1->fenshu.English);
 
 p1->fenshu.sum=p1->fenshu.China+p1->fenshu.shuxue+p1->fenshu.English;
 p1->fenshu.average=p1->fenshu.sum/3.0;
 if(head==NULL)
 {
            head=p1;                //head和p2都為p1
            tail=p1;
          }
          else
          { 
            tail->next=p1;      //第二次以後的執行命令,目的就是p1向後移,而head的位置不變
            tail=p1;
          }
          
        total++;                //錄入一個人後,總數就加1
    }
        tail->next=NULL;                     //尾指標域賦值為NULL
        free(p1);
        printf("\n新建簡易學生管理系統成功,共有%d個學生\n ",total);
        getchar();      //這個getchar是吸收回車鍵的
        Save(head); //將新建立的學生連結串列儲存到學生檔案中
    }
    else  
    {
        printf("\n\t學生資訊檔案已經存在,不能重複建立!\n\n按任意鍵返回主選單\n\n");
        getch();     //輸入任意鍵進入下一步
    }  
    return head;        //返回頭指標 
}
/*void Save(ID *head)
{


}*/




/************************************************
*函式名:Save(儲存)
*功能:將連結串列(資料)儲存在檔案
*返回值:NULL
*引數:連結串列頭節點
*************************************************/
void Save(ID *head) 
{
FILE *fp; //定義一個檔案指標,接收fopen的返回值,用於最後的關閉檔案 
    ID* t ; //定義一個指標,從頭到尾遍歷一遍單鏈表,向檔案中寫入
    if ((fp=fopen("student.txt","w"))==NULL) //開啟檔案來寫入
    {
        printf("開啟檔案失敗!\n");
        getch();     //輸入任意鍵進入下一步
        exit(0); //退出
    }
    t=head; //把頭指標賦給t,讓它從頭開始
    while(t!=NULL) //只要t指標不為空,即等於連結串列沒有結束
    {
       fwrite(t,sizeof(ID),1,fp); //把連結串列寫入檔案中
       t=t->next; //指標後移
    }
    fclose(fp); //把檔案關閉
    printf("\n檔案儲存成功\n");
printf("\n請按任意鍵返回主選單\n");
getch(); 
}




/************************************************
*函式名:Read(讀取學生檔案)
*功能:讀取檔案中的資訊並將其放入單鏈表中,並且最後返回一個頭指標
*返回值:ID *(結構體指標)
*************************************************/
ID * Read()
{
    FILE *fp; //定義一個檔案指標,接收fopen的返回值,用於最後的關閉檔案
    ID *t1,*t2,*head=NULL;
   
    if((fp=fopen("student.txt","r"))==NULL)      //判斷檔案是否存在
    {
        printf("開啟檔案失敗!沒有該檔案\n\n");
  printf("請按任意鍵返回主選單\n");
        getch();
return 0;
     }
rewind(fp);  //這個函式是把一個檔案的位置指標從新移至開頭,不然的話會出現一個組資料丟失
    t1=(ID *) malloc(sizeof(ID)); //申請動態空間
    head=t2=t1; //把t1賦給頭結點
    while(!feof(fp)) //feof函式的功能是判斷這個檔案是不是結束了,如果結束了,返回一個非零值,否則返回一個0,
    {
        if(fread(t1,sizeof(ID),1,fp)!=1) //fread函式返回讀出資料項的個數
           break;  //如果沒有讀取內容,則結束 
        t1->next=(ID *)malloc(sizeof(ID)); //把在申請動態空間的同時,把t1的next指向下一個結點
        t2=t1;     //t2是真正的尾節點
t1=t1->next; //t1向後移一個結點
    }
    t2->next=NULL; 
fclose(fp); //關閉檔案
    return head; //返回一個頭指標,因為在沒有建立一個單鏈表和檔案的時候,就是靠這個頭指標進行一系列的操作的
}




/************************************************
*函式名: Display(顯示學生檔案)
*功能:顯示聯絡人資訊
*返回值:無返回值)
*************************************************/
void Display(ID * head)
{
ID *t1=head;
printf("\n學生姓名==學號=====性別===年齡==語文成績==數學成績==英語成績==總分==平均分\n\n");
    while(t1!=NULL)
{
printf("%-8s%-11s  %-4s  %-4d  %-8.2f %-8.2f  %-8.2f  %-8.2f %-8.2f \n",t1->name,t1->sno,t1->sex,t1->age,t1->fenshu.China,t1->fenshu.shuxue,t1->fenshu.English,t1->fenshu.sum,t1->fenshu.average);
t1=t1->next;
}
printf("\n\n簡易學生管理系統成功顯示\n");
printf("\n請按任意鍵返回主選單\n");
getch();


}



/************************************************
*函式名: Add(新增)
*功能:新增人物資訊
*返回值:ID *(結構體指標)
*************************************************/
ID* Add(ID* head)
{
    char saveflag; //存檔標誌
int k=0;

    ID *p1,*p2,*pa; //pa是用來放新增的資訊的,p1,p2是用來臨時移動的
    p1=p2=head; //先讓它們都等於頭指標
    system("cls"); //清屏
    while(p1->next!=NULL) //把p1移到尾節點
        p1=p1->next;


bb2:pa=(ID*)malloc(sizeof(ID)); //申請動態儲存空間
printf("請輸入新增人的姓名:\n");
fflush(stdin);
    scanf("%8s",pa->name);
    fflush(stdin);
    printf("請輸入學號: \n");
    scanf("%11s",pa->sno);
    p2=head;      //讓p2從頭開始遍歷
    while(p2!=NULL)       //當p2不為空時
    {
      if((strcmp(pa->name,p2->name)==0)&&(strcmp(pa->sno,p2->sno)==0))
      {
           free(pa);
           printf("你重複輸入了!\n");
           goto bb2;
 }
 
       p2=p2->next;
     }
     pa->name[8]=0;   //使得每個欄位都能有效結束
     pa->sno[11]=0;
 
fflush(stdin);
     printf("請輸入學生性別:");
scanf("%4s",pa->sex);
pa->sex[4]=0;
fflush(stdin);
     printf("請輸入學生年齡:");
scanf("%d",&pa->age);
fflush(stdin);
     printf("請輸入學生科目成績(語文,數學,英語):");
scanf("%lf%lf%lf",&pa->fenshu.China,&pa->fenshu.shuxue,&pa->fenshu.English);
pa->fenshu.sum=pa->fenshu.China+pa->fenshu.shuxue+pa->fenshu.English;
pa->fenshu.average=pa->fenshu.sum/3.0;
p1->next=pa; //尾節點p1的next新增pa
pa->next=NULL;
     printf("新新增學生資訊成功,是否存檔?(Y/N)\n");
fflush(stdin);
scanf("%c",&saveflag);//存檔?Y or N
if(saveflag=='y'||saveflag=='Y')//當輸入y Y的時候
Save(head); //呼叫儲存函式
else
{
printf("請按任意鍵返回主選單\n");
getch(); 
}
free(pa);
     return(head); 
}





/************************************************
*函式名: Change(修改) 
*功能:修改人物資訊
*返回值:ID *(結構體指標)
*************************************************/
ID* Change(ID* head)
{
    ID *p1,*p2; 
    char saveflag; 
 
    char n[10],t[12]; //存放待修改人的姓名和學號
int flag=0; //修改標誌
    system("cls"); //清屏
p1=head; 
    printf("請輸入要修改的學號:\n"); 
    scanf("%11s",t); 
    while(p1!=NULL) //這個while語句的作用是在遍歷整個單鏈表
{
  if(strcmp(p1->sno,t)==0)//判斷是不是你輸入的學號是不是和簡易學生管理系統中的相同
  {
flag=1; //當存在一樣的名字時,
printf("\n你要修改的學生資訊為:\n");
printf("\n學生姓名==學號=====性別===年齡==語文成績==數學成績==英語成績==總分==平均分\n\n");
        printf("%-8s%-11s  %-4s  %-4d  %-8.2f %-8.2f  %-8.2f  %-8.2f %-8.2f \n",p1->name,p1->sno,p1->sex,p1->age,p1->fenshu.China,p1->fenshu.shuxue,p1->fenshu.English,p1->fenshu.sum,p1->fenshu.average);

bb3:printf("\n請輸入修改後的姓名:\n");
fflush(stdin);
scanf("%8s",n);


p2=head; //讓p2從頭開始遍歷
while(p2!=NULL)//當p2不為空時
{
if((strcmp(n,p2->name)==0)&&(strcmp(t,p2->sno)==0))
{
printf("你重複輸入了。\n");
goto bb3;
}
p2=p2->next;
}


strcpy(p1->name,n);
p1->name[8]=0;
fflush(stdin);
   printf("請輸入學生性別:");
   scanf("%4s",p1->sex);
p1->sex[4]=0;
fflush(stdin);
   printf("請輸入學生年齡:");
   scanf("%d",&p1->age);
   fflush(stdin);
   printf("請輸入學生科目成績(語文,數學,英語):");
   scanf("%lf%lf%lf",&p1->fenshu.China,&p1->fenshu.shuxue,&p1->fenshu.English);
   p1->fenshu.sum=p1->fenshu.China+p1->fenshu.shuxue+p1->fenshu.English;
   p1->fenshu.average=p1->fenshu.sum/3.0;
printf("該學生資訊已修改成功\n");
printf("學生資訊已經新建成功,是否進行儲存? (Y/N)\n");
fflush(stdin);
scanf("%c",&saveflag);
if(saveflag=='y'||saveflag=='Y')//當輸入是的時候
Save(head); //呼叫儲存函式
else
{
printf("請按任意鍵返回主選單\n");
getch(); 
}
break;
  }  
  p1=p1->next;  //p1指標向後移
}
    if(flag==0) //沒有這個名字的人,返回主選單
{
        printf("\n沒有找到要修改的學生資訊,請按任意鍵返回主選單!\n");
getch(); //按下任意鍵就進入下一條語句的函式
    }
return(head);    
}
/************************************************
*函式名:Search(查詢)
*功能:可以通過姓名查詢,也可以通過型別查詢
*返回值:NULL
*************************************************/
void Search(ID *head)
{
int num; //子選單選擇
int count=0;
ID* p; 
int flag; //flag是用來判斷是否找到,
char c[10],searchflag='y';//c是來存放姓名或者型別,
    char ch[12];
while(1)
{
searchflag='y';
printf("\n**************查詢子選單*******************\n");
printf("\n\t 1.按姓名\n");
printf("\n\t 2.按學號\n");
printf("\n\t 3.返回主選單\n");
printf("\n*******************************************\n");
fflush(stdin);
printf("請輸入您的選擇:\n");
scanf("%d",&num);//選擇你想要查詢的方式 
switch(num) 
{

case 1: while(searchflag=='y'||searchflag=='Y') 
{
count=0;
flag=0; //初始化為0
printf("\n請輸入待查詢的姓名: \n");
scanf("%8s",c);
p=head; 
while(p!=NULL)
{
  if(strcmp(p->name,c)==0)
  {  
  count++;
  if(count==1)
printf("\n學生姓名==學號=====性別===年齡==語文成績==數學成績==英語成績==總分==平均分\n\n");
                    printf("%-8s%-11s  %-4s  %-4d  %-8.2f %-8.2f  %-8.2f  %-8.2f %-8.2f \n",p->name,p->sno,p->sex,p->age,p->fenshu.China,p->fenshu.shuxue,p->fenshu.English,p->fenshu.sum,p->fenshu.average);

  flag=1; //flag賦值為1,表示為已經查到了資料了   
  }
  p=p->next; //p1指標向後移
}
if(flag==0) //表示沒有找到相關資料
{
printf("\n未能找到符合條件的記錄\n");
}
else
printf("\n\n\######找到了%d個姓名為\"%s\"學生!#####\n\n",count,c);
printf("\n查詢完畢,是否需要重新查詢? (Y/N)\n");
fflush(stdin);
scanf("%c",&searchflag);//是否繼續查詢(Y/N) 
}
break;
case 2: 
while(searchflag=='y'||searchflag=='Y')
{
count=0;
flag=0; //初始化為0,
printf("\n請輸入被查詢人的學號: \n");
scanf("%11s",ch);


p=head; 
while(p!=NULL)
{
  if(strcmp(p->sno,ch)==0)
  {
  count++;
  if(count==1)
printf("\n學生姓名==學號=====性別===年齡==語文成績==數學成績==英語成績==總分==平均分\n\n");
                        printf("%-8s%-11s  %-4s  %-4d  %-8.2f %-8.2f  %-8.2f  %-8.2f %-8.2f \n",p->name,p->sno,p->sex,p->age,p->fenshu.China,p->fenshu.shuxue,p->fenshu.English,p->fenshu.sum,p->fenshu.average);

  flag=1; //flag賦值為1,表示為已經查到了資料了   
  }
  p=p->next;  //p1指標向後移
}
  if(flag==0) //表示沒有找到相關資料
{
printf("\n對不起,未能找到符合條件的記錄\n");
}
  else
printf("\n\n\######找到了該學生!#####\n\n");
printf("\n查詢完畢,是否需要重新查詢? Y/N\n");
fflush(stdin);
scanf("%c",&searchflag);//是否繼續查詢(Y/N)
}
break; 
case 3:return;
default :printf("你輸入錯了,請你輸入任意鍵返回主選單...\n");
    getch();
}
}
}


/************************************************
*函式名: Delete(刪除)
*功能:通過查詢學號來實現刪除學生記錄
*返回值:ID *(結構體指標)
*************************************************/
ID* Delete(ID *head)
{
ID *p1,*p2; //p1是用來遍歷整一個單鏈表定位要刪除的結點,p2是用來定位p1的前結點的
    char saveflag='n', temp; //saveflag是否儲存,temp是否刪除


char s[12]; //存放輸入的學號 
    p1=p2=head; //把head賦給p1,p2  
    printf("\n請輸入要刪除的學號:\n");
    scanf("%11s",s);
getchar();
while(p1!=NULL)//這個while語句的作用是在遍歷整個單鏈表時,當遇到一樣的名字時把i賦值,引導下面的工作
{
  if(strcmp(p1->sno,s)==0)//判斷是不是你輸入的名字是不是和學生資訊中的相等
  {
printf("你要刪除的學生為:\n");
   printf("\n學生姓名==學號=====性別===年齡==語文成績==數學成績==英語成績==總分==平均分\n\n");
            printf("%-8s%-11s  %-4s  %-4d  %-8.2f %-8.2f  %-8.2f  %-8.2f %-8.2f \n",p1->name,p1->sno,p1->sex,p1->age,p1->fenshu.China,p1->fenshu.shuxue,p1->fenshu.English,p1->fenshu.sum,p1->fenshu.average);
printf("請確定是否要刪除該記錄?Y/N?\n");
fflush(stdin);
scanf("%c",&temp);//確定要刪除嗎? 
if(temp=='y'||temp=='Y')//當輸入是的時候
{
  if(p1==head)//判斷是不是在頭結點
  head=p1->next;//把頭結點去掉
  else


  p2->next=p1->next;//刪除p1結點(p2的next域指向p1的下個結點)
  printf("該學生資訊已刪除成功,是否存檔?Y/N?\n");
  fflush(stdin);
  scanf("%c",&saveflag);//確定要儲存嗎?
  if(saveflag=='y'||saveflag=='Y')//當輸入是的時候
 Save(head); //呼叫儲存函式
  else
{
printf("請按任意鍵返回主選單\n");
getch(); 
}
}
else
{
printf("請按任意鍵返回主選單\n");
getch(); 
}
break;
  }
  p2=p1;
  p1=p1->next;  //p1指標向後移
}
if((p1->next)==NULL&&strcmp(p1->sno,s))
{
printf("沒有找到要刪除的學生學號,請檢查你要刪除的學號是否正確\n");
printf("請按任意鍵返回主選單\n");
getch(); //按下任意鍵就進入下一條語句的函式 

}
return(head); //return一個已經完成修改的連結串列頭指標   
}


/************************************************
*函式名: Swap(交換)
*功能:交換結點內資料
*返回值:無
*************************************************/
void Swap1(char t1[],char t2[])
{
char t[20]={0};
strcpy(t,t1);
strcpy(t1,t2);
strcpy(t2,t);


}
void Swap2(double s1,double s2)
{
double s;
s=s1;
s1=s2;
s2=s;
}
void Swap3(int r1,int r2)
{
int r;
r=r1;
r1=r2;
r2=r;
}
/************************************************
*函式名: Sort(排序)
*功能:按照型別排序通訊記錄
*返回值:ID *(結構體指標)
*************************************************/
void Sort(ID *head)
{
ID  *p1,*p2;
char saveflag='y';
p2=NULL;


while( head != p2)
{
p1 = head;
while( p1->next!= p2 )
{  
if( strcmp(p1->sno,p1->next->sno)>0)
{
Swap1(p1->name,p1->next->name);
Swap1(p1->sno,p1->next->sno);

Swap1(p1->sex ,p1->next->sex );
Swap2(p1->fenshu.China,p1->next->fenshu.China);
Swap2(p1->fenshu.shuxue,p1->next->fenshu.shuxue);
Swap2(p1->fenshu.English,p1->next->fenshu.English);
Swap2(p1->fenshu.sum,p1->next->fenshu.sum);
Swap2(p1->fenshu.average,p1->next->fenshu.average);
Swap3(p1->age,p1->next->age);




            } 
p1 = p1->next;
        }
  p2= p1;
    }


printf("學生已按照 學號型別 排序成功,是否存檔?Y/N?\n");
fflush(stdin);
scanf("%c",&saveflag);//確定要儲存嗎?
if(saveflag=='y'||saveflag=='Y')//當輸入是的時候
Save(head); //呼叫儲存函式
}