C Primer Plus 第十四章 编程练习8

 应用     |      2020-03-18 17:09
/*
巨人航空公司的机群由座位容量为12的飞机组成.
它每天飞行一个航班.
按照下面的功能,写一个座位预订程序:
A. 程序使用一个含12个结构的数组.
    每个结构要包括一个用于标识座位的编号,一个表示座位是否分配出去的标记
    座位预订人的姓和名
B. 程序显示下面的菜单:
    To choose a function, enter its letter label:
    a) Show number of empty seats
    b) Show list of empty seats
    c) Show alphabetical list of seats
    d) Assign a customer to a seat assignment
    e) Delete a seat assignment
    f) Quit

C. 程序应能执行菜单所给出的功能.选择 d) 和 e) 需要额外的输入,
    每一个选项都应当允许用户终止输入.
D. 当执行完一个特定的功能之后,程序再次显示菜单,除非选择了 f
E. 每次运行程序都把数据保存到一个文件中,当程序再次运行时,首先从文件中载入数据(如果有的话) 
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NAMELEN 10
#define SIZE 12

struct order{
    unsigned short number;
    unsigned short flag;
    char fname[NAMELEN];
    char lname[NAMELEN];
};

void clearcache(void);                  /*清空缓存*/
void showmenu(void);
void showEmptyNumber(struct order *);   /*显示空座位号码*/
void showEmptyList(struct order *);     /*显示空座位列表*/
void showAlphaList(struct order *);     /*显示按字母顺序排列的座位列表*/
void addSeat(struct order *);           /*添加一个订单*/
void delSeat(struct order *);           /*删除一个订单*/
struct order readfile(struct order *);

int main(void)
{
    struct order seat[SIZE] = {0};
    FILE * fp;
    char ch;
    int err;
    int i, count = 0;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "rb")) == NULL)     /*如果文件不存在*/
    {
        if((fp = fopen("order.dat", "w+b")) == NULL)    /*创建文件失败*/
        {
            fprintf(stderr, "Can't create order.dat file.n");
            exit(1);
        }
        for(i = 0; i < SIZE; i++)
        {
            seat[i].number = i + 1;
            fwrite(&seat[i], size, 1, fp);
        }
    }
    //while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    //  count++;
    fclose(fp);

    showmenu();
    printf("Please select an operation: ");

    while((ch = getchar()) != 'f')
    {
        err = 0;
        clearcache();   /*清空缓存中的字符*/

        switch(ch){
            case 'a':showEmptyNumber(seat);break;
            case 'b':showEmptyList(seat);break;
            case 'c':showAlphaList(seat);break;
            case 'd':addSeat(seat);break;
            case 'e':delSeat(seat);break;
            default:err = 1;break;
        }
        if(err)
        {
            fprintf(stderr, "Invalid option.n");
            printf("Try again: ");
            continue;
        }
        showmenu();
        printf("Please select again: ");

    }

    printf("Bye.n");
    return 0;
}

void showEmptyNumber(struct order * seat)   /*显示空座位号码*/
{
    int i, num = 0, count = 0;
    FILE * fp;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "rb")) == NULL)     /*读取文件失败*/
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(1);

    }
    while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    {
        if(seat[count].flag != 0)
            num++;
        count++;
    }
    fclose(fp);

    if(num == SIZE)
    {
        fprintf(stderr, "nNo empty seat.nn");
        return;
    }

    printf("The empty seat number:n");
    for(i = 0; i < SIZE; i++)
        if(seat[i].flag == 0)
            printf("%6d", seat[i].number);
    printf("nn");
}

