C语言航空订票系统课程设计
?
目錄
1.設計目的:
2總體設計和功能:
3.菜單設計
4.各功能代碼詳解(閑話少扯):
4.1.C語言文件的操作:
4.2.讀取航班信息:
C語言知識回顧?
4.3.打印航班信息
5.根據要求查找航班(航班號、起點站、終點站)
6.訂票功能(鏈表操作)
前言:最經做了一個課程設計,設計的內容就是航空訂票系統,又認真復習了一遍c語言的知識,感覺這個設計對于初學者來說,C的能力和邏輯能力會有一個提升,為了更好的總結自己學習的成果,故寫下此篇博客記錄一下該課程設計的重點知識,以便以后回顧。
1.設計目的:
1. ?數據結構課程設計是綜合運用數據結構課程中學到的幾種典型數據結構,以及程序設計語言(C語言),自行實現一個較為完整的應用系統的設計與開發
2. ?通過課程設計,自己通過系統分析、系統設計、編程調試,寫實驗報告等環節,進一步掌握應用系統設計的方法和步驟,靈活運用并深刻理解典型數據結構在軟件開發中的應用 。
3. ?學會將知識應用于實際的方法,提高分析和解決問題的能力,增加綜合能力。
??航空訂票系統:
(1)熟練掌握鏈表存儲結構及其建立過程和常用操作;
(2)熟練掌握隊列的建立過程和常用操作;
(3)學會自己調試程序的方法并掌握一定的技巧。
2總體設計和功能:
通過此系統可以實現如下功能:
?
3.菜單設計
3.1主菜單代碼如下:
int main() {int sel;readinfo(&L);readinfo_book(&B);InitOrder();while (1){printf("\n\n\n\n");printf("\t歡迎進入航班訂票系統\n");printf("*****************************\n");printf("* 航空訂票客運系統 *\n");printf("* 1.顯示各航線信息 *\n");printf("* 2.查詢各航線信息 *\n");printf("* 3.訂 票 *\n");printf("* 4.退 票 *\n");printf("* 0.退 出 系 統 *\n");printf("*****************************\n");printf("請 選 擇(0-4):\n");scanf("%d", &sel);switch (sel){case 1:meau1(); break;//選擇菜單1case 2:meau2(); break;//選擇菜單2case 3:orderTicket(); break;//訂票case 4:refund_ticket(); break;//退票case 0:return;//退出程序default:printf("輸入錯誤\n"); break;}}?界面如下:
主程序是整個系統的入口,首先初始化L和B的結構體變量,打印提示信息,然后讓用戶輸入一個數值,從.0-4,輸入數值1進入菜單1(meau1()):
meau1()程序如下:
void meau1(void) {int subsel;while (1){printf("============================\n");printf("= 顯示各航線信息的子菜單 =\n");printf("============================\n");printf("* 1.顯示所有航線 *\n");printf("* 2.顯示訂單客戶 *\n");printf("* 3.返回主菜單 *\n");printf("============================\n");printf("請 選 擇(1-3):\n");scanf("%d", &subsel);switch (subsel){case 1:printAllofAirMsg(); break;case 2:printOrderCustomByAirNum1(); break;case 3:return;default:printf("輸入錯誤\n"); break;}} }界面如下:
meau2()?程序如下:
void meau2(void) {int subsel;while (1){printf("============================\n");printf("= 航線信息查詢子菜單 =\n");printf("============================\n");printf("* 1.按航班號查詢 *\n");printf("* 2.按起點站查詢 *\n");printf("* 3.按終點站查詢 *\n");printf("* 4.返回主菜單 *\n");printf("============================\n");printf("請 選 擇(1-4):\n");scanf("%d", &subsel);switch (subsel){case 1:searchbyAirno(); break;case 2:searchbystartPlace(); break;case 3:searchbyEndPlace(); break;case 4: return;default:printf("輸入錯誤\n"); break;}} }界面如下:?
還有一些菜單都是都是比較簡單的知識,直接看源代碼即可。?
?
4.各功能代碼詳解(閑話少扯):
4.1.C語言文件的操作:
- 文件操作基礎知識解析:點我查看
在這個系統中,需要讀取兩個文件,一個是航班信息文件,一個是訂票客戶信息文件,后綴都是(.txt),內容如下:
航班信息.txt
航班號 起點 終點 飛行日 起飛時間 到達時間 機型 價格 乘員定額 余票量 CA1544 合肥 北京 1.3.5 10:55 12:40 A733 960 100 90 MU5341 上海 廣州 每日 14:20 16:15 M90 1280 150 150 CZ3869 重慶 深圳 2.4.6 08:55 10:35 733 1010 100 100 MU3682 桂林 南京 2.3.4 20:50 22:15 M90 1380 150 120 HU1836 上海 北京 每日 09:40 11:20 738 1250 120 120 CZ3528 成都 廈門 1.3.5 15:10 16:50 CRJ 1060 130 130 MU4594 昆明 西安 2.4.6 10:15 11:40 328 1160 140 140 SC7425 青島 海口 1.3.6 19:20 21:20 DH4 1630 190 190 CA1234 洛陽 上海 1.3.5 08:00 10:00 DH4 1050 300 300 CA4321 shai 洛陽 2.4.6 16:00 18:00 DH4 1100 300 300訂票信息.txt
航班號 姓名 身份證 訂票數量 CA1544 丁方 410221 4 CA1544 邢風 410222 4 CA1544 劉向 410223 2 MU5341 wan 415225 2 MU5341 嚴寒 412003 12 MU3682 吳偉 412009 2 MU3682 劉敏 400281 1在系統運行時,首先會從電腦本地磁盤讀取上面兩個文件的信息到兩個不同的結構體里面,然后就可以通過讀取結構體的內容獲取到這個航班信息和訂票客戶的信息了(注意結構體的成員變量應該是和我們所需要讀取文件的內容是一致的,就是說要讀取多少的內容,就需要為這個結構體變量開辟多少的靜態內存):
航班信息結構體如下:
//航班信息結構體定義,每個航班號都會有不同的乘客名單,所以每個航班都應該有一個鏈表 typedef struct airinfo {char Airno[8];//航班號char start[6];//出發地char end[6];//目的地char sche[6];//飛行日char time1[8];//出發時間char time2[8];//到達時間char mode[5];//機型int price;//票價int fixed;// 乘客定額int remained;//余票PBookList order;/*指向乘員名單鏈表的頭指針,通過這個指針就可以找到所有乘客的名單了*/ }AirInfo,*PAirInfo;客戶訂單結構體:
//航訂票客戶列表體結構體定義 typedef struct Book {char Airnum[8];//航班號char name[20];//客戶姓名 char didentify[6];//身份證號 int order_amount;//訂票數量int grade;struct Book *Pnext;//指向下一個用戶的首地址 }*PBookList, BookList;接下來再定義兩個結構體,去定義航班信息和客戶的總體信息,以及統計航班數和客戶訂單數量:
//航班信息總體結構體定義 typedef struct {AirInfo s[MAX]; //航班信息數組int acount; //記錄當前航班信息數 }SSList; //訂單客戶總體信息 typedef struct {BookList book[BOOKMAX];int book_acount; }SbookList;#define MAX 20 #define BOOKMAX 1004.2.讀取航班信息:
下貼上程序,然后再進行分析:
//讀取文本信息,并賦值給結構體變量,傳入的參數是SSList結構體變量的指針 void readinfo(SSList *L) {FILE *fp;//定義文件指針if ((fp = fopen("航班信息.txt", "r")) == NULL){printf("航班文件不存在 \n");exit(1);}else{int i = 0; char tep[500];L->acount = 0; //航班次數初始化while (!feof(fp)){fgets(tep, 500, fp);//讀取第一行說明:航班號 起點 終點 略..;//讀取正確的信息;if (10 != fscanf(fp, "%s %s %s %s %s %s %s %d %d %d", L->s[i].Airno, L->s[i].start, L->s[i].end, L->s[i].sche, L->s[i].time1, L->s[i].time2,L->s[i].mode, &L->s[i].price, &L->s[i].fixed, &L->s[i].remained)){printf("讀取文件出錯\n");//關閉文件流指針,退出;fclose(fp);exit(1);}i++;L->acount++;}}fclose(fp); }程序分析:
提示:文件讀取的詳細解釋:帶我查看
注意:這里打開的文件使用的相對路徑。?
如果fopen返回了打開文件的首地址,打開成功,進行航班信息的讀取工作。
-
fcanf函數的講解
格式化輸入函數fscanf
?調用:fscanf(fpt,格式控制,地址列表);
?功能:以ASCII碼值的方式從fpt關聯的文件中讀取數據,按格式控制字符串中指定的數據格式轉換后送到由輸入地址列表中相應項指定的內存單元。函數返回值為正確處理的數據項個數。
例子:
如果文件的內容為 ”6,6.6“,則可以使用如下語句讀取:
//m和a是已經定義的int類型和double類型的變量
fcanf(fp,"%d,%lf",&m,&a);???//注意此處是地址列表
?
fscanf(fp, "%s %s %s %s %s %s %s %d %d %d",
?? ??? ??? ??? ?L->s[i].Airno, L->s[i].start, L->s[i].end, L->s[i].sche,
?? ??? ??? ??? ?L->s[i].time1,L->s[i].time2,L->s[i].mode, &L->s[i].price,?
?? ??? ??? ??? ?&L->s[i].fixed, &L->s[i].remained))
解釋:fscanf函數的第一個參數是打開文件的指針變量,第二個參數格式控制,第三個參數就是讀取的地址列表。
我們需要讀入的數據以空格隔開,共有十個數據,所以上面橙色字體的格式控制有10個,我們需要讀入的是結構體里面,定義了一個結構體變量L來存放它。
為什么是這種形式賦值:L->s[i].Airno?
回憶一下:我們傳入這個函數的形參是SSList *類型的
這里為了去統計航班信息數,使用了一個結構體的嵌套:如下:
如果在函數void readinfo(SSList *L),中需要去改變第i個航班的Airno的成員變量的值,如何做?
C語言知識回顧?
此處就涉及到了C語言指針一些語法的問題了,先復習一下指針的知識吧,例如我定義了一下的兩個變量
int a=5; //定義了一個整形變量a int * b; //定義了一個變量b,這個變量是整形的指針變量,用于存放整形數據的地址 b = &a; //把a的地址 賦予給b這個指針變量上面的語句相當于做了什么事呢?用一個簡圖表示如下:
那么在C語言中有規定,此時:*b? 和? a?的值是相等的。
注意:*b的含義是:以b內容(1000h)為地址的變量的值(那就是變量a的值咯)。
繼續深入,結合結構體:
現在定義一個如下的結構體:
typedef struct student {int age; //結構體成員變量int num; }stu;stu stu1; //定義了一個結構體變量stu1,此時已經在內存開辟了一塊靜態空間給結構體變量stu1,因為沒有//進行賦值,所以里面的是垃圾值如果此時我們想在主函數調用一個函數去改變這個stu1結構體變量的信息,如何做?
提示:如果我們想通過函數調用的方法去改變一個函數的值,那必須傳遞指針才能做到,因為當你在主函數中調用一個函數,那么此時就會分一塊新的空間給這個函數,即使我們改變了調用函數的值,但是函數執行結束,就會自動釋放內存,也無法把我們想要的結果傳遞回來。所以在主函數通過調用函數的方式改變一個變量或者結構體變量,必須傳遞指針(當然還有返回值,但是返回值只能返回一個數據)。
因此定義一個函數為:void change_stu_msg(stu * student)
那么在這個函數中應該怎樣寫,可以考慮一下,這個函數的形參是stu *?類型的,表示的是接受stu結構體變量的地址,那么想要改變stu1這個結構體變量的內容,傳遞進來的應該是 :?stu1的地址(&stu1)。
通過上面知道,此時?student = &stu1,也就是student這個結構體指針變量存放了stu1的地址。
那么,*student?就等價于 stu1 ,此時想要改變stu1結構體變量的值,函數就可以如下這樣寫:
void change_stu_msg(stu * student) {(*student).age=10;(*student).num=20;}那么當我們在main主函數中調用這個函數:change_stu_msg(&stu1);
執行結果:這個結構體變量的成員,age=10,num=20;不再是一個垃圾值了。
那么箭頭? ->?和這個有什么關系??這點其實就是語法的規定而已
在C語言中規定:
還是拿上面的函數舉例,為了方便書寫,可以把 :(*student).? ? 等價成為? ? ->? ??
那么?void change_stu_msg(stu * student)?也可以這樣子寫:
void change_stu_msg(stu * student) {student->age=10;student->num=20;}這下應該對上面的賦值語句有所了解了吧。
復習完C語言的知識,回到剛剛那么問題:
如果在函數void readinfo(SSList *L),中需要去改變第i個航班的Airno的成員變量的值,如何做?
這個函數的形參不就是接受一個?SSList?結構體變量的指針嘛,那先定義一個結構體變量咯:SSList L;
提示:其實這個L變量就是用來存放我們的數據的,只是現在是一些垃圾值,void readinfo(SSList *L)?這個函數就是對這個變量?L?進行初始化滴。
那在主函數中調用的話,必須把L的指針傳遞進去,即為:readinfo(&L);
此時就會有這樣的一個關系:?L = &L;? ? ?//注意此時這兩個L不是一樣的,一個是實參,一個是形參。形參的L可以隨便改
這樣看起來怪怪的,把形參的L修改成?List?把,這樣容易看一點 ,即為:void readinfo(SSList *List)?
此時有這樣一個關系:?List = &L;? ??那么 *List = L?。
而L結構體有兩個成員變量,如下:
改變第一個成員變量的值使用:(*List).s[MAX]?
可以看到s[MAX]?是一個數組,他是一個怎樣的數組呢?AirInfo類型的數組,而Airinfo是一個結構體,那s[MAX]?就是一個結構體數組(定義MAX為20),AirInfo結構體有什么內容?
從內存角度來說其實就是開辟了類似如下的一大塊靜態內存:
那么想改變第2個航班的信息,就必須定位到 s[1]這個結構體咯,即為:(*List).s[1]
想改變這個結構體變量? s[1]的成員變量? Airno[8],如何做?? 即為:(*List).s[1].Airno ="Hello"??
在C語言復習那部分,知道??(*List).? 可以等價于? List->
這樣子就可以回答上面提出的問題了:
如果在函數void readinfo(SSList *List),中需要去改變第i個航班的Airno的成員變量的值,如何做?
在函數中可以這樣寫:List->s[ i ].Airno ="Hello";
?
從本地磁盤讀取用戶信息,因為其邏輯和讀取航班信息是一樣的,只貼出程序:
//讀取訂單客戶的文件,傳入的參數是BookList結構體變量的指針。 //讀取到訂單客戶的信息應給是存儲在一個數組里面。例如:book[BOOKMAX]; void readinfo_book(SbookList * book) {FILE *fp;//定義文件指針if ((fp = fopen("訂票信息.txt", "r")) == NULL) //以只讀的方式打開{printf("訂票信息.txt文件不存在 \n");exit(1);}else{int i = 0; char title[500]; //讀B.book_acount = 0;while (!feof(fp)) //C提供了一個測試文件狀態的函數feof(pf),當文件未結束時feof函數的值為0,//否則為非0值。使用函數feof來判斷文件是否結束既可用于文本文件,還可用于二進制文件{fgets(title, 500, fp);//讀取第一行說明:航班號 起點 終點 略去;//讀取正確的信息,格式化讀取信息,把fp所指向的文件讀取到結構體里面去if (4 != fscanf(fp, "%s %s %s %d", B.book[i].Airnum, B.book[i].name, B.book[i].didentify, &B.book[i].order_amount)){printf("讀取文件出錯\n");//關閉文件流指針,退出;fclose(fp);exit(1);}i++;B.book_acount++;}}fclose(fp); }有了這兩個結構體和結構體成員變量,還有文件讀取函數,就可以把這些航班信息和客戶信息讀取到我們所定義的結構體里面,我們結構體就是存儲。也就是存儲到如下的結構體里面
4.3.打印航班信息
通過在主函數調用讀取航班信息和讀取訂票用戶信息,然后把文本數據讀取到L和B的結構體變量:
通過上面的函數在結構體變量已經進行了賦值,也就是說我們的航班信息和客戶訂票信息已經儲存于內存了。
接下來就可以通過調用相應的結構體去讀取信息啦:
- 打印航班信息:
代碼如下,此處把結構體成員變量L的內容打印出來:
void printAllofAirMsg(void) {int i = 0;for (i = 0; i < L.acount; i++) //L.account是統計航班個數的,打印所有航班{printf("航班號 起點 終點 飛行日 起飛時間 到達時間 機型 價格 乘員定額 余票量\n");printf("%s %s %s %s %s %s %s %d %d %d\r\n", L.s[i].Airno, L.s[i].start, L.s[i].end, L.s[i].sche, L.s[i].time1, L.s[i].time2, L.s[i].mode, L.s[i].price, L.s[i].fixed, L.s[i].remained);} }已上的程序完成了一些簡單的文件操作,需要掌握的知識是:
1.文件的操作
2.結構體的定義
3.結構體變量的賦值
4.打印結構體變量的內容?
5.根據要求查找航班(航班號、起點站、終點站)
此處只講解一下按航班號查詢航班信息,其他兩個查詢方式幾乎和第一個一樣。
先貼出代碼如下:
/*根據客戶提出的航班號輸出航線信息*/ void searchbyAirno() {PAirInfo info, a;char Airnum01[10];int i = 0, sel;info = L.s;a = L.s;printf("===============================\n");printf("== 為您列出航班號供您選擇: =\n");for (int j = 0; j < L.acount; j++){printf("%d %s\n", j, a[j].Airno);}printf("===============================\n");printf("請輸入要選擇航班的序號:");scanf("%d", &sel);//根據用戶的選擇,給Airnumber變量賦值不同的航班號if (sel >= L.acount) {printf("輸入錯誤\n");return;}else //輸入的序列號有效{strcpy(Airnum01, info[sel].Airno);}while (i < MAXSIZE){if (!strcmp(Airnum01, a[i].Airno)) break;i++;}if (i >= MAXSIZE){printf("\n\n");printf("對不起,該航線未找到!\n");printf("\n\n");}else{printf("================================================================================\n");//printf("航班號 起點 終點 飛行日 起飛時間 到達時間 機型 價格 乘員定額 余票量\n");printOneofAirMsg(i);} }在界面上顯示效果如下:
接下來讀取航班序號,來判斷你選擇的航班信息:
打印航班信息:
void printOneofAirMsg(int i) {printf("航班號 起點 終點 飛行日 起飛時間 到達時間 機型 價格 乘員定額 余票量\n");printf("%s %s %s %s %s %s %s %d %d %d\r\n", L.s[i].Airno, L.s[i].start, L.s[i].end, L.s[i].sche, L.s[i].time1, L.s[i].time2, L.s[i].mode, L.s[i].price, L.s[i].fixed, L.s[i].remained);}效果如下:
6.訂票功能(鏈表操作)
其實這一部分最終要的就是鏈表的操作,無非就是鏈表的創建,鏈表的增加,鏈表的刪除等問題。
所以首先需要熟悉的是鏈表
?
最近比較忙,先貼上代碼吧。
代碼鏈接:https://download.csdn.net/download/qq_36243942/10785641
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的C语言航空订票系统课程设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win32 段寄存器怎么寻址
- 下一篇: Win系统利用本地安全策略全面禁止360