C primer plus(第五版)编程练习第十四章

第一题:重做复习题3但用月份名的拼写代替月份号(别忘了可以使用strcmp())。
解:可能是印刷错误,应该是重做复习题5
代码如下:
#include
#include
typedef struct month {
    char name[10];
    char na[3];
    int days;
    int monumb;
} MONTH;
int countdays(MONTH mon[],char m);
int main(void)
{
    MONTH mon[12] = {
    {"January","jan",31,1},
    {"Febyuary","feb",28,2},
    {"March","mar",31,3},
    {"April","apr",30,4},
    {"May","may",31,5},
    {"June","jun",30,6},
    {"July","jul",31,7},
    {"August","agu",31,8},
    {"September","sep",30,9},
    {"October","oct",31,10},
    {"November","nov",30,11},
    {"December","dec",31,12},
};
    char line[10];
    int i;
    int find = 0;
    int m;

    while(gets(line) != NULL && line[0] != '\0')
    {
        for(i = 0;i < 12;i++)
            if(strcmp(mon[i].name,line) == 0)
            {
                find = 1;
                break;
            }
        if(find)
        {
            m = mon[i].monumb;
            break;
        }
        else
            puts("wrong input,try again");    
    }
    printf("%d days\n",countdays(mon,m));
    return 0;
}
int countdays(MONTH mon[],char m)
{
    int tdays = 0;
    int i;
  
    for(i = 0;i < m;i++)
        tdays +=mon[i].days;
    return tdays;
}
———————————————分割线—————————————————
第二题:编写一个程序。请求用户键入日、月、年。月份可以是月份号、月份名或月份缩写。然后程序返回一年中到给定日志包括这一天的总天数。
解:
代码如下:
#include
#include
#include
union month_n {
    int m_n;
    char m_c[10];
    char m_s[3];
};
struct input {
    int day_n;
    union month_n mon_n;
    int year_n;
};
struct months {
    char name[10];
    char na[3];
    int day;
    int mon_n;
};
int main(void)
{
    struct months mons[12] = {
    {"January","jan",31,1},
    {"Febyuary","feb",28,2},
    {"March","mar",31,3},
    {"April","apr",30,4},
    {"May","may",31,5},
    {"June","jun",30,6},
    {"July","jul",31,7},
    {"August","agu",31,8},
    {"September","sep",30,9},
    {"October","oct",31,10},
    {"November","nov",30,11},
    {"December","dec",31,12}
    };
    struct input in;
    int i;
    int tdays = 0;
    char line[10];

    puts("Input the day:");
    scanf("%d",&in.day_n);
    while(getchar() != '\n');
    puts("Input the month:");
    if(scanf("%d",&in.mon_n.m_n))
    {
        if(!(in.mon_n.m_n > 0 && in.mon_n.m_n < 13))
        {
            puts("out of range!");
            exit(1);
        }
    }
    else 
    {
        scanf("%s",line);
        if(strlen(line) > 3)
        {
            strcpy(in.mon_n.m_c,line);
            for(i = 0;i < 12;i++)
            {
                if(strcmp(mons[i].name,in.mon_n.m_c) == 0)
                {
                    in.mon_n.m_n = i + 1;
                    break;
                }
            }
        }
        else if(strlen(line) == 3)
        {
            strcpy(in.mon_n.m_s,line);
            for(i = 0;i < 12;i++)
           {
                if(strcmp(mons[i].na,in.mon_n.m_s) == 0)
                {
                    in.mon_n.m_n = i + 1;
                    break;
                }
            }
        }
    }
    puts("Input the year:");
    scanf("%d",&in.year_n);
    
    for(i = 0;i < in.mon_n.m_n - 1;i++)
        tdays += mons[i].day;
    tdays += in.day_n;
    if(in.mon_n.m_n > 2 && in.year_n % 4 == 0)
        tdays++;
    printf("total %d days\n",tdays);
    return 0;
}
———————————————分割线—————————————————
第三题:修改程序清单14.2中的书目列表程序,使它首先按照输入的顺序输出图书的描述,然后按照标题的字母升序输出图书的描述,最后按照value值的升序输出图书的描述。
解:
代码如下:
#include
#include
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100
struct book {
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
int main(void)
{
    struct book library[MAXBKS];
    int count = 0;
    int index;

    printf("Please enter the book title.\n");
    printf("Press [enter] at the start of a line to stop.\n");
    while(count < MAXBKS && gets(library[count].title) != NULL && library[count].title[0] != '\0')
    {
        printf("Now enter the author.\n");
        gets(library[count].author);
        printf("Now enter the value.\n");
        scanf("%f",&library[count++].value);
        while(getchar() != '\n');
        if(count < MAXBKS)
            printf("Enter the next title.\n");
    }
    if(count > 0)
    {
        printf("Here is the list of your books:\n");
        for(index = 0;index < count;index++)
            printf("%s by %s:$%.2f\n",library[index].title,library[index].author,library[index].value);
        puts("");
        if(count == 1)
            printf("%s by %s:$%.2f\n",library[0].title,library[0].author,library[0].value);
        char * ptr[MAXTITL];
        char lib[count][MAXTITL];
        char * temp;
        int j;
        for(index = 0;index < count;index++)
        {
            strcpy(lib[index],library[index].title);
            ptr[index] = lib[index];
        }
        for(index = 0;index < count - 1;index++)
            for(j = index + 1;j < count;j++)
                if(strcmp(ptr[index],ptr[j]) > 0)
                {
                    temp = ptr[index];
                    ptr[index] = ptr[j];
                    ptr[j] = temp;
                }
        if(count > 1)
            for(index = 0;index < count;index++)
                for(j = 0;j < count;j++)
                    if(strcmp(ptr[index],library[j].title) == 0)
                        printf("%s by %s:$%.2f\n",library[j].title,library[j].author,library[j].value);
    }
    else
        printf("No books?Too bad.\n");
    return 0;
}
———————————————分割线—————————————————
第四题:编写一个程序。按照下列要求,创建一个含有两个成员的结构模板:
a.第一个成员是社会保障号;第二个成员是一个含三个成员的结构。它的第一个成员是名,第二个成员是名和姓中间的名字,最后一个成员是姓。创建并初始化一个含有5个此类结构的数组。程序以下列行书输出数据:
    Dribble,Flossie M. - 302039823
名和姓中间的名字只输出了它的第一个字母,后面加了一个据点。如果姓名中间的名字为空,那么它的第一个字母和据点都不会输出。写一个函数来实现输出,把结构数组传递给这个函数
b.修改a部分,传递结构的值而不是结构地址。
解:
代码如下:
//a
#include
#include
#define LEN1 5
#define LEN2 20
#define LEN3 10
struct fullname {
    char lastname[LEN2];
    char middlename[LEN2];
    char firstname[LEN2];
};
struct info {
    char num[LEN3];
    struct fullname  name;
};
void show(struct info * ptr);
int main(void)
{
    struct info infos[LEN1] = {
        {"111111111",{"panda","","zhang"}},
        {"111111112",{"pandb","Jsns","zhang"}},
        {"111111113",{"pandc","Dok","zhang"}},
        {"111111114",{"pandd","Lkjd","zhang"}},
        {"111111115",{"pande","Mshd","zhang"}}
    };
    show(infos);
    return 0;
}
void show(struct info * ptr)
{
    int i;

    for(i = 0;i < LEN1;i++)
    {
        if(strlen(ptr[i].name.middlename))
            printf("%s,%s %c. - %s\n",ptr[i].name.firstname,ptr[i].name.lastname,ptr[i].name.middlename[0],ptr[i].num);
        else
            printf("%s,%s - %s\n",ptr[i].name.firstname,ptr[i].name.lastname,ptr[i].num);
    }
}
//b
#include
#include
#define LEN1 5
#define LEN2 20
#define LEN3 10
struct fullname {
    char lastname[LEN2];
    char middlename[LEN2];
    char firstname[LEN2];
};
struct info {
    char num[LEN3];
    struct fullname  name;
};
void show(struct info inf);
int main(void)
{
    struct info infos[LEN1] = {
        {"111111111",{"panda","","zhang"}},
        {"111111112",{"pandb","Jsns","zhang"}},
        {"111111113",{"pandc","Dok","zhang"}},
        {"111111114",{"pandd","Lkjd","zhang"}},
        {"111111115",{"pande","Mshd","zhang"}}
    };
    int i;

    for(i = 0;i < LEN1;i++)
        show(infos[i]);
    return 0;
}
void show(struct info inf)
{
    int i;

        if(strlen(inf.name.middlename))
            printf("%s,%s %c. - %s\n",inf.name.firstname,inf.name.lastname,inf.name.middlename[0],inf.num);
        else
            printf("%s,%s - %s\n",inf.name.firstname,inf.name.lastname,inf.num);
}
———————————————分割线—————————————————
第五题:写一个程序,满足下列要求:
a.外部定义一个name结构模板,它含有2个成员:一个字符串用于存放名字,另一个字符串用于存放姓氏。
b.外部定义一个student结构模板,它含有3个成员:一个name结构,一个存放3个浮点数分数的grade数组,以及一个存放这3个分数的平均分的变量。
c.使main()函数声明一个具有CSIZE(CSIZE=4)个student结构的数组,并随意初始化这些结构的名字部分。使用函数来执行d、e、f以及g部分所描述的任务。
d.请求用户输入学生姓名和分数,以交互地获取每个学生的成绩。将分数放到相应结构的grade数组成员中。您可以自主选择在main()或一个函数中实现这个循环。
e.为每个结构计算平均分,并把这个值赋值给适合的成员。
f.输出每个结构中的信息。
g.输出结构的每个数值成员的班级平均分。
解:假定科目为语文、数学和英语
代码如下:
#include
#define CSIZE 4
#define SIZE 20
struct name {
    char firstname[SIZE];
    char lastname[SIZE];
};
struct student {
    struct name fname;
    float grade[3];
    float avg;
};
struct student getinfo(struct student s);
struct student avgcompute(struct student s);
void show(struct student s);
void showavg(struct student * ptr);
int main(void)
{
    struct student stds[CSIZE] = {
        {.fname.firstname = "bao"},
        {.fname.firstname = "bei"},
        {.fname.firstname = "bu"},
        {.fname.firstname = "ku"}
    };
    int i;


    for(i = 0;i < CSIZE;i++)
    {
        stds[i] = getinfo(stds[i]);
        stds[i] = avgcompute(stds[i]);
    }
    
    for(i = 0;i < CSIZE;i++)
    {
        show(stds[i]);
    }
    showavg(stds);     
    return 0;
}
struct student getinfo(struct student s)
{
    printf("Input %s's lastname:\n",s.fname.firstname);
    gets(s.fname.lastname);
    printf("Input %s's yu grade:\n",s.fname.firstname);
    scanf("%f",&s.grade[0]);
    while(getchar() != '\n');
    printf("Input %s's shu grade:\n",s.fname.firstname);
    scanf("%f",&s.grade[1]);
    while(getchar() != '\n');
    printf("Input %s's english grade:\n",s.fname.firstname);
    scanf("%f",&s.grade[2]);
    while(getchar() != '\n');
    return s;
}
struct student avgcompute(struct student s)
{
    s.avg = (s.grade[0] + s.grade[1] + s.grade[2]) / 3.0;
    return s;
}
void show(struct student s)
{
    printf("name:%s %s,grade:yu(%.2f) shu(%.2f) en(%.2f) average:%.2f\n",s.fname.firstname,s.fname.lastname,s.grade[0],s.grade[1],s.grade[2],s.avg);
}
void showavg(struct student * ptr)
{
    int i;
    float to_y = 0.0;
    float to_s = 0.0;
    float to_e = 0.0;
    
    for(i = 0;i < CSIZE;i++)
    {
        to_y += ptr[i].grade[0];
        to_s += ptr[i].grade[1];
        to_e += ptr[i].grade[2];
    }
    printf("yu:%.2f shu:%.2f en:%.2f all avg:%.2f\n",to_y / 4.0,to_s /4.0,to_e / 4.0,(to_y + to_s + to_e) / 12.0);
}
———————————————分割线—————————————————
第六题:一个文本文件中存放着一个棒球队的信息。每一行的数据都是这样排列的:
4 Jessie Joybat 5 2 1 1
第一项是球员号码,为了方便,范围是0到18.第二项是球员的名,第三项是姓。姓和名都是单个的单词。下一项是官方统计的球员上场次数,紧跟着是击中数、走垒数和跑点数(RBI)。文件可能包括超过一场比赛的数据。因此一个球员可能会有多余一行的数据,而且在不同的行之间有可能有别的球员的数据。写一个程序,把这些数据存储到一个结构数组中。结构中必须含有姓、名、上场次数、击中数、走垒数和跑点数,以及击球平均成功率(稍后计算)。可以使用球员号码作为数组索引。程序应该读到文件末尾,并且应该保存每个球员的累计总和。
    这个棒球运动中的统计方法是相关的。例如,一次走垒和触垒中的失误并不会记作上场次数,但是这可能产生一个RBI。可是,该程序所要做的只是处理数据文件,而不必关心数据的实际含义。要实现这些功能,最简单的方法是把结构的内容初始化为零值,将文件的数据读入临时变量中,然后把它们加到相应结构的内容中。程序读完文件后,应该计算每个球员的击球平均成功率,并把它保存到相应的结构成员里。计算击球平均成功率是用球员的累积击中数除以上次累计次数;这是个浮点数计算。然后程序要显示每个球员的累计数据,并且对整个时期显示一行综合统计数据。
解:模拟这个文件是stdin
代码如下:
#include
#include
#define SIZE 20
#define INDEX 19
struct info {
    char firstname[SIZE];
    char lastname[SIZE];
    int times;
    int hit;
    int zou;
    int rbi;
    float avg;
};
int main(void)
{
    struct info infos[INDEX] = {};
    int n,m,i;

    puts("Input player number(q to quit):");
    while(scanf("%d",&n)) 
    {
        while(getchar() != '\n');
        if(!strlen(infos[n].firstname))
        {
            puts("Input player's firstname:");
            gets(infos[n].firstname);
            puts("Input player's lastname:");
            gets(infos[n].lastname);
        }
        puts("Input times:");
        scanf("%d",&m);
        while(getchar() != '\n');
        infos[n].times += m;
        puts("Input hit:");
        scanf("%d",&m);
        while(getchar() != '\n');
        infos[n].hit += m;
        puts("Input zou:");
        scanf("%d",&m);
        while(getchar() != '\n');
        infos[n].zou += m;
        puts("Input rbi:");
        scanf("%d",&m);
        while(getchar() != '\n');
        infos[n].rbi += m;
        puts("Input next player number(q to quit):");
    }
    for(i = 0;i < INDEX;i++)
        infos[i].avg = (float)infos[i].hit / (float)infos[i].times;
    for(i = 0;i < INDEX;i++)
        if(strlen(infos[i].firstname))
            printf("number:%d name: %s %s times:%d hits:%d zou:%d rbi:%d avg:%.2f\n",
            i,infos[i].firstname,infos[i].lastname,infos[i].times,infos[i].hit,infos[i].zou,infos[i].rbi,infos[i].avg);
    return 0;
}
———————————————分割线—————————————————
第七题:修改程序清单14.14,在从文件中读出每个记录并且显示它时,允许用户选择删除该记录或修改该记录的内容。如果删除记录,把空出来的数组空间留给下一个要读入的记录。要能够改变现有的文件内容,必须使用"r+b"模式,而不是"a+b"模式。要注意文件指针的定位,以便追加的记录不会覆盖已有的记录。最简单的方法是对存储在程序内存中的数据做所有的改变,然后再把最后的信息写入文件中。
解:题意不便理解,不知是删除后添加是使用插入模式还是附加模式,那便补全模式:显示,新增,删除,插入,保存并退出,为了删除结构,引用了memory.h中的memset()。
代码如下:
#include
#include
#include
#include
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10
struct book {
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
char getchoice(void);
void print(struct book * library,int count);
int add(struct book * library,int count);
int del(struct book * library,int count);
int insert(struct book * library,int count);
void save(struct book * library,int count,FILE * fp);
int main(void)
{
    struct book library[MAXBKS];
    int count = 0;
    int index,filecount;
    FILE * pbooks;
    int size = sizeof(struct book);
    char ch;
  
    if((pbooks = fopen("book.dat","r+b")) == NULL)
    {
        fputs("Can't open book.dat file,create one\n",stderr);
        pbooks = fopen("book.dat","a+b");
    }
    rewind(pbooks);
    while(count < MAXBKS && fread(&library[count],size,1,pbooks) == 1)
    {
        if(count ==0)
            puts("Current contents of book.dat:");
        printf("number %d: %s by %s: $%.2f\n",count + 1,library[count].title,library[count].author,library[count].value);
        count++;
    }
    fclose(pbooks);
    while((ch = getchoice()) != 'q')
    {
        switch(ch)
        {
            case 'p':print(library,count);
                         break;
            case 'a':count = add(library,count);
                         break;
            case 'd':count = del(library,count);
                         break;
            case 'i':count = insert(library,count);
                         break;
            case 's':save(library,count,pbooks);
        }
    }
    puts("Bye.");
    return 0;
}
char getchoice(void)
{
    int ch;
    do
    {
    puts("You can do");
    puts("p)print all books                a)add books");
    puts("d)delete a  book                i)insert a book between books");
    puts("s)save change and quit     q)without save and quit");
    scanf("%c",&ch);
    while(getchar() != '\n');
    }while(!strchr("padisq",ch) && puts("wrong choice,try again"));
    return ch;
}
void print(struct book * library,int count)
{
    int i;
 
    if(count == 0)
        puts("Sorry,no book!");
    else
        for(i = 0;i < count;i++)
            printf("number %d: %s by %s: $%.2f\n",
            i + 1,library[i].title,library[ i ].author,library[i].value);
}
int add(struct book * library,int count)
{
    int i;

    if(count == MAXBKS)
        puts("Sorry,only save 10 books!");
    else
        for(i = count,puts("book title([Enter] at start to quit):");i < MAXBKS,gets(library[i].title) != NULL,library[i].title[0] != '\0';)
        {
            puts("book author:");
            gets(library[i].author);
            puts("book value:");
            scanf("%f",&library[i].value);
            while(getchar() != '\n');
            i++;
            if(i < MAXBKS)
                puts("next book title");
        }
    return i;    
}
int del(struct book * library,int count)
{
    int i;
    
    if(count == 0)
        puts("Sorry,no book!");
    else
    {
        print(library,count);
        puts("which number your will delete(0 to quit):");
        while(scanf("%d",&i) && i >0 && i < count)
        {
            while(getchar() != '\n');
            for(i--;i < count - 1;i++)
                library[i] = library[i + 1];
            memset(&library[count -1],0,sizeof(struct book));
        }
    }
    while(getchar() != '\n');
    return count - 1;
}
int insert(struct book * library,int count)
{
    int i,j;

    if(count == MAXBKS)
    {
        puts("Sorry,already 10 books!");
        return count;
    }
    else if(count == 0)
        puts("No book,you can't choose where to insert but add to 1");
    else
    {
        print(library,count);
        puts("which number your will insert(0 to quit):");
    }
    scanf("%d",&i);
    if(i >0 && i <= count)
    {
        while(getchar() != '\n');
        for(j = count;j >= i;j--)
            library[j] = library[j - 1];
        puts("book title:");
        gets(library[i - 1].title);
        puts("book author:");
        gets(library[i - 1].author);
        puts("book value:");
        scanf("%f",&library[i - 1].value);
        while(getchar() != '\n');
        return count + 1;
    }
    else
    {
        puts("wrong number!");
        return count;
    }
}
void save(struct book * lib rary ,int count,FILE * fp)
{
    if((fp = fopen("book.dat","wb")) == NULL)
    {
        fputs("Can't open book.dat file\n",stderr);
        exit(2);
    }
    if(fwrite(library,count * sizeof(struct book),1,fp))
    {
        puts("saved");
        fclose(fp);
        exit(0);
    }
    else
        puts("save failed");
    fclose(fp);
}
———————————————分割线—————————————————
第八题:巨人航空公司的机群由作为容量为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
#include
#include
#include
#define INDEX 12
#define LEN 20
struct customer {
    int index;
    _Bool own;
    char last[LEN];
    char first[LEN];
 };
char getchoice(void);
void show_n(struct customer * plane);
void show_l(struct customer * plane);
void show_a(struct customer * plane);
void assign(struct customer * plane);
void delete(struct customer * plane);
int main(void)
{
    struct customer plane[INDEX] = {
        {.index = 1,.own = false},
        {.index = 2,.own = false},
        {.index = 3,.own = false},
        {.index = 4,.own = false},
        {.index = 5,.own = false},
        {.index = 6,.own = false},
        {.index = 7,.own = false},
        {.index = 8,.own = false},
        {.index = 9,.own = false},
        {.index = 10,.own = false},
        {.index = 11,.own = false},
        {.index = 12,.own = false}
    };
    char ch;
    FILE * fp;
    char file[] = "customer.list";
    int size = sizeof(struct customer);
    int count = 0;
    
    
    if((fp = fopen(file,"r+b")) == NULL)
    {
        fputs("Can't open file,create one\n",stderr);
        fp = fopen(file,"a+b");
    }
    rewind(fp);
    while(count < INDEX)
        fread(&plane[count++],size,1,fp);
    fclose(fp);
    while((ch = getchoice()) != 'f')
    {
        switch(ch)
        {
            case 'a':show_n(plane);
                         break;
            case 'b':show_l(plane);
                         break;
            case 'c':show_a(plane);
                         break;
            case 'd':assign(plane);
                         break;
            case 'e':delete(plane);
        }
    }
    if((fp = fopen(file,"wb")) == NULL)
    {
        fputs("Can't open file\n",stderr);
        exit(2);
    }
    if(fwrite(plane,INDEX * size,1,fp))
    {
        puts("saved");
        fclose(fp);
        exit(0);
    }
    else
        puts("save failed");
    fclose(fp);
    puts("Bye.");
    return 0;
}
char getchoice(void)
{
    char ch;

    do
    {
    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");
    scanf("%c",&ch);
    while(getchar() != '\n');
    }while(!strchr("abcdef",ch) && puts("wrong choice,try again"));
    return ch;
}
void show_n(struct customer * plane)
{
    int n,m;
  
    for(n = 0,m = 0;n < INDEX;n++)
        if(!plane[n].own)
            m++;
    printf("%d empty seats\n",m);
}
void show_l(struct customer * plane)
{
    int n;
  
    puts("empty seats index:");
    for(n = 0;n < INDEX;n++)
        if(!plane[n].own)
            printf(" %d",plane[n].index);
    puts("");
}
void show_a(struct customer * plane)
{
    char * ptr[INDEX];
    int n,m;
    char * temp;

    for(n = 0;n < INDEX;n++)
        ptr[n] = plane[n].first;
    for(n = 0;n < INDEX - 1;n++)
        for(m = n + 1;m < INDEX; m++)
            if(strcmp(ptr[n],ptr[m]) > 0)
            {
                temp = ptr[n];
                ptr[n] = ptr[m];
                ptr[m] = temp;
            }
    for(n = 0;n < INDEX;n++)
        for(m = 0;m < INDEX;m++)
            if(strlen(ptr[n]) > 0 && strcmp(ptr[n],plane[m].first) == 0)
                printf("%s %s own seat %d\n",plane[m].first,plane[m].last,plane[m].index);
}
void assign(struct customer * plane)
{
    int n = 1;

    show_l(plane);
    puts("which index do you want to assign(0 to back):");
    while(scanf("%d",&n) && n > 0 && n <= INDEX)
    {
        while(getchar() != '\n');
        if(!plane[--n].own)
        {
            puts("Input lastname:");
            gets(plane[n].last);
            puts("Input firstname:");
            gets(plane[n].first);
            plane[n].own = true;
        }    
        else
            puts("it is owned,try again");
        puts("which index do you want to assign(0 to back):");
    }
    while(getchar() != '\n');
}
void delete(struct customer * plane)
{
    int n;
  
    puts("owned seats index:");
    for(n = 0;n < INDEX;n++)
        if(plane[n].own)
            printf(" %d:%s %s\n",plane[n].index,plane[n].first,plane[n].last);
    puts("which index do you want to delete(0 to back):");
    while(scanf("%d",&n) && n > 0 && n <= INDEX)
    {
        while(getchar() != '\n');
        if(plane[--n].own)
        {
            plane[n].own = false;
            strcpy(plane[n].last,"");
            strcpy(plane[n].first,"");
        }    
        else
            puts("it is empty,try again");
        puts("which index do you want to delete(0 to back):");
    }
    while(getchar() != '\n');
}
———————————————分割线—————————————————
第九题:巨人航空公司(见第八题)需要另一架飞机(同样容量),并使它每天服务4个航班(航班102、311、444和519)。把程序扩展为能够处理4个航班。有一个顶层菜单可供选择航班和退出。选择了一个特定的航班,就会调出和第八题相似的菜单,但要加上一个新项:确认一个座位分配;并用一个退回顶层菜单的选项代替退出选项。每个显示要指明现在正在处理哪个航班。座位分配显示必须要指明确认状态。
解:将航班号加入到乘客的结构中,并且用4个文件来管理4个航班的信息
代码如下:
#include
#include
#include
#include
#define INDEX 12
#define LEN 20
struct customer {
    int flt_no;
    int index;
    _Bool own;
    _Bool confirm;
    char last[LEN];
    char first[LEN];
 };
int getflt(void);
char getchoice(void);
void show_n(struct customer * plane);
void show_l(struct customer * plane);
void show_a(struct customer * plane);
void assign(struct customer * plane);
void confirm(struct customer * plane);
void delete(struct customer * plane);
int main(void)
{
    struct customer planetmp[INDEX] = {
        {.index = 1,.own = false,.confirm = false},
        {.index = 2,.own = false,.confirm = false},
        {.index = 3,.own = false,.confirm = false},
        {.index = 4,.own = false,.confirm = false},
        {.index = 5,.own = false,.confirm = false},
        {.index = 6,.own = false,.confirm = false},
        {.index = 7,.own = false,.confirm = false},
        {.index = 8,.own = false,.confirm = false},
        {.index = 9,.own = false,.confirm = false},
        {.index = 10,.own = false,.confirm = false},
        {.index = 11,.own = false,.confirm = false},
        {.index = 12,.own = false,.confirm = false}
    };
    struct customer plane[INDEX];
    int flt;
    char ch;
    FILE * fp;
    char file[LEN];
    int size = sizeof(struct customer);
    int count = 0;
    
    while((flt = getflt()) != 0)
    {
        for(count = 0;count < INDEX;count++)
            plane[count] = planetmp[count];
        switch(flt)
        {
            case 102:for(count = 0;count < INDEX;count++)
                               plane[count].flt_no = 102;
                           strcpy(file,"FLT_NO102") ;
                           break;
            case 311: for(count = 0;count < INDEX;count++)
                               plane[count].flt_no = 311;
                           strcpy(file,"FLT_NO311") ;
                           break;
            case 444: for(count = 0;count < INDEX;count++)
                               plane[count].flt_no = 444;
                           strcpy(file,"FLT_NO44") ;
                           break;
            case 519: for(count = 0;count < INDEX;count++)
                               plane[count].flt_no = 519;
                           strcpy(file,"FLT_NO519") ;
        }
        if((fp = fopen(file,"r+b")) == NULL)
        {
            fputs("Can't open file,create one\n",stderr);
            fp = fopen(file,"a+b");
        }
        rewind(fp);
        count = 0;
        while(count < INDEX)
            fread(&plane[count++],size,1,fp);
        fclose(fp);

        while((ch = getchoice()) != 'g')
        {
            switch(ch)
            {
                case 'a':show_n(plane);
                             break;
                case 'b':show_l(plane);
                             break;
                case 'c':show_a(plane);
                             break;
                case 'd':assign(plane);
                             break;
                case 'e':confirm(plane);
                             break;
                case 'f':delete(plane);
            }
        }
    if((fp = fopen(file,"wb")) == NULL)
    {
        fputs("Can't open file\n",stderr);
        exit(2);
    }
    if(fwrite(plane,INDEX * size,1,fp))
        puts("saved");
    else
        puts("save failed");
    fclose(fp);
    }
    puts("Bye.");
    return 0;
}
int getflt(void)
{
    int ch;

    do
    {
    puts("To choose flight no(0 to quit) :");
    puts("102    311    444    519");
    scanf("%d",&ch);
    while(getchar() != '\n');
    }while(ch != 102 && ch != 311 && ch != 444 && ch != 519 && ch != 0 && puts("wrong choice,try again"));
    return ch;
}
char getchoice(void)
{
    char ch;

    do
    {
    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)Confirm the a seat  assignment");
    puts("f)Delete a seat assignment");
    puts("g)Back");
    scanf("%c",&ch);
    while(getchar() != '\n');
    }while(!strchr("abcdefg",ch) && puts("wrong choice,try again"));
    return ch;
}
void show_n(struct customer * plane)
{
    int n,m;
  
    for(n = 0,m = 0;n < INDEX;n++)
        if(!plane[n].own)
            m++;
    printf("%d empty seats\n",m);
}
void show_l(struct customer * plane)
{
    int n;
  
    puts("empty seats index:");
    for(n = 0;n < INDEX;n++)
        if(!plane[n].own)
            printf(" %d",plane[n].index);
    puts("");
}
void show_a(struct customer * plane)
{
    char * ptr[INDEX];
    int n,m;
    char * temp;

    for(n = 0;n < INDEX;n++)
        ptr[n] = plane[n].first;
    for(n = 0;n < INDEX - 1;n++)
        for(m = n + 1;m < INDEX; m++)
            if(strcmp(ptr[n],ptr[m]) > 0)
            {
                temp = ptr[n];
                ptr[n] = ptr[m];
                ptr[m] = temp;
            }
    for(n = 0;n < INDEX;n++)
        for(m = 0;m < INDEX;m++)
            if(strlen(ptr[n]) > 0 && strcmp(ptr[n],plane[m].first) == 0)
            printf("FLT_NO:%d index:%d name:%s %s\n",plane[m].flt_no,plane[m].index,plane[m].first,plane[m].last);
}
void assign(struct customer * plane)
{
    int n = 1;

    show_l(plane);
    puts("which index do you want to assign(0 to back):");
     while(scanf("%d",&n) && n > 0 && n <= INDEX)
    {
        while(getchar() != '\n');
        if(!plane[--n].own)
        {
            puts("Input lastname:");
            gets(plane[n].last);
            puts("Input firstname:");
            gets(plane[n].first);
            plane[n].own = true;
        }    
        else
            puts("it is owned,try again");
        puts("which index do you want to assign(0 to back):");
    }
    while(getchar() != '\n');
}
void confirm(struct customer * plane)
{
    int n;
    puts("unconfirmed seats index:");
    for(n = 0;n < INDEX;n++)
        if(plane[n].own && !plane[n].confirm)
            printf("FLT_NO:%d index:%d name:%s %s\n",plane[n].flt_no,plane[n].index,plane[n].first,plane[n].last);
    puts("which index do you want to confirm(0 to back):");
    while(scanf("%d",&n) && n > 0 && n <= INDEX)
    {
        while(getchar() != '\n');
        if(plane[--n].own && !plane[n].confirm)
        {
            plane[n].confirm = true;
        }    
        else
            puts("it is not owned or it had confirmed,try again");
        puts("which index do you want to confirm(0 to back):");
    }
    while(getchar() != '\n');
}
void delete(struct customer * plane)
{
    int n;
  
    puts("owned seats index:");
    for(n = 0;n < INDEX;n++)
        if(plane[n].own)
            printf("FLT_NO:%d index:%d name:%s %s\n",plane[n].flt_no,plane[n].index,plane[n].first,plane[n].last);
    puts("which index do you want to delete(0 to back):");
    while(scanf("%d",&n) && n > 0 && n <= INDEX)
    {
        while(getchar() != '\n');
        if(plane[--n].own)
        {
            plane[n].own = false;
            strcpy(plane[n].last,"");
            strcpy(plane[n].first,"");
        }    
        else
            puts("it is empty,try again");
        puts("which index do you want to delete(0 to back):");
    }
    while(getchar() != '\n');
}
———————————————分割线—————————————————
第十题:编写一个程序,用指向函数的指针数组执行菜单。例如,在菜单中选择a会激活由数组第一个元素指向的函数。
解:
代码如下:
#include
void ta(void);
void tb(void);
void print(void (* fp)(void));
int main(void)
{
    void (* fp[2])(void);
    fp[0] = ta;
    fp[1] = tb;
    char ch;
 
    do
    {
        puts("you have a choose like:");
        puts("a)use function a");
        puts("b)use function b");
        scanf("%c",&ch);
        while(getchar() != '\n');
    }while(ch != 'a' && ch != 'b' && puts("wrong choice,try again"));
    if(ch == 'a')
        print(fp[0]);
    else
        print(fp[1]);
    return 0;
}
void ta(void)
{
    printf("I am temp function a\n");
}
void tb(void)
{
    printf("I am temp function b\n");
}
void print(void (* fp)(void))
{
    (* fp)();
}
———————————————分割线—————————————————
第十一题:编写一个transform()函数,它接收4个参数:包含double类型数据的源数组名,double类型的目标数组名,表示数组元素个数的int变量以及一个函数名(或者,等价的指向函数的指针)。transform()函数把指定的函数作用于源数组的每个元素,并将返回值放到目标数组中。例如:
    transform(source,target,100,sin);
    这个函数调用把sin(source[0])赋给target[0],等等,共有100个元素。在一个程序中测试该函数,调用4次transform(),分别使用math.h函数库中的两个函数以及自己设计的两个合适的函数作为参数。
解:
代码如下:
#include
#include
double addone(double n);
double reduceone(double n);
void transform(double * source,double * target,int n,double (* fp)(double m));
int main(void)
{
    double source[10] = {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
    double target[10];
    int i;
    double (* fp)(double m);

    puts("source:");
    for(i = 0;i < 10;i++)
        printf(" %.2f",source[i]);
    puts("");
    puts("function sin:");
    transform(source,target,10,sin);
    puts("function cos:");
    transform(source,target,10,cos);
    puts("function addone:");
    transform(source,target,10,addone);
    puts("function reduceone:");
    transform(source,target,10,reduceone);
    return 0;
}
double addone(double n)
{
    return n + 1.0;
}
double reduceone(double n)
{
    return n - 1.0;
}
void transform(double * source,double * target,int n,double (* fp)(double m))
{
    int i;
  
    for(i = 0;i < 10;i++)
    {
        target[i] = fp(source[i]);
        printf(" %.2f",target[i]);
    }
    puts("");
}
运行说明:如果编译时提示sin和cos未定义,错误原因主要是没有定义“sin”函数,或者说没有找到“sin”函数的实现,虽然我们在函数开头声明了数学函数库,但还是没有找到sin的实现,这时我们就需要指定sin函数的具体路径了。
[ root@c cpp]# gcc 14_11.c
/tmp/ccJhYNWJ.o: In function `main':
14_11.c:(.text+0xf7): undefined reference to `sin'
14_11.c:(.text+0x11e): undefined reference to `cos'
collect2: error: ld returned 1 exit status
[ root@c cpp]# gcc 14_11.c -lm          
[ root@c cpp]# ./a.out 
source:
 0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00
function sin:
 0.00 0.84 0.91 0.14 -0.76 -0.96 -0.28 0.66 0.99 0.41
function cos:
 1.00 0.54 -0.42 -0.99 -0.65 0.28 0.96 0.75 -0.15 -0.91
function addone:
 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 10.00
function reduceone:
 -1.00 0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00
















你可能感兴趣的:(C,Primer,Plus编程练习)