火車訂票系統學習筆記
阿新 • • 發佈:2019-01-13
/* 系統名稱:火車訂票系統 1、插入一個火車資訊 2、搜尋火車資訊 3、預定火車資訊 4、修改火車資訊 5、顯示火車資訊 6、儲存火車資訊 結構組成 1、火車資訊結構體 2、訂票人資訊結構體 3、火車資訊連結串列節點結構體 4、訂票人的連結串列節點結構體 操作流程: 進入主介面 -》 選擇選單 -》選擇基本操作 -》顯示結果 -》儲存資訊 -》退出 */ #include "stdio.h" #include "stdlib.h" #include "string.h" int saveflag = 0; //定義是否儲存是否檔案改變(全域性變數) (1、表示未儲存 0、表示已儲存) #define HEADER1 "---------------------------------火車訂票系統-----------------------------\n" #define HEADER2 "| 編號 | 起始城市 | 抵達城市 | 起始時間 | 到達時間 |票的價格 | 車票數量|\n" #define HEADER3 "--------------------------------------------------------------------------\n" #define FORMAT "%- 10s%- 10s%- 10s%- 10s%- 10s %5d %5d\n" #define DATA q->data.num,q->data.startcity,q->data.reachcity,q->data.takeofftime,q->data.receivetime,q->data.price,q->data.ticketnum /*定義儲存火車資訊的結構體*/ struct train{ char num[10]; //列車號 char startcity[10]; //出發城市 char reachcity[10]; //目的城市 char takeofftime[10]; //發車時間 char receivetime[10]; //到達時間 int price; //票價 int ticketnum; //票數量 }; /*訂票人的資訊*/ struct man{ char num[20]; //×××號碼 char name[10]; //姓名 int bookNum; //訂票的數 }; /*定義火車連結串列的節點結構*/ typedef struct node{ struct train data; struct node *next; }Node,*Link; /*定義訂票人鏈表的節點結構域*/ typedef struct Man{ struct man data; struct Man *next; }book,*bookLink; /*初始化介面*/ void menu() { puts("\n\n"); puts("\t\t|----------------------------------------------------------|"); puts("\t\t| 火車訂票系統 |"); puts("\t\t|----------------------------------------------------------|"); puts("\t\t| 0:退出系統 |"); puts("\t\t| 1:插入一個火車資訊 |"); puts("\t\t| 2:搜尋火車資訊 |"); puts("\t\t| 3:預定火車票 |"); puts("\t\t| 4:修改火車資訊 |"); puts("\t\t| 5:顯示火車資訊 |"); puts("\t\t| 6:儲存資訊到檔案 |"); puts("\t\t|----------------------------------------------------------|"); } //新增一個火車資訊 void Trianinfo(Link linkhead) { struct node *p,*r,*s; char num[10]; r = linkhead; //連結串列的頭指標不能移動(在以後的查詢中無法找到頭指標) s = linkhead->next; //連結串列頭指標後面一個節點才開始有火車資訊資料 while(r->next != NULL) //找到連結串列尾部 r = r->next; while(1) { printf("請輸入火車的編號(0-無窮大)"); scanf("%s",num); if(strcmp(num,"0") == 0) break; /*判斷是否存在*/ while(s /* s != NULL */) { if(strcmp(s->data.num , num) == 0){ printf("編號為%s的火車已存在!!\n",num); return ; } s = s->next; } p = (struct node*)malloc(sizeof(struct node)); strcpy(p->data.num,num); //將編號存放到節點裡面 printf("請輸入火車開始城市 :"); scanf("%s",p->data.startcity);//輸入出發城市 printf("請輸入火車目的城市 :"); scanf("%s",p->data.reachcity);//輸入目的城市 printf("請輸入火車出發時間 :"); scanf("%s",p->data.takeofftime);//輸入出發時間 printf("請輸入火車到達時間 :"); scanf("%s",p->data.receivetime);//輸入到達時間 printf("請輸入票價:"); scanf("%d",&p->data.price);//輸入票價 printf("請輸入票數:"); scanf("%d",&p->data.ticketnum);//輸入票數 p->next = NULL; r->next = p; //插入到連結串列 r = p; saveflag = 1; } } //列印火車頭資訊 void printheader() { printf(HEADER1); printf(HEADER2); printf(HEADER3); } /*格式化輸出表中的資料*/ void printdata(Node *p) { Node* q ; q = p; printf(FORMAT,DATA); } /*顯示火車票資訊*/ void showtrain(Link l) { Node *p; p = l->next;//連結串列頭指標後面一個節點才開始有火車資訊資料 printheader(); //列印頭部資訊 if(l->next == NULL) //是否為空連結串列 printf("是空連結串列"); else while(p != NULL) { printdata(p); p = p->next; } } /*查詢火車資訊*/ void searchtrian(Link l) { Node *s[10],*r; //*s[10]用來儲存尋找到的物件 int sel,k,i = 0; //sel表示選擇查詢方式 char str1[10],str2[10];//str1用來輸入火車編號 ,str2用來輸入城市名稱 if(!l->next){ printf("沒有任何記錄"); return; } printf("選擇方式:\n 1:根據火車編號; \n 2:根據城市:\n"); scanf("%d",&sel);//輸入選擇的序號 if(sel == 1)//根據火車編號來查詢 { printf("輸入火車編號:"); scanf("%s",str1); r = l->next; //連結串列是從第二個元素開始才有資料 while(r != NULL) { if(strcmp(r->data.num,str1) == 0)//檢索是否有與輸入的編號相匹配 { s[i] = r; //把已經找到的節點存放到定義好的結構體指標陣列 i++; r = r->next;//繼續往表的後面尋找 }else r = r->next;//繼續往表的後面尋找 } if( i == 0) printf("找不到相對應的編號的火車"); } else if(sel == 2)//根據城市來查詢 { printf("輸入想要去的城市:"); scanf("%s",str2); r = l->next; //連結串列是從第二個元素開始才有資料 while(r != NULL) { if(strcmp(r->data.reachcity,str2) == 0)//檢索是否有與輸入的編號相匹配 { s[i] = r; //把已經找到的節點存放到定義好的結構體指標陣列 i++; r = r->next;//繼續往表的後面尋找 }else r = r->next;//繼續往表的後面尋找 } if( i == 0) printf("找不到相對應的城市的火車"); } printheader(); for(k = 0 ; k < i ; k++) printdata(s[k]); } /*修改火車資訊*/ void Modify(Link l) { Node *p ; //p節點從第二個節點開始(因為第二個節點才有資料) char tnum[10],ch;//ch判斷是否修改 tnum[10]火車編號的輸入 p = l->next; if(!p/* p != NULL */) { printf("你沒有記錄可以修改"); return; } else { printf("\n你想修改它麼??(y/n)\n"); scanf("%c",&ch); if(ch == 'y'|| ch == 'Y')//字元的比較 { printf("\n輸入火車編號:"); scanf("%s",tnum); while(p != NULL) { if(strcmp(p->data.num,tnum) == 0)//查詢與輸入的編號相匹配的記錄 break; //如果已經找到 我們的p肯定不為NULL else p = p->next; } if(p)//如果找到的p不為空 { printf("輸入火車的起始城市:"); scanf("%s",p->data.startcity); printf("輸入火車的目的城市:"); scanf("%s",p->data.reachcity); printf("輸入火車的起始時間:"); scanf("%s",p->data.takeofftime); printf("輸入火車的抵達時間:"); scanf("%s",p->data.receivetime); printf("輸入火車的票的價格:"); scanf("%d",&p->data.price); printf("輸入火車的票的數量:"); scanf("%d",&p->data.ticketnum); saveflag = 1;//資料發生改變需要儲存 } else/*沒有找到跳到此地*/ printf("沒有找到該編號的火車"); } } } /*訂票模組*/ void Bookticket(Link l,bookLink k)//l是火車連結串列 k是人員連結串列 { Node *r[10],*p;//r存放滿足條件的火車資訊 /*str表示輸入想去城市、ch判斷是否訂票*,tnum 表示火車車次*/ char ch[2],tnum[10],str[10],str1[10],str2[10]; book *q,*h; int i = 0, t = 0,flag = 0,dnum;//i 記錄滿足條件的火車資訊的數量,t 進行迴圈列印火車資訊 flag 標誌有票 dnum 買票的數量 q = k;//將人員連結串列的表頭賦值給q while(q->next != NULL) q = q->next; //遍歷人員連結串列(新增訂票人資訊,從連結串列尾部新增) printf("輸入你想去的城市: "); scanf("%s",str); p = l->next;//連結串列的第二節點才有資料 while( p != NULL)//遍歷火車資訊連結串列 { if(strcmp(p->data.reachcity,str) == 0)//如果找到你想去的城市 { r[i] = p;//將滿足條件的記錄存到陣列r中 i++; } p = p->next; } printf("\n\n記錄的數量%d\n",i); printheader(); for(t = 0 ; t < i ; t++) printdata(r[t]); if(i == 0)//如果沒有找到你想去的城市 printf("沒有你所要找的車次"); else//如果找到就訂票 { printf("\n你想要訂票麼?<y/n>\n"); scanf("%s",ch); if(strcmp(ch,"Y")== 0 || strcmp(ch,"y")==0)//進行字串的比較 { printf("請輸入需要的火車車次:"); scanf("%s",tnum); for(t = 0; t < i ; t ++) { if(strcmp(r[t]->data.num,tnum) == 0) { if(r[t]->data.ticketnum < 1)//判斷剩餘的供票數量是否為0 { printf("對不起,沒有票"); return; } printf("剩餘%d張票\n",r[t]->data.ticketnum); flag = 1;//標誌有票 break; } } if(flag == 1){ h = (book*)malloc(sizeof(book));//增加人員連結串列節點 printf("輸入你的名字: "); scanf("%s",str1); printf("輸入你的×××:"); scanf("%s",str2); printf("輸入你要的買的數量:"); scanf("%d",&dnum);/*買票的數量*/ if(dnum > r[t]->data.ticketnum){ printf("你所需要的票數過多,無法購買!!!"); return; } r[t]->data.ticketnum = r[t]->data.ticketnum-dnum;//定票成功則票數相應減少 /*對人員資訊表新增節點,q= h 表示在尾部新增*/ h->data.bookNum = dnum; strcpy(h->data.name,str1); strcpy(h->data.num,str2); h->next = NULL; q->next = h; q = h; printf("\n恭喜購票成功!!!\n"); saveflag = 1; } else{ printf("輸入有誤"); return; } } } } void SaveTrainInfo(Link l) { FILE *fp;//申明一個檔案指標 Node *p;//申明一個火車的節點 int count = 0 , flag = 1; fp = fopen("g:/train.txt","wb"); if(fp == NULL) { printf("無法開啟該檔案"); return ; } p = l->next; while(p) { if(fwrite(p,sizeof(Node),1,fp) == 1){//每次寫入一個結構進去 p = p->next; count++; }else { flag = 0; break; } } if(flag){//如果寫入成功 printf("儲存%d列火車記錄\n",count); saveflag = 0; }else{ printf("儲存檔案失敗"); } fclose(fp); } /*儲存訂票人的資訊*/ void SaveBookInfo(bookLink k) { FILE *fp;//申明一個檔案指標 book *p;//申明一個火車的節點 int count = 0 , flag = 1; fp = fopen("g:/man.txt","wb"); if(fp == NULL) { printf("無法開啟該檔案"); return ; } p = k->next; while(p) { if(fwrite(p,sizeof(book),1,fp) == 1){//每次寫入一個結構進去 p = p->next; count++; }else { flag = 0; break; } } if(flag){//如果寫入成功 printf("儲存%d列人員記錄\n",count); saveflag = 0; }else{ printf("儲存檔案失敗"); } fclose(fp); } int main(){ FILE *fp1,*fp2;//fp1檔案指標對應火車資訊,fp2檔案指標對應人員資訊 Node *p,*r; //表示火車資訊節點 p用來表示讀檔案的節點 char ch1,ch2; Link l; //表示火車資訊的連結串列 l指的是連結串列的首位 bookLink k; //這裡表示人員的連結串列 book *t,*h; //表示人員的節點 int sel; //選擇選單變數 l = (Node*)malloc(sizeof(Node)); l->next = NULL; //它下一個節點指向NULL r = l; //利用r來做一個迴圈表示 k = (book*)malloc(sizeof(book)); k->next = NULL; //它下一個節點指向NULL h = k; /*火車基本資訊的讀取*/ fp1 = fopen("g:/train.txt","ab+"); //開啟儲存火車資訊的檔案(如果沒有該檔案就寫一個) if(fp1 == NULL){ printf("無法開啟該檔案"); return 0; } while(!feof(fp1)){ //feof()函式表示讀檔案到了檔案的結尾( EOF表示檔案的結尾) p = (Node*)malloc(sizeof(Node)); if(fread(p,sizeof(Node),1,fp1) == 1)/*從指定磁碟檔案讀取記錄*/ { p->next = NULL; //因為p為節點,p後面現在還有指向,給它初始化 r->next = p; //構建連結串列 r = p; } } fclose(fp1); /*人員基本操作的讀取*/ fp2 = fopen("g:/man.txt","ab+"); if(fp2 == NULL){ printf("無法讀取人員基本操作檔案"); return 0; } while(!feof(fp2)){ t = (book*)malloc(sizeof(book)); if(fread(t,sizeof(book),1,fp2) == 1){ t->next = NULL; h->next = t; h = t; } } fclose(fp2); while(1){ menu(); printf("\t請選擇(0~6):"); scanf("%d",&sel); system("cls"); if(sel == 0) { if(saveflag == 1)//表示未儲存 { getchar(); printf("\n該檔案已更改!你想儲存它麼(y/n)?\n"); scanf("%c",&ch1); if(ch1 == 'y' || ch1 == 'Y'){ /*儲存 1、火車資訊檔案 2、人員操作檔案 */ SaveTrainInfo( l); SaveBookInfo(k); } } printf("\n謝謝使用 下次光臨\n"); break; } switch(sel)/*根據與輸入的sel值不同選擇相對應的操作*/ { case 1: Trianinfo(l);/*插入火車資訊*/ break; case 2: searchtrian(l);/*搜尋火車資訊*/ break; case 3: Bookticket(l,k);/*預定火車票 */ break; case 4: Modify(l);/*修改火車資訊*/ break; case 5: showtrain(l);/*顯示火車資訊*/ break; case 6: /*儲存 1、火車資訊檔案 2、人員操作檔案 */ SaveTrainInfo(l); SaveBookInfo(k); break; case 0: return 0; } printf("\n請按任意鍵繼續..."); } system("pause"); return 0; }