C語言,實現12306火車售票系統!附源碼,項目實戰!

程序設計要求用C語言寫一個簡單的火車售票系統,主要實現的功能為:

● 錄入班次信息

● 瀏覽班次信息

● 按班次號查詢

● 按終點站查詢

● 按餘票數量排序保存

● 售票

● 退票

● 更新班次信息

● 退出系統

所有的班次信息保存在number.dat文件中,排序過後的保存在sort.dat中(.dat是一種二進制文件)。

在編寫的過程中我覺得在判斷火車的狀態比較值得深究。這裡假設火車主要有四種狀態:

1、未發車

2、已發車

3、停止檢票

4、停止退票

在程序中,思路是將代表發車時間的字符串轉化為整型,再和系統現在的時間進行大小比較,主要採用if判斷各種情況。其中atime代表的是發車時間的整型數,btime代表的是系統時間的整型數,具體實現如下:

C語言,實現12306火車售票系統!附源碼,項目實戰!

編程學習交流圈:【1/0/8/2/6/7/1/4/6/4】Q

在判斷退票時如果兩個時間的小時數是一樣的,則它們的分鐘數如果相差在30之內即半小時之內或者發車時間的小時和系統時間的小時相差一個1,並且發車時間的分鐘數小於30,系統時間的分鐘大於30,則它們之間也就相差在30之內,此時代表停止退票。

判斷檢票和上面思想大致相同。


為了參考研究,貼上代碼:

<code>#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

#include<string.h>

#include "time.h"

//班次信息表

#define SIZELIMIT 10 //每班次的具體信息的字符個數限制在10以內

#define MAXNUM 1000 //設定最多隻能錄入1000個車次信息

typedef struct cardbase //定義一個關於班次信息的結構體,取名為CardBase


{

char C_ID[SIZELIMIT];//班次

char C_TIME[SIZELIMIT];//發車時間

char C_ANAME[SIZELIMIT];//起點站

char C_BNAME[SIZELIMIT];//終點站

char C_USETIME[SIZELIMIT];//行車時間

char C_MAXNUM[SIZELIMIT];//額定載量

char C_REMAINNUM[SIZELIMIT];//餘票數量

}CardBase;

int cbNum=0;//記錄班次數

CardBase cBList[MAXNUM];//班次列表

//讀取班次信息

void readcardbasefile()

{

FILE *fp;

//打開文件失敗則創建文件

if((fp=fopen("./number.dat","r"))==NULL)

{

//初次運行創建文件

if ((fp=fopen("./number.dat","w"))==NULL)

{

exit(0); //返回


}

else

{

fclose(fp);

}

return ;

}

/*文件位置指針移動到文件末尾*/

fseek(fp,0,2);//重定位文件內部位置指針

/* int fseek( FILE *stream, long offset, int origin );

第一個參數stream為文件指針

第二個參數offset為偏移量,正數表示正向偏移,負數表示負向偏移

第三個參數origin設定從文件的哪裡開始偏移,可能取值為:SEEK_CUR、 SEEK_END 或 SEEK_SET

SEEK_SET: 文件開頭

SEEK_CUR: 當前位置

SEEK_END: 文件結尾

其中SEEK_SET,SEEK_CUR和SEEK_END依次為0,1和2.

簡言之:

fseek(fp,100L,0);把stream指針移動到離文件開頭100字節處;


fseek(fp,100L,1);把stream指針移動到離文件當前位置100字節處;

fseek(fp,-100L,2);把stream指針退回到離文件結尾100字節處。 */

if (ftell(fp)>0)//文件不為空

/*ftell函數用於得到文件位置指針當前位置相對於文件首的偏移字節數

也就是得到文件所包含的字節數,如果大於0,則代表文件非空*/

{

//文件位置指針移動到文件開始

rewind(fp);

char buff[10]={0};

for (cbNum=0;!feof(fp) && fread(&cBList[cbNum],sizeof(CardBase),1,fp);cbNum++)

/*對於feof函數,如果遇到文件結束,函數feof(fp)的值為非零值,否則為0。

即如果文件結束,!feof(fp)為0,跳出循環

對於fread函數,是從一個文件流中讀數據,如果調用成功返回實際讀取到的項個數,

如果不成功或讀到文件末尾返回 0*/

fgets(buff,10,fp);

/*char *fgets(char *buf, int bufsize, FILE *stream);

從文件結構體指針stream中讀取數據,每次讀取一行。讀取的數據保存在buf指向的字符數組中,

每次最多讀取bufsize-1個字符(第bufsize個字符賦'\\0'),如果文件中的該行,不足bufsize個字符,

則讀完該行就結束。如若該行(包括最後一個換行符)的字符數超過bufsize-1,則fgets只返回一個不完整的行,

但是,緩衝區總是以NULL字符結尾,對fgets的下一次調用會繼續讀該行。函數成功將返回buf,失敗或讀到文件結尾返回NULL。

因此我們不能直接通過fgets的返回值來判斷函數是否是出錯而終止的,應該藉助feof函數或者ferror函數來判斷。

*/

fclose(fp);

}

else

{

fclose(fp);

}

return;

}