void showEmptyList(struct order * seat)     /*显示空座位列表*/
{
    int i, num = 0, count = 0;
    FILE * fp;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "rb")) == NULL)     /*读取文件失败*/
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(1);

    }
    while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    {
        if(seat[count].flag != 0)
            num++;
        count++;
    }

    fclose(fp);
    if(num == SIZE)
    {
        fprintf(stderr, "nNo empty seat.nn");
        return;
    }

    printf("The empty seat list:n");
    printf("Number   FirstName   Lastnamen");
    for(i = 0; i < SIZE; i++)
        if(seat[i].flag == 0)
            printf("%3dn", seat[i].number);
    printf("nn");

}
void showAlphaList(struct order * seat)
{
    struct order *pst[SIZE];        /*结构指针数组*/
    struct order *tmp;
    int i, j, num = 0, count = 0;
    FILE * fp;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "rb")) == NULL)     /*读取文件失败*/
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(1);

    }
    while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    {
        if(seat[count].flag != 0)
            num++;
        count++;
    }

    fclose(fp);

    if(num == 0)
    {
        fprintf(stderr, "nNo order record.nn");
        return;
    }

    for(i = 0; i < SIZE; i++)        /*为结构数组每个元素分配一个结构指针*/
        pst[i] = &seat[i];

    for(i = 0; i < SIZE - 1; i++)
        for(j = i + 1; j < SIZE; j++)
        {
            if(strcmp(pst[i]->fname,pst[j]->fname) > 0) /*比较 FIRSTNAME*/
            {
                tmp = pst[i];
                pst[i] = pst[j];
                pst[j] = tmp;
            }
            else if(strcmp(pst[i]->fname,pst[j]->fname) == 0) /*如果FNAME相同,比较LNAME*/
            {
                if(strcmp(pst[i]->lname,pst[j]->lname) > 0)
                {
                    tmp = pst[i];
                    pst[i] = pst[j];
                    pst[j] = tmp;
                }
            }
        }

    printf("The alphabetical list of seats:n");
    printf("  FirstName      Lastname     Numbern");
    for(i = 0; i < SIZE; i++)
        if(pst[i]->flag != 0)
            printf("%10s     %10s       %3dn", pst[i]->fname, pst[i]->lname, pst[i]->number);
    printf("nn");


}
void addSeat(struct order * seat)
{
    int i, count = 0, num = 0;
    int sum;
    FILE * fp;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "r+b")) == NULL)
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(2);
    }
    while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    {
        if(seat[count].flag != 0)
            num++;
        count++;
    }
    fclose(fp);

    if(num == SIZE)
    {
        fprintf(stderr, "nFull of orders.nn");
        return;
    }


    printf("The empty seat number:n");             /*显示空座位列表*/
    for(i = 0; i < SIZE; i++)
        if(seat[i].flag == 0)
            printf("%6d", seat[i].number);
    printf("nn");

    printf("Please enter seat number(q to quit): ");
    while(scanf("%d", &sum) == 1)
    {
        clearcache();
        sum--;

        if(sum >= 0 && sum <= 11)                     /*判断输入的数字*/
        {
            if(seat[sum].flag == 1)                 /*判断是否是空座位*/
            {
                fprintf(stderr, "The seats have been booked.n");
                printf("Please enter seat number again(q to quit): ");
                continue;
            }

            seat[sum].flag = 1;                     /*设定标记*/
            //seat[num].number = num;                   /*接受输入信息,存入结构体*/
            printf("Enter the first name: n");
            gets(seat[sum].fname);
            printf("Enter the last name: n");
            gets(seat[sum].lname);

            //fwrite(&seat[sum], size, 1, fp);      /*将一条订单信息写入文件*/
            printf("Please enter seat number(q to quit): ");
        }
        else
        {
            fprintf(stderr, "Invalid number.n");
            printf("Please enter seat number again(q to quit): ");
                continue;
        }
    }
    if((fp = fopen("order.dat", "w+b")) == NULL)
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(2);
    }
    for(i = 0; i < SIZE; i++)
        fwrite(&seat[i], size, 1, fp);

    clearcache();
    fclose(fp);
}

void delSeat(struct order * seat)           /*删除订单*/
{
    int i, count = 0, num = 0;
    int sum;
    char null[1] = "";
    FILE * fp;
    int size = sizeof(struct order);

    if((fp = fopen("order.dat", "r+b")) == NULL)
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(2);
    }
    while(count < SIZE && fread(&seat[count], size, 1, fp) == 1)
    {
        if(seat[count].flag != 0)
            num++;
        count++;
    }
    fclose(fp);

    if(num == SIZE)
    {
        fprintf(stderr, "nFull of orders.nn");
        return;
    }


    printf("The seat order list:n");               /*显示订单列表*/
    printf("Number     FirstName     Lastnamen");
    for(i = 0; i < SIZE; i++)
        if(seat[i].flag != 0)
            printf("%3d     %10s     %10sn", seat[i].number, seat[i].fname, seat[i].lname);
    printf("nn");

    printf("Please enter seat number(q to quit): ");
    while(scanf("%d", &sum) == 1)
    {
        clearcache();
        sum--;

        if(sum >= 0 && sum <= 11)                     /*判断输入的数字*/
        {
            if(seat[sum].flag != 1)                 /*判断是否是空座位*/
            {
                fprintf(stderr, "The seats have no booked.n");
                printf("Please try again(q to quit): ");
                continue;
            }

            seat[sum].flag = 0;                     /*设定标记*/
            //strcpy(seat[sum].fname, null);
            //strcpy(seat[sum].lname, null);

            printf("Deleted Order No.%d .n");
            printf("enter next seat number(q to quit): ");
        }
        else
        {
            fprintf(stderr, "Invalid number.n");
            printf("Try again(q to quit): ");
                continue;
        }
    }
    if((fp = fopen("order.dat", "w+b")) == NULL)
    {
        fprintf(stderr, "Can't open order.dat file.n");
        exit(2);
    }
    for(i = 0; i < SIZE; i++)
        fwrite(&seat[i], size, 1, fp);

    clearcache();
    fclose(fp);
}

void showmenu(void)
{
    puts("To choose a function, enter its letter label:");  
    puts("a) Show number of empty seats");                      /*显示空座位号码*/
    puts("b) Show list of empty seats");                        /*显示空座位列表*/
    puts("c) Show alphabetical list of seats");                 /*显示按字母顺序排列的座位列表*/
    puts("d) Assign a customer to a seat assignment");          /*添加一个订单*/
    puts("e) Delete a seat assignment");                        /*删除一个订单*/
    puts("f) Quit");

}

void clearcache(void)
{
    while(getchar() != 'n')
        continue;
}