程序設計要求用C語言寫一個簡單的火車售票系統,主要實現的功能為:
● 錄入班次信息
● 瀏覽班次信息
● 按班次號查詢
● 按終點站查詢
● 按餘票數量排序保存
● 售票
● 退票
● 更新班次信息
● 退出系統
所有的班次信息保存在number.dat文件中,排序過後的保存在sort.dat中(.dat是一種二進制文件)。
在編寫的過程中我覺得在判斷火車的狀態比較值得深究。這裡假設火車主要有四種狀態:
1、未發車
2、已發車
3、停止檢票
4、停止退票
在程序中,思路是將代表發車時間的字符串轉化為整型,再和系統現在的時間進行大小比較,主要採用if判斷各種情況。其中atime代表的是發車時間的整型數,btime代表的是系統時間的整型數,具體實現如下:
在判斷退票時如果兩個時間的小時數是一樣的,則它們的分鐘數如果相差在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++編程入門學習交流俱樂部(群),私信我【編程學習】進入,還有編程學習文件(源碼,零基礎教程,項目實戰教學視頻),歡迎初學者和正在進階中的小夥伴們!
閱讀更多 虎牙來了 的文章