//保存班次信息

void writecardbasefile()

{

int i;

FILE *fp;

if ((fp=fopen("./number.dat","w"))==NULL)

{

printf("系統錯誤");

}

char buff[10]={0};

strcpy(buff,"\\r\\n");

for (i=0;i<cbnum>
{

if (fwrite(&cBList[i],sizeof(CardBase),1,fp)!=1)

{

printf("系統錯誤");

}

if (fwrite(buff,2,1,fp)!=1)

{

printf("系統錯誤");

}

}

fclose(fp);

}

//保存排序信息


void writesortfile()

{

int i;

FILE *fp;

if ((fp=fopen("./sort.dat","w"))==NULL)

{

printf("系統錯誤");

}

char buff[10]={0};

strcpy(buff,"\\r\\n");

for (i=0;i<cbnum>
{

if (fwrite(&cBList[i],sizeof(CardBase),1,fp)!=1)

{

printf("系統錯誤");

}

if (fwrite(buff,2,1,fp)!=1)

{

printf("系統錯誤");

}

}

fclose(fp);

}

//打印並輸入後返回

void printReturn(char *info)

{

printf("\\n\\n\\t %s",info);

fflush(stdin);//清空輸入緩衝區,通常是為了確保不影響後面的數據讀取.

getchar();

}

//輸入信息

void setInfo(char pinfo[1024],char desinfo[])

{

printf("\\n\\t%s:",pinfo);

fflush(stdin);

scanf("%s",desinfo);

}

//系統初始化

void initsystem()

{

readcardbasefile();

};

//錄入班次

void infoinput()

{

setInfo("班次",cBList[cbNum].C_ID);

setInfo("發車時間(24小時制)",cBList[cbNum].C_TIME);

setInfo("起點站",cBList[cbNum].C_ANAME);

setInfo("終點站",cBList[cbNum].C_BNAME);

setInfo("行車時間",cBList[cbNum].C_USETIME);

setInfo("額定載量",cBList[cbNum].C_MAXNUM);

setInfo("餘票數量",cBList[cbNum].C_REMAINNUM);

cbNum++;

writecardbasefile();

printReturn("\\n\\t錄入成功,回車鍵返回");

};

//時間比較

int timecmp(char A[10])

{

//將火車時間轉成整數

char tempa[10]={0};

int ta=0;

int i;

for(i=0;i<strlen>
if(A[i]!=':'&&A[i]!=':') //冒號的中文輸入和英文輸入

{

tempa[ta]=A[i];

ta++;

}

int atime=atoi(tempa);//把字符串變成整型


//獲取系統時間

char tempb[10]={0};

time_t t = time(0);

strftime( tempb, 10, "%H%M",localtime(&t) );

int btime=atoi(tempb);

//比較

if(atime<=btime) //已經發車

return 1;

if(((atime-btime<=30)&&(atime-btime>5)&&(atime/100==btime/100))||(((atime%100+(60-btime%100))<=30)&&(atime%100+(60-btime%100))>5&&(atime/100-btime/100==1))) //距發車半小時以內,停止退票,%表示取餘

return 2;

if(((atime-btime<=5)&&(atime/100==btime/100))||((atime%100+(60-btime%100)&&(atime/100-btime/100==1))<=5)) //距發車前五分鐘內停止檢票

return 3;

return 0; //可以辦理購退票

}

//瀏覽所有班次

void queryallinfo()

{

printf("班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量 狀態\\n");

int i;

for(i=0;i<cbnum>

{

char temp[20]={0};

strcpy(temp,"未發車");

if(1==timecmp(cBList[i].C_TIME))

strcpy(temp,"已發車");

if(2==timecmp(cBList[i].C_TIME))

strcpy(temp,"停止退票");

if(3==timecmp(cBList[i].C_TIME))

strcpy(temp,"停止檢票");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s%s\\n",

cBList[i].C_ID,cBList[i].C_TIME,

cBList[i].C_ANAME,cBList[i].C_BNAME,cBList[i].C_USETIME,

cBList[i].C_MAXNUM,cBList[i].C_REMAINNUM,temp );

}

printReturn("\\n\\t回車鍵返回");

};

//通過班次號查路線

void queryinfobyID()

{

char ID[20]={0};

setInfo("輸入班次號",ID);

int i;

for( i=0;i<cbnum>
{

if(strcmp(cBList[i].C_ID,ID)==0)

{

printf("班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量\\n");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s\\n",

cBList[i].C_ID,cBList[i].C_TIME,

cBList[i].C_ANAME,cBList[i].C_BNAME,cBList[i].C_USETIME,

cBList[i].C_MAXNUM,cBList[i].C_REMAINNUM );

printReturn("\\n\\t回車鍵返回");

return;

}

}

printReturn("\\n\\t指定信息不存在,回車鍵返回");

};

//通過終點站查路線

void queryinfobyBNAME()

{

char Name[20]={0};

setInfo("輸入終點站",Name);

int i;

for(i=0;i<cbnum>
{

if(strcmp(cBList[i].C_BNAME,Name)==0)

{

printf("班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量\\n");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s\\n",

cBList[i].C_ID,cBList[i].C_TIME,

cBList[i].C_ANAME,cBList[i].C_BNAME,cBList[i].C_USETIME,

cBList[i].C_MAXNUM,cBList[i].C_REMAINNUM );

printReturn("\\n\\t回車鍵返回");

return;

}

}

printReturn("\\n\\t指定信息不存在,回車鍵返回");

};

//排序按餘票數量排序保存

void sortSave()

{

//冒泡排序

int i,j;

for(i=0;i<cbnum>
for(j=0;j<cbnum-i-1>
{

if(atoi(cBList[j].C_REMAINNUM)<atoi>
{

CardBase temp=cBList[j];


cBList[j]=cBList[j+1];

cBList[j+1]=temp;

}

}

//打印排序結果

queryallinfo();

//保存排序結果

writesortfile();

};

//售票

void sale()

{

char ID[20]={0};

setInfo("輸入班次號",ID);

int i;

for(i=0;i<cbnum>
{

if(strcmp(cBList[i].C_ID,ID)==0)

{

if(cBList[i].C_REMAINNUM==0)

{

printReturn("\\n\\t餘票不足,回車返回");

return;

}

//餘票減少

int temp=atoi(cBList[i].C_REMAINNUM)-1;

if(temp<0) temp=0;//確保餘票不為負數

_itoa(temp,cBList[i].C_REMAINNUM,10);

//保存到文件

writecardbasefile();

printf("班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量\\n");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s\\n",

cBList[i].C_ID,cBList[i].C_TIME,

cBList[i].C_ANAME,cBList[i].C_BNAME,cBList[i].C_USETIME,

cBList[i].C_MAXNUM,cBList[i].C_REMAINNUM );

printReturn("\\n\\t售票成功,回車返回");

return;

}

}

printReturn("\\n\\t指定班次不存在,回車鍵返回");

};

//退票

void back()

{

char ID[20]={0};

setInfo("輸入班次號",ID);

int i;

for(i=0;i<cbnum>
{

if(strcmp(cBList[i].C_ID,ID)==0)

{

//餘票增加

int temp=atoi(cBList[i].C_REMAINNUM)+1;

_itoa(temp,cBList[i].C_REMAINNUM,10);

//保存到文件

writecardbasefile();

printf("班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量\\n");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s\\n",

cBList[i].C_ID,cBList[i].C_TIME,

cBList[i].C_ANAME,cBList[i].C_BNAME,cBList[i].C_USETIME,

cBList[i].C_MAXNUM,cBList[i].C_REMAINNUM );

printReturn("\\n\\t\\t退票成功,回車返回");

return;

}

}

printReturn("\\n\\t指定班次不存在,回車鍵返回");

};


//更新車次信息

void update()

{

int flag;

char ID[20]={0};

setInfo("請輸入要刪除或修改的車次(請確認車次輸入正確)",ID);

do

{

printf("\\n\\t按下列提示更新車次信息(退出修改請按0):");

printf("\\n\\t1:刪除車次;2:修改發車時間;3:修改起點站;4:修改終點站;");

printf("\\n\\t5:修改行車時間;6:修改額定載量;7:修改餘票數量;0:退出修改;");

printf("\\n\\t請選擇:");

scanf("%d",&flag);

int i;

CardBase temp;

for(i=0;i<cbnum>
{

if(strcmp(cBList[i].C_ID,ID)==0)

{

if(flag==1) //刪除車次信息

{

int j;

for(j=i;j<cbnum>
cBList[j]=cBList[j+1];//後面的數據覆蓋前面的數據

cbNum--;//車次數減一

//保存到文件

writecardbasefile();

}

if(flag==2) //修改發車時間

{

setInfo("請輸入新的發車時間",cBList[i].C_TIME);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

if(flag==3) //修改起點站

{

setInfo("請輸入新的起點站",cBList[i].C_ANAME);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

if(flag==4) //修改終點站


{

setInfo("請輸入新的終點站",cBList[i].C_BNAME);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

if(flag==5) //修改行車時間

{

setInfo("請輸入新的行車時間",cBList[i].C_USETIME);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

if(flag==6) //修改額定載量

{

setInfo("請輸入新的額定載量",cBList[i].C_MAXNUM);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

if(flag==7) //修改餘票數量

{

setInfo("請輸入新的餘票數量",cBList[i].C_REMAINNUM);

temp=cBList[i];

//保存到文件

writecardbasefile();

}

}

}

//更改完成後顯示更新後的班次信息,如果是刪除車次則不顯示,即flag不等於0的時候顯示更新信息

if(flag!=1&&flag!=0)

{ printf("更新後的班次信息\\n");

printf("班次 發車時間 起點站 終點站 行車時間 額定載量 餘票數量\\n");

printf("%-010s%-010s%-010s%-010s%-010s%-010s%-010s\\n",

temp.C_ID,temp.C_TIME,

temp.C_ANAME,temp.C_BNAME,temp.C_USETIME,

temp.C_MAXNUM,temp.C_REMAINNUM );

}

}while(flag);

printReturn("\\n\\t完成車次信息更新,回車鍵返回");

};

void mainmenu()

{


while(1)

{

char select;

do{

system("cls");//清屏

printf("\\n\\t ╭═════════■□■□═══╮");

printf("\\n\\t│ 火車班次系統 │");

printf("\\n\\t╰═══■□■□══════════╯");

printf("\\n\\t ┌────────────────┐");

printf("\\n\\t │1.錄入班次 │");

printf("\\n\\t │2.瀏覽所有班次 │");

printf("\\n\\t │3.通過班次號查路線 │");

printf("\\n\\t │4.通過終點站查路線 │");

printf("\\n\\t │5.排序保存 │");

printf("\\n\\t │6.售票 │");

printf("\\n\\t │7.退票 │");

printf("\\n\\t │8.更新車次信息 │");

printf("\\n\\t │0.退出登錄 │");

printf("\\n\\t └────────────────┘");

printf("\\n\\t 請選擇:");

fflush(stdin);//清空輸入緩衝區,通常是為了確保不影響後面的數據讀取.


select=getchar();//等待用戶輸入數據

}while (select'8');

switch(select)

{

case '0':exit(0);break;

case '1':infoinput();break;

case '2':queryallinfo();break;

case '3':queryinfobyID();break;

case '4':queryinfobyBNAME();break;

case '5':sortSave();break;

case '6':sale();break;

case '7':back();break;

case '8':update();break;

}

}

}

//主函數

int main()

{

initsystem(); //系統初始化

while(1)

{

mainmenu();

}

}/<cbnum>/<cbnum>/<cbnum>/<cbnum>/<atoi>/<cbnum-i-1>/<cbnum>/<cbnum>/<cbnum>/<cbnum>/<strlen>/<cbnum>/<cbnum>/<string.h>/<conio.h>/<stdlib.h>/<stdio.h>/<code>

——END——

對於熱愛編程的人來說,有一群一起學習一起解答的小夥伴很重要!筆者有一個C語言/C++編程入門學習交流俱樂部(群),私信我【編程學習】進入,還有編程學習文件(源碼,零基礎教程,項目實戰教學視頻),歡迎初學者和正在進階中的小夥伴們!


分享到:


相關文章: