1. 程式人生 > >火車訂票系統學習筆記

火車訂票系統學習筆記

/*
系統名稱:火車訂票系統
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;
}