火車票管理系統(tǒng)一、課題內(nèi)容和要求
改系統(tǒng)要求實(shí)現(xiàn)一個(gè)簡單、實(shí)用的火車票管理程序,主要功能包括火車票數(shù)據(jù)的錄入、查找、刪除、顯示、售票、退票等。所有火車票數(shù)據(jù)都要利用文件系統(tǒng)保存,以備系統(tǒng)下次運(yùn)行時(shí)使用。通過此課題,熟練掌握文件、數(shù)組、指針的各種操作,以及一些基本算法思想的應(yīng)用。
二、需求分析
功能框架圖:(見圖2-1)
火車票管理系統(tǒng)
錄入
查找
刪除
排序
售票
退票
保存
圖2-1。
1.新增火車票數(shù)據(jù)記錄:預(yù)先建立一個(gè)txt文檔,存入數(shù)據(jù),然后在程序中讀取文檔。
2.查找火車票數(shù)據(jù)(可按車次,發(fā)車時(shí)間、起點(diǎn)站、終點(diǎn)站等查找)。
3.刪除火車票數(shù)據(jù)記錄(先查找,再刪除。若查找出多條記錄,則進(jìn)一步提示用戶選擇記錄的車次,再刪除)。
4.對火車票排序(可按車次、發(fā)車時(shí)間、起點(diǎn)站、終點(diǎn)站等排序。)。
5.顯示當(dāng)前所有火車票信息列表。
6.售票(先查找,當(dāng)確定車次后,根據(jù)售票張數(shù)對該車次的已售票人數(shù)進(jìn)行修改)。
7.退票(售票的逆處理,過程與售票類似)。
8.保存火車票數(shù)據(jù)到文件中。
9.從文件中讀入火車票數(shù)據(jù)。
三、概要設(shè)計(jì)
1)主要結(jié)構(gòu)體:
struct
time
{
int
hour;
int
minutes;
};
struct
ticket
{
char
SerialNumber[10];
struct
time
SetOut;
char
DeparturePoint[MAX];
char
TerminalPoint[MAX];
float
LastTime;
int
FixNumber;
int
FixedNumber;
}train[N];
2)主要函數(shù)流程圖:
l
載入函數(shù):用于從文本中載入信息。(見圖3-1)
打開文本
能否打開
讀入數(shù)據(jù)
是否結(jié)束
結(jié)束
否
否
開始
開始
否
是
是
讀入車次
是否符合輸出信息
結(jié)束
是
圖3-2
圖3-1
l
查找函數(shù):利用輸入的車次或站點(diǎn)進(jìn)行順序查找并將找到的信息輸出。(見圖3-2)
l
刪除函數(shù):先查找出要?jiǎng)h除的信息再刪除。(見圖3-3)
否
否
是
無法訂票
人數(shù)加一
是否超載
否
圖3-4
結(jié)束
開始
讀入車次
是否誤點(diǎn)
否
圖3-3
是
是
否
是否符合讀入車次
開始
記錄下標(biāo)i
i=i+1,i++
i<車次總數(shù)-1
結(jié)束
l
售票退票函數(shù):先判斷該車是否已發(fā)車,若未發(fā)車且人未滿則訂票成功,否則無法訂票退票。(見圖3-4)
l
備份文件函數(shù):將文件內(nèi)容存儲(chǔ)到用戶給定的地址中(見圖3—5)
圖3-5
l
排序函數(shù)(見圖3-6)
圖3-6
四、源程序代碼
#include
#include
#include
#include
#include
#include
const
int
MAX=20;
const
int
N=50;
const
int
MAXFILENAME=100;
enum
{FALSE,TRUE};
struct
time
{
int
hour;
int
minutes;
};
struct
ticket
{
char
SerialNumber[10];
struct
time
SetOut;
char
DeparturePoint[MAX];
char
TerminalPoint[MAX];
float
LastTime;
int
FixNumber;
int
FixedNumber;
}train[N];
int
RecordNumber;
int
FLAG=FALSE;
/**********************************************/
int
ShowMessage(void);
//載入原始數(shù)據(jù)
void
mainmenu(void);
//主菜單
void
InsertMessage(void);
//錄入班次信息
void
SearchMenu(void);
//查詢路線子菜單
void
SearchByNumber(void);
//按班次號(hào)查詢
void
SearchByAddress(void);
//按終點(diǎn)站查詢
void
cancle(void);//刪除數(shù)據(jù)
void
selection(ticket
*pa,int
n);//排序
void
TicketManagement(void);
//車票售出與退回
void
TicketOrder(void);
//售票
void
TicketDelete(void);
//退票
void
exit(void);
//退出該系統(tǒng)
void
SaveRecord(ticket
x);
//儲(chǔ)存信息到文件中
/********************************************/
int
main(void)
{
do{
mainmenu();
}while(FLAG==FALSE);
return
0;
}
void
mainmenu(void)
{
system(“mode
con:
cols=140
lines=130“);
char
functionNumber;
printf(“
火車票管理系統(tǒng)\n\n“);
printf(“============================================================================\n“);
printf(“
1.錄入班次信息\t\n“);
printf(“
2.顯示所有車票信息列表\t\n“);
printf(“
3.查詢火車票數(shù)據(jù)\t\n“);
printf(“
4.刪除火車票數(shù)據(jù)記錄\t\n“);
printf(“
5.按行車時(shí)間排序\t\n“);
printf(“
6.售票與退票系統(tǒng)\t\n“);
printf(“
7.退出該系統(tǒng)\t\n“);
printf(“============================================================================\n“);
printf(“請選擇你所需要的功能:“);
scanf(“%c“,&functionNumber);
switch(functionNumber)
{
case
'1':
{
InsertMessage();
printf(“\n按任意鍵回主菜單......\n“);
getchar();
getchar();
}
break;
case
'2':
{
RecordNumber=ShowMessage();
printf(“\n按任意鍵回主菜單......\n“);
getchar();
getchar();
}
break;
case
'3':
{
SearchMenu();
printf(“\n按任意鍵回主菜單......\n“);
getchar();
getchar();
}
break;
case
'4':
{
cancle();
printf(“\n按任意鍵回主菜單......\n“);
getchar();
getchar();
}
break;
case
'5':
{
selection(train,RecordNumber);
printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“);
int
i;
for(i=0;i { printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } printf(“\n按任意鍵回主菜單......\n“); getchar(); getchar(); } break; case '6': { TicketManagement(); getchar(); getchar(); } break; case '7': { int i; FLAG=TRUE; for(i=0;i { SaveRecord(*(train+i)); } exit(); } break; default: { printf(“輸入錯(cuò)誤,請確保你的輸入為1--7.\n“); printf(“按任意鍵回主菜單......\n“); getchar(); getchar(); } }//switch ends FLAG=FALSE; } void InsertMessage(void) { FILE *fp; char filename[MAXFILENAME]; int i; printf(“請輸入文件名或者文件路徑名:“); scanf(“%s“,filename); if((fp=fopen(filename,“r“))==NULL) { printf(“文件%s不可讀,請確認(rèn)文件%s存在或者文件路徑正確.\n\n“,filename,filename); mainmenu(); } for(i=RecordNumber;!feof(fp)&&!ferror(fp);i++) { fscanf(fp,“%s%d%d“,&train[i].SerialNumber,&train[i].SetOut.hour,&train[i].SetOut.minutes); fscanf(fp,“%s%s%f%d%d“,&train[i].DeparturePoint,&train[i].TerminalPoint,&train[i].LastTime,&train[i].FixNumber,&train[i].FixedNumber); } RecordNumber=i; /*******************************輸出更新后的訂票記錄************************************************************/ printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); for(i=0;i { printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } fclose(fp); } int ShowMessage(void) { int i; FILE *fp; if((fp=fopen(“add.txt“,“r“))==NULL) { printf(“讀取數(shù)據(jù)失敗,請檢查文件add.txt是否存在.\n“); exit(-1); } for(i=RecordNumber;!feof(fp)&&!ferror(fp);i++) { fscanf(fp,“%s%d%d“,&train[i].SerialNumber,&train[i].SetOut.hour,&train[i].SetOut.minutes); fscanf(fp,“%s%s%f%d%d“,&train[i].DeparturePoint,&train[i].TerminalPoint,&train[i].LastTime,&train[i].FixNumber,&train[i].FixedNumber); } int count=i; printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); for(i=0;i { printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\t“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); printf(“\n“); } return count; } void SearchMenu(void) { system(“mode con: cols=140 lines=130“); char functionNumber; printf(“ 查詢子菜單\n“); printf(“============================================================================\n“); printf(“ 1.按班次號(hào)查詢\t\n“); printf(“ 2.按終點(diǎn)站查詢\t\n“); printf(“ 3.返回主菜單\t\n“); printf(“============================================================================\n“); printf(“請選擇你所需要的功能:“); scanf(“%*c%c“,&functionNumber); switch(functionNumber) { case '1':SearchByNumber();break; case '2':SearchByAddress();break; case '3': getchar(); mainmenu(); break; default: printf(“輸入錯(cuò)誤,請確保你的輸入為1--3.\n“); printf(“按任意鍵回查詢子菜單......\n“); getchar(); getchar(); SearchMenu(); } } void SearchByNumber(void) { int i; char Number[MAX]; printf(“請輸入班次號(hào):“); scanf(“%s“,&Number); printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); for(i=0;i { //對比終點(diǎn)站記錄,找到并輸出 if((strcmp(Number,train[i].SerialNumber))==0) { printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } } } void SearchByAddress(void) { int i; char Address[MAX]; printf(“請輸入終點(diǎn)站的名稱:“); scanf(“%s“,&Address); printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); for(i=0;i { //對比終點(diǎn)站記錄,找到并輸出 if((strcmp(Address,train[i].TerminalPoint))==0) { printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } } } void cancle(void) { SearchMenu(); int i,j; char m[MAX]; printf(“請輸入要?jiǎng)h除的班次:“); scanf(“%s“,&m); for(i=0;i { if(i==RecordNumber) { printf(“對不起,沒有這趟車\n“); } } for(j=i;j { train[j]=train[j+1]; } printf(“刪除成功\n“); } void selection(ticket *pa,int n) { int i,k,index; struct ticket temp; for(k=0;k { index=k; for(i=k+1;i if(pa[i].LastTime index=i; if(index!=k) { temp=pa[index]; pa[index]=pa[k]; pa[k]=temp; } } } void TicketManagement(void) { char functionNumber; system(“mode con: cols=140 lines=130“); printf(“ 訂票與退票菜單\n“); printf(“============================================================================\n“); printf(“ 1.訂票\t\n“); printf(“ 2.退票\t\n“); printf(“ 3.返回主菜單.\n“); printf(“============================================================================\n“); printf(“選擇你需要的功能:“); scanf(“%*c%c“,&functionNumber); switch(functionNumber) { case '1': { TicketOrder(); //getchar(); //getchar(); } break; case '2':TicketDelete();break; case '3': { getchar(); mainmenu(); } break; default: { printf(“輸入錯(cuò)誤,請確保你的輸入為1--3.\n“); printf(“按任意鍵回主菜單......\n“); getchar(); getchar(); mainmenu(); } } } void TicketOrder(void) { SearchMenu(); int i,j; char a[MAX]; printf(“請輸入要訂購的車票的班次:“); scanf(“%s“,&a); printf(“請輸入要訂購的車票的張數(shù):“); scanf(“%d“,&j); for(i=0;i { if((strcmp(a,train[i].SerialNumber))==0) { if(train[i].FixedNumber { (train[i].FixedNumber)+=j; printf(“你的訂票成功,請按時(shí)上車,謝謝使用!\n“); printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } else printf(“對不起,票已賣完\n“); } } } void TicketDelete(void) { SearchMenu(); int i,j; char b[MAX]; printf(“請輸入要退購的車票的班次:“); scanf(“%s“,&b); printf(“請輸入要退購的車票的張數(shù):“); scanf(“%d“,&j); for(i=0;i { if((strcmp(b,train[i].SerialNumber))==0) { if(train[i].FixedNumber>=1) { train[i].FixedNumber-=j; printf(“退訂車票成功,謝謝使用!\n“); printf(“班次\t發(fā)車時(shí)間\t起點(diǎn)\t終點(diǎn)\t行車時(shí)間(小時(shí))\t額定載量\t已定票人數(shù)\n“); printf(“%s\t%d:%d\t\t“,train[i].SerialNumber,train[i].SetOut.hour,train[i].SetOut.minutes); printf(“%s\t%s\t\t%.1f\t %d\t\t%d\n“,train[i].DeparturePoint,train[i].TerminalPoint,train[i].LastTime,train[i].FixNumber,train[i].FixedNumber); } else printf(“對不起,今天的這趟車的票尚未賣出,無法完成退票!\n“); } } } void exit(void) { printf(“\n\n*********************謝謝使用本系統(tǒng),歡迎下次繼續(xù)使用***********************\n“); exit(0); } void SaveRecord(ticket x) { FILE *fp; if((fp=fopen(“add.txt“,“a“))==NULL) { printf(“打開文件%s失?。躰“,“add.txt“); exit(-1); } fprintf(fp,“\n%s\t%d\t%d\t\t“,x.SerialNumber,x.SetOut.hour,x.SetOut.minutes); fprintf(fp,“%s\t%s\t\t%.1f\t %d\t\t%d“,x.DeparturePoint,x.TerminalPoint,x.LastTime,x.FixNumber,x.FixedNumber); } 五、測試數(shù)據(jù)及其結(jié)果分析 顯示的主菜單界面: 火車票管理系統(tǒng) ============================================================================ 1.錄入班次信息 2.顯示所有車票信息列表 3.查詢火車票數(shù)據(jù) 4.刪除火車票數(shù)據(jù)記錄 5.按行車時(shí)間排序 6.售票與退票系統(tǒng) 7.退出該系統(tǒng) ============================================================================ 請選擇你所需要的功能: 1)錄入班次信息 輸入:1 輸出:請輸入文件名或者文件路徑名: 輸入:D:\\1.txt 輸出: 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 200 k1234 10:20 上海 蘇州 2.0 200 t2222 12:40 長沙 上海 9.0 250 k2323 13:50 揚(yáng)州 南京 1.5 200 k1122 9:20 廣州 南京 20.0 300 170 按任意鍵回主菜單......2)顯示所有車票信息列表 輸入:2 輸出: 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 200 k1234 10:20 上海 蘇州 2.0 200 t2222 12:40 長沙 上海 9.0 250 k2323 13:50 揚(yáng)州 南京 1.5 200 k1122 9:20 廣州 南京 20.0 300 170 按任意鍵回主菜單......3)查詢火車票記錄 輸入:3 輸出: 查詢子菜單 ============================================================================ 1.按班次號(hào)查詢 2.按終點(diǎn)站查詢 3.返回主菜單 ============================================================================ 請選擇你所需要的功能: 輸入:1 輸出:請輸入班次號(hào): 輸入:k1111 輸出: 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 200 按任意鍵回主菜單......輸入:2 輸出:請輸入終點(diǎn)站的名稱: 輸入:上海 輸出: 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 200 t2222 12:40 長沙 上海 9.0 250 按任意鍵回主菜單......4)刪除火車票數(shù)據(jù) 輸入:4 輸出:查詢子菜單 ============================================================================ 1.按班次號(hào)查詢 2.按終點(diǎn)站查詢 3.返回主菜單 ============================================================================ 請選擇你所需要的功能: (查找過程同上) 輸出:請輸入要?jiǎng)h除的班次: 輸入:t2222 輸出:刪除成功 按任意鍵回主菜單......5)按行車時(shí)間排序: 輸入:5 輸出: 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k2323 13:50 揚(yáng)州 南京 1.5 200 k1234 10:20 上海 蘇州 2.0 200 k1111 8:30 南京 上海 4.0 300 200 t2222 12:40 長沙 上海 9.0 250 k1122 9:20 廣州 南京 20.0 300 170 按任意鍵回主菜單......6)售票 輸入:6 輸出: 訂票與退票菜單 =================================================== 1.訂票 2.退票 3.返回主菜單 ================================================== 選擇你需要的功能: 輸入:1 輸出: 查詢子菜單 ======================================================================== 1.按班次號(hào)查詢 2.按終點(diǎn)站查詢 3.返回主菜單 ========================================================================= 請選擇你所需要的功能: (查詢過程同上) 輸出:請輸入需要訂購的車票班次 輸入:k1111 輸出:請輸入要訂購的車票張數(shù) 輸入:10 輸出: 您的訂票成功,請按時(shí)上車,謝謝使用! 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 210 7)退票 輸入:6 輸出: 訂票與退票菜單 =================================================== 1.訂票 2.退票 3.返回主菜單 ================================================== 選擇你需要的功能: 輸入:2 輸出: 查詢子菜單 ======================================================================== 1.按班次號(hào)查詢 2.按終點(diǎn)站查詢 3.返回主菜單 ========================================================================= 請選擇你所需要的功能: (查詢過程同上) 輸出:請輸入需要退購的車票班次 輸入:k1111 輸出:請輸入要訂購的車票張數(shù) 輸入:5 退訂車票成功,謝謝使用! 班次 發(fā)車時(shí)間 起點(diǎn) 終點(diǎn) 行車時(shí)間(小時(shí)) 額定載量 已定票人數(shù) k1111 8:30 南京 上海 4.0 300 195 8)退出 輸入:7 輸出:****************謝謝使用本系統(tǒng),歡迎下次繼續(xù)使用**************** 結(jié)果分析:(1).若輸入數(shù)字不在1——7之間,則會(huì)提示錯(cuò)誤。 (2).當(dāng)輸入列車班次信息不正確時(shí),將不會(huì)得到結(jié)果。 (3).文件錄入不正確時(shí),將不會(huì)得到任何結(jié)果。 六、調(diào)試過程中的問題 1)文件存儲(chǔ)方式不正確:應(yīng)先定義一個(gè)文件存儲(chǔ)函數(shù),在其它函數(shù)中調(diào)用,方便有效。 2)刪除時(shí)若遇到?jīng)]有的班次則程序出錯(cuò)。應(yīng)在不存在輸入的列車班次時(shí),輸出不存在的提示 3)保存后在下次運(yùn)行時(shí)出錯(cuò)問題:在保存信息時(shí),應(yīng)在每個(gè)信息之間加一空格來保存,否則在文件下次使用時(shí)讀取就會(huì)沒有分界點(diǎn)。 4)訂票退票只能一次一張。應(yīng)在用戶輸入列車班次后讓用戶輸入需要訂購的張數(shù)。 5)結(jié)構(gòu)指針定義錯(cuò)誤,ticket前不應(yīng)加struct。