《C Primer Plus》第14章复习题与编程练习

《C Primer Plus》第14章复习题与编程练习

复习题

1. 以下模板有什么错误?

structure {
    char itable;
    int num[20];
    char * togs
}

正确的关键字是struct而不是structure。模板需要在开始花括号前有一个标记或在结束花括号后有一个变量名。在*togs后面和在模板结尾处都应该有一个分号。

2. 下面是某程序的一部分。输出会是什么?

#include <stdio.h>

struct house {
    float sqft;
    int rooms;
    int stories;
    char address[40];
};
int main(void)
{
    struct house fruzt = {1560.0, 6, 1, "22 Spiffo Road"};
    struct house *sign;

    sign = &fruzt;
    printf("%d %d\n", fruzt.rooms, sign->stories);
    printf("%s \n", fruzt.address);
    printf("%c %c\n", sign->address[3], fruzt.address[4]);
    return 0;
}

6 1
22 Spiffo Road
S p

3. 设计一个结构模板,保存一个月份名、一个3个字母的该月份的缩写、该月的天数,以及月份号。

struct month {
char name[30];
char sup_name[4];
int days;
int month_day;
};

4. 定义一个含有12个第3题中那种类型的结构的数组,并把它初始化为一个年份(非闰年)

struct month months[12] =
{
{“January”, “jan”, 31, 1},
{“February”, “feb”, 28, 2},
{“March”, “mar”, 31, 3},
{“April”, “apr”, 30, 4},
{“May”, “may”, 31, 5},
{“June”, “jun”, 30, 6},
{“July”, “jul”, 31, 7},
{“August”, “aug”, 31, 8},
{“September”, “sep”, 30, 9},
{“October”, “oct”, 31, 10},
{“November”, “nov”, 30, 11},
{“December”, “dec”, 31, 12}
};

5. 编写一个函数。当给出月份号后,程序返回一年中到该月为止(包括该月)总共的天数。假定在外部声明了第3题中的结构模板和一个该结构的数组。

#include <stdio.h>

struct month {
    char name[30];
    char sup_name[4];
    int days;
    int month_day;
};
int days(const struct month months[], int month);
int main(void)
{
    int month;
    struct month months[12] =
    {
        {"January", "jan", 31, 1},
        {"February", "feb", 28, 2},
        {"March", "mar", 31, 3},
        {"April", "apr", 30, 4},
        {"May", "may", 31, 5},
        {"June", "jun", 30, 6},
        {"July", "jul", 31, 7},
        {"August", "aug", 31, 8},
        {"September", "sep", 30, 9},
        {"October", "oct", 31, 10},
        {"November", "nov", 30, 11},
        {"December", "dec", 31, 12}
    };
    printf("Please enter the month: \n");
    scanf("%d", &month);
    printf("the total days is: %d\n", days(months, month));
    return 0;
}
int days(const struct month months[], int month)
{
    int index, total;

    if(month < 1 || month > 12)
         return -1;
    else
    {
        for(index = 0; index < month; index++)
             total += months[index].days;
        return total;
    }
}

6.

a.给定下面的typedef,声明一个10个元素的指定结构的数组。然后通过各个成员赋值(或等价字符串),使第3个元素描述一个焦距长度为500mm,孔径为f/2.0的Remarkata镜头。

typedef struct lens {     /* 镜头描述 */
    float foclen;         /* 焦距长度 */
    float fstop;          /* 孔径 */
    char brand[30];       /* 品牌名称 */
} LENS;

b.重复a,但在声明中使用一个指定初始化项目列表,而不是对每个成员使用单独的赋值语句。

答:

a.

typedef struct lens { /* 镜头描述 /
float foclen; /
焦距长度 /
float fstop; /
孔径 /
char brand[30]; /
品牌名称 */
} LENS;
LENS arr[10];
arr[2].foclen = 500;
arr[2].fstop = 2.0;
strcpy(arr[2].brand, “Remarkata”); // #include <string.h>

b.

typedef struct lens { /* 镜头描述 /
float foclen; /
焦距长度 /
float fstop; /
孔径 /
char brand[30]; /
品牌名称 */
} LENS;
LENS arr[10] = { [2] = {500, 2.0, “Remarkata”} };

7. 考虑下面的程序段:

struct name {
    char first[20];
    char last[20];
};
struct bem {
    int limbs;
    struct name title;
    char type[30];
};
struct bem * pb;
struct bem deb = {
    6,
    {"Berbnazel", "Gwolkapwolk"},
    "Arcturan"
};

pb = &deb;

a.下列每个语句会打印出什么?

printf("%d\n", deb.limbs);
printf("%s\n", pb->type);
printf("%s\n", pb->type + 2);

b.
怎样用结构符号表示"Gwolkapwolk"(使用两种方法)?

c.
编写一个函数,以一个bem结构的地址作为参数,并以下面所示的形式输出结构内容。假定结构模板在一个名为starfolk.h的文件中。

Berbnazel Gwolkapwolk is a 6-limbed Arcturan.

答:
a.

6
Arcturan
cturan

b.

deb.title.last
pb->title.last

c.

#include <stdio.h>
#include "starfolk.h"
struct name {
    char first[20];
    char last[20];
};
struct bem {
    int limbs;
    struct name title;
    char type[30];
};
void show(const struct bem *);
int main(void)
{
    struct bem * pb;
    struct bem deb = {
        6,
        {"Berbnazel", "Gwolkapwolk"},
        "Arcturan"
    };

    pb = &deb;
    show(pb);
    return 0;
}
void show(const struct bem * fp)
{
    printf("%s %s is a %d-limbed %s.", fp->title.first, fp->title.last, fp->limbs, fp->type);
}

8. 考虑下列声明:

struct fullname {
    char fname[20];
    char lname[20];
};
struct bard {
    struct fullname name;
    int born;
    int died;
};
struct bard willie;
struct bard *pt = &willie;

a.使用willie标识符表示willie结构的born成员。

b.使用pt标识符表示willie结构的born成员。

c.使用一个scanf()函数调用为通过willie标识符表示的born成员读入一个值。

d.使用一个scanf()函数调用为通过pt标识符表示的born成员读入一个值。

e.使用一个scanf()函数调用为通过willie标识符表示的name成员的lname成员读入一个值。

f.使用一个scanf()函数调用为通过pt标识符表示的name成员的lname成员读入一个值。

g.构造一个标识符,表示willie变量描述的人的名字的第3个字母。

h.构造一个表达式,表示willie变量描述的人的姓和名的所有字母数。

答:

a.willie.born
b.pt->born
c.scanf(“%d”, &willie.born);
d.scanf(“%d”, &pt->born);
e.scanf(“%s”, willie.name.lname);
f.scanf(“%s”, pt->name.lname);
g.willie.name.fname[2]; (我觉得有欠考虑,万一姓不足3个字母怎么办?)
h.strlen(willie.name.fname) + strlen(willie.name.lname);

9. 定义一个适合保存下列项目的结构模板:一辆汽车的名称、马力、市内行驶的EPA英里每加仑(mpg)等级、轴距和使用年数。用car作为模板标记。

struct car {
char name[20];
float hp;
float epampg;
float wbase;
int year;
};

10. 假设有以下结构:

struct gas {
    float distance;
    float gals;
    float mpg;
};

a.设计一个函数,它接受一个struct gas参数。假定传递进来的结构包括distance和gals信息。函数为mpg成员正确计算出值并返回这个现在完整的结构。

b.设计一个函数,它接受一个struct gas参数的地址。假定传递进来的结构包括distance和gals信息。函数为mpg成员正确计算出值并把它赋给恰当的成员。

答:

a.

struct gas mpgs(struct gas fp)
{
    if(fp.gals > 0)
        fp.mpg = fp.distance / fp.gals;
    else
        fp.mpg = -1.0;
    return fp;
}

b.

void set_mpgs(struct gas * fp)
{
    if(fp->gals > 0)
        fp->mpg = fp->distance / fp->gals;
    else
        fp->mpg = -1.0;
}

11. 声明一个枚举类型,使用choices作为标记,将枚举常量no、yes和maybe分别设置为0、1和2。

enum choices {no, yes, maybe};

12. 声明一个指向函数的指针。该函数的返回值是一个char指针,参数为一个char指针和一个char值。

char * (* fp)(char *, char);

13. 声明4个函数,并把一个指针数组初始化为指向它们。每个函数接受两个double参数并返回一个double值。另外,用两种方法使用该数组调用带10.0和2.5实参的第2个函数。

double f1(double, double);
double f2(double, double);
double f3(double, double);
double f4(double, double);
double (*fp[4])(double, double) = {f1, f2, f3, f4};

调用:

fp[1](10.0, 2.5);
(*fp[1])(10.0, 2.5);

编程练习

1. 重新编写复习题5

重新编写复习题5,用月份名的拼写代替月份号(别忘了使用strcmp())。在一个简单的程序中测试该函数。

代码:

months.h:

#ifndef MONTHS_H
#define MONTHS_H

struct month
{
    char name[20];
    char abbrev[4];
    int days;
    int monumb;
}; // 结构模板

extern struct month months[12];

#endif

months.cpp:

#include "months.h"

struct month months[12] =
    {
        {"January", "Jan", 31, 1},
        {"February", "Feb", 28, 2},
        {"March", "Mar", 31, 3},
        {"April", "Apr", 30, 4},
        {"May", "May", 31, 5},
        {"June", "Jun", 30, 6},
        {"July", "Jul", 31, 7},
        {"August", "Aug", 31, 8},
        {"September", "Sep", 30, 9},
        {"October", "Oct", 31, 10},
        {"November", "Nov", 3, 11},
        {"December", "Dec", 31, 12}}; // 结构数组

14.1.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "months.h"

int days(char *input); // 获取月份名,计算天数

int main()
{
    char input[20];
    int total_days;

    printf("请输入月份名:(按q退出程序)\n");
    while (scanf("%s", input) == 1 && input[0] != 'q') // 输入q才停止循环
    {
        total_days = days(input); // 调用函数
        if (total_days > 0)       // 总天数大于0,说明有对应月份号
        {
            printf("总天数是:%d\n", total_days);
        }
        else
        {
            printf("输入有误。\n");
        }
        printf("请输入下一个月份名:(按q退出程序)\n");
    }
    printf("程序结束\n");

    system("pause");
    return 0;
}

int days(char *input)
{
    int i;
    int total = 0;
    int num = 0;

    input[0] = toupper(input[0]);      // 第一个字母转成大写
    for (i = 1; input[i] != '\0'; i++) // 循环到输入为止,都转为小写字母
    {
        input[i] = tolower(input[i]);
    }
    for (i = 0; i < 12; i++)
    {
        if (strcmp(input, months[i].name) == 0) // 和结构数组每一个元素的名字比较
        {
            num = months[i].monumb; // 找到对应月份,把月份号赋值给num
            break;
        }
    }
    if (num == 0) // 没有对应月份号
    {
        total = 0;
    }
    else
    {
        for (i = 0; i < num; i++) // 有对应月份号
        {
            total += months[i].days; // 求和
        }
    }
    return total; // 返回总天数
}

运行结果:

在这里插入图片描述

2. 返回一年中到用户指定日子(包括这一天)的总天数

编写一个函数,提示用户输入日、月和年。月份可以是月份号、月份名或月份名缩写。然后该 程序应返回一年中到用户指定日子(包括这一天)的总天数。

代码:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#define LEN 12

struct month
{
    char name[10];
    char abbrev[4];
    int days;
    int monumb;
};

struct month months[LEN] =
    {
        {"January", "Jan", 31, 1},
        {"February", "Feb", 28, 2},
        {"March", "Mar", 31, 3},
        {"April", "Apr", 30, 4},
        {"May", "May", 31, 5},
        {"June", "Jun", 30, 6},
        {"July", "Jul", 31, 7},
        {"August", "Aug", 31, 8},
        {"September", "Sep", 30, 9},
        {"October", "Oct", 31, 10},
        {"November", "Nov", 30, 11},
        {"December", "Dec", 31, 12}};

void leap_year(int year);
int days_result(char *month, int days);

int main()
{
    int n, val;
    int day, year;
    char month[LEN];

    printf("Please enter day, month and year (q to quit): ");
    while (scanf("%d %11s %d", &day, month, &year) == 3)
    {
        leap_year(year);
        val = days_result(month, day);
        if (val > 0)
        {
            printf("There are %d days from the beginning of %d to %s %d\n", val, year, month, day);
        }
        else
        {
            printf("input error\n");
        }
        months[1].days = 28; // 2月份天数还原为非闰年时的天数
        printf("You can enter day, month and year again (q to quit): ");
    }
    printf("Done.\n");

    system("pause");
    return 0;
}

void leap_year(int year) // 判断是否是闰年
{
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        months[1].days = 29; // 是闰年则2月份天数改为29天;
    }
    return;
}

int days_result(char *month, int days)
{
    int i;
    int total = 0;
    int temp = atoi(month);

    if (days < 1 || days > 31)
    {
        return -1; // 输入的天数有误则终止本函数
    }
    if (0 == temp) // 用户输入的月份不是数字时要进行转换
    {
        month[0] = toupper(month[0]);
        for (i = 1; month[i] != '\0'; i++)
        {
            month[i] = tolower(month[i]);
        }
    }
    for (i = 0; i < LEN; i++)
    {
        if ((temp == months[i].monumb) ||
            (strcmp(month, months[i].name) == 0) ||
            (strcmp(month, months[i].abbrev) == 0))
        {
            if (days > months[i].days)
            {
                return -1; // 输入的天数不符合月份的规则
            }
            else
            {
                return total + days; // 累加到此月后加上本月天数
            }
        }
        else
        {
            total += months[i].days;
        }
    }
    return -1; // 输入月份有误后的终止条件
}

运行结果:

在这里插入图片描述

3. 按照要求输出图书的信息

修改程序清单14.2中的图书目录程序,使其按照输入图书的顺序输出图书的信息,然后按照标题字母的声明输出图书的信息,最后按照价格的升序输出图书的信息。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100

struct book
{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

char *s_gets(char *st, int n);
void sort_title(struct book *pb[], int n);
void sort_value(struct book *pb[], int n);

int main()
{
    struct book library[MAXBKS];
    struct book *book[MAXBKS]; // 指向结构体book的指针数组
    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 && s_gets(library[count].title, MAXTITL) && library[count].title[0] != '\0')
    {
        printf("Now enter the author.\n");
        s_gets(library[count].author, MAXAUTL);
        printf("Now enter the value.\n");
        scanf("%f", &library[count].value);
        book[count] = &library[count];
        count++;
        while (getchar() != '\n')
            continue;
        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);
        }
        // 按照标题字母的声明输出图书的信息
        sort_title(book, count);
        printf("\nHere is the list of your books sorted by title letters:\n");
        for (index = 0; index < count; index++)
        {
            printf("%s by %s: $%.2f\n", book[index]->title,
                   book[index]->author, book[index]->value);
        }
        // 按照价格的升序输出图书的信息
        sort_value(book, count);
        printf("\nHere is the list of your books sorted by value(from low to high):\n");
        for (index = 0; index < count; index++)
        {
            printf("%s by %s: $%.2f\n", book[index]->title,
                   book[index]->author, book[index]->value);
        }
    }
    else
    {
        printf("No books? Too bad.\n");
    }

    system("pause");
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void sort_title(struct book *pb[], int n)
{
    struct book *temp;

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (strcmp(pb[j]->title, pb[i]->title) < 0)
            {
                temp = pb[j];
                pb[j] = pb[i];
                pb[i] = temp;
            }
        }
    }
    return;
}

void sort_value(struct book *pb[], int n)
{
    struct book *temp;

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (pb[j]->value < pb[i]->value)
            {
                temp = pb[j];
                pb[j] = pb[i];
                pb[i] = temp;
            }
        }
    }
    return;
}

运行结果:

在这里插入图片描述

4. 传值 / 传地址打印数据

编写一个程序,创建一个有两个成员的结构模板:

a.第1个成员是社会保险号,第2个成员是一个有3个成员的结构,第1个成员代表名,第2 个成员代表中间名,第3个成员表示姓。创建并初始化一个内含5个该类型结构的数组。该程序以下 面的格式打印数据:

Dribble, Flossie M. –– 302039823

如果有中间名,只打印它的第1个字母,后面加一个点(.);如果没有中间名,则不用打印 点。编写一个程序进行打印,把结构数组传递给这个函数。

b.修改a部分,传递结构的值而不是结构的地址。

a.

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 15
#define LEN 30

struct names
{
    char fname[N];
    char mname[N];
    char lname[N];
};

struct messages
{
    char ins_num[LEN];
    struct names name;
};

char *s_gets(char *st, int n);
void show(struct messages *p[], int n);

int main()
{
    int count = 0;
    struct messages m[5];
    struct messages *p[5];

    printf("Please enter the insurance number:\n");
    printf("Press [enter] at the start of a line to stop.\n");
    while (count < 5 && s_gets(m[count].ins_num, LEN) && m[count].ins_num[0] != '\0')
    {
        printf("Now enter the former name.\n");
        s_gets(m[count].name.fname, N);
        printf("Now enter the middle name (without, [enter] to the next).\n");
        s_gets(m[count].name.mname, N);
        printf("Now enter the last name.\n");
        s_gets(m[count].name.lname, N);
        if (count++ < 5)
        {
            printf("Enter the next insurance number:\n");
        }
    }
    for (int i = 0; i < count; i++)
        p[i] = &m[i];
    if (count > 0)
    {
        show(p, count);
    }
    else
    {
        printf("No data!\n");
    }

    system("pause");
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void show(struct messages *p[], int n)
{
    printf("All numbers messages:\n");
    for (int i = 0; i < n; i++)
    {
        if (p[i]->name.mname[0] == '\0')
        {
            printf("%s, %s", p[i]->name.fname, p[i]->name.lname);
            printf(" -- %s\n", p[i]->ins_num);
        }
        else
        {
            printf("%s, %s %c.", p[i]->name.fname, p[i]->name.lname, p[i]->name.mname[0]);
            printf(" -- %s\n", p[i]->ins_num);
        }
    }
    return;
}

运行结果:

在这里插入图片描述

b.

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 15
#define LEN 30

struct names
{
    char fname[N];
    char mname[N];
    char lname[N];
};

struct messages
{
    char ins_num[LEN];
    struct names name;
};

char *s_gets(char *st, int n);
void show(const struct messages m[], int n);

int main()
{
    int count = 0;
    struct messages m[5];

    printf("Please enter the insurance number:\n");
    printf("Press [enter] at the start of a line to stop.\n");
    while (count < 5 && s_gets(m[count].ins_num, LEN) && m[count].ins_num[0] != '\0')
    {
        printf("Now enter the former name.\n");
        s_gets(m[count].name.fname, N);
        printf("Now enter the middle name (without, [enter] to the next).\n");
        s_gets(m[count].name.mname, N);
        printf("Now enter the last name.\n");
        s_gets(m[count].name.lname, N);
        if (count++ < 5)
        {
            printf("Enter the next insurance number:\n");
        }
    }
    if (count > 0)
    {
        show(m, count);
    }
    else
    {
        printf("No data!\n");
    }

    system("pause");
    return 0;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void show(const struct messages m[], int n)
{
    printf("All numbers messages:\n");
    for (int i = 0; i < n; i++)
    {
        if (m[i].name.mname[0] == '\0')
        {
            printf("%s, %s", m[i].name.fname, m[i].name.lname);
            printf(" -- %s\n", m[i].ins_num);
        }
        else
        {
            printf("%s, %s %c.", m[i].name.fname, m[i].name.lname, m[i].name.mname[0]);
            printf(" -- %s\n", m[i].ins_num);
        }
    }
    return;
}

运行结果:

在这里插入图片描述

5. 班级

编写一个程序满足下面的要求。

a. 外部定义一个有两个成员的结构模板name: 一个字符串储存名,一个字符串储存姓。
b. 外部定义一个有3个成员的结构模板student: 一个name类型的结构,一个grade数组储存3个浮点型分数,一个变量储存3个分数平均数。
c. 在main()函数中声明一个内含CSIZE (CSIZE = 4)个student类型结构的数组,并初始化这些结构的名字部分。用函数执行d、e、f和g中描述的任务。
d. 以交互的方式获取每个学生的成绩,提示用户输入学生的姓名和分数。把分数储存到grade数组相应的结构中。可以在main()函数或其他函数中用循环来完成。
e. 计算每个结构的平均分,并把计算后的值赋给合适的成员。
f. 打印每个结构的信息。
g. 打印班级的平均分,即所有结构的数值成员的平均值。

代码:

student.h:

#ifndef STUDENT_H
#define STUDENT_H

#define LEN 15
#define CSIZE 4
#define SCORES 3

struct names
{
    char fname[LEN];
    char lname[LEN];
};

struct student
{
    struct names name;
    float grade[SCORES];
    float average;
};

extern struct student s[CSIZE];

#endif

student.cpp:

#include "student.h"

struct student s[CSIZE] =
    {
        {"Flip", "Snide"},
        {"Clare", "Voyans"},
        {"Bingo", "Higgs"},
        {"Fawn", "Hunter"}}; // 结构数组

main.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.h"

void set_students(struct student s[], int n);
void cal_averages(struct student s[], int n);
void show_students(const struct student s[], int n);
void show_averages(const struct student s[], int n);

int main()
{
    set_students(s, CSIZE);
    cal_averages(s, CSIZE);
    show_students(s, CSIZE);
    show_averages(s, CSIZE);

    system("pause");
    return 0;
}

void set_students(struct student s[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("Please enter three scores for %s %s:\n", s[i].name.fname, s[i].name.lname);
        for (int j = 0; j < SCORES; j++)
        {
            while (scanf("%f", &s[i].grade[j]) != 1)
            {
                while (getchar() != '\n')
                    continue;
                printf("Please enter a number: ");
            }
        }
    }
}

void cal_averages(struct student s[], int n)
{
    for (int i = 0; i < n; i++)
    {
        float sum = 0.0;
        for (int j = 0; j < SCORES; j++)
        {
            sum += s[i].grade[j];
        }
        s[i].average = sum / SCORES;
    }
}

void show_students(const struct student s[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("\n%s %s's three scores: ", s[i].name.fname, s[i].name.lname);
        for (int j = 0; j < SCORES; j++)
        {
            printf("%f ", s[i].grade[j]);
        }
        printf("\nAverage grade: %f\n", s[i].average);
    }
}

void show_averages(const struct student s[], int n)
{
    float total = 0.0;

    for (int i = 0; i < n; i++)
    {
        total += s[i].average;
    }
    printf("\nClass average grade: %f\n", total / n);
}

运行结果:

在这里插入图片描述

6. 垒球队

一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:

4 Jessie Joybat 5 2 1 1

第1项是球员号,为方便起见,其范围是0~18。第2项是球员的名。第3项是球员的姓。名和姓都是一个单词。第4项是官方统计的球员上场次数。接着3项分别是击中数、走垒数和打点(RBI)。

文件可能包含多场比赛的数据,所以同一位球员可能有多行数据,而且同一位球员的多行数据之间可能有其他球员的数据。编写一个程序,把数据储存到一个结构数组中。该结构中的成员要分别表示球员的名、姓、上场次数、击中数、走垒数、打点和安打率(稍后计算)。可以使用球员号作为数组的索引。该程序要读到文件结尾,并统计每位球员的各项累计总和。

世界棒球统计与之相关。例如,一次走垒和触垒中的失误不计入上场次数,但是可能产生一个RBI。但是该程序要做的是像下面描述的一样读取和处理数据文件,不会关心数据的实际含义。

要实现这些功能,最简单的方法是把结构的内容都初始化为零,把文件中的数据读入临时变量中, 然后将其加入相应的结构中。程序读完文件后,应计算每位球员的安打率,并把计算结果储存到结构的相应成员中。计算安打率是用球员的累计击中数除以上场累计次数。这是一个浮点数计算。最后,程序结合整个球队的统计数据,一行显示一位球员的累计数据。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 19

typedef struct
{
    int id;          // 球员的编号
    char fname[LEN]; // 球员的名;
    char lname[LEN]; // 球员的姓;
    int stage_num;   // 球员的上场次数;
    int hit_num;     // 球员的击中数;
    int base_num;    // 球员的走垒数;
    int rbi;         // 球员的打点;
    double hit_rate; // 球员的安打率;
} TEAM;

TEAM players[LEN];

void print_data(FILE *fp); // 打印文件信息
int read_data(TEAM players[], int n, FILE *fp);
void cal_hit_rate(TEAM players[], int n);
void show_player(TEAM players[], int n);

int main()
{
    FILE *fp;

    if ((fp = fopen("data.txt", "r")) == NULL)
    {
        fprintf(stderr, "Can't open file data.txt.\n");
        exit(EXIT_FAILURE);
    }
    // show_player(players, LEN);
    print_data(fp);
    rewind(fp); // 定位到文件开始处

    int count_player = read_data(players, LEN, fp); // 统计文件中不同球员的数量
    printf("There are %d players.\n", count_player);
    cal_hit_rate(players, LEN);
    show_player(players, LEN);
    if (fclose(fp) != 0)
    {
        fprintf(stderr, "Can't close file data.txt.\n");
    }

    return 0;
}

void print_data(FILE *fp)
{
    int get_id, beat, time, walk, RBI; // 获取每行对应的信息
    char name[LEN];
    char surname[LEN];

    printf("file content:\n");
    while (fscanf(fp, "%d %18s %18s %d %d %d %d", &get_id, name, surname, &time, &beat, &walk, &RBI) == 7 && !feof(fp))
    {
        printf("%d %s %s %d %d %d %d\n", get_id, name, surname, time, beat, walk, RBI); // 打印文件数据
    }
    printf("%d %s %s %d %d %d %d\n", get_id, name, surname, time, beat, walk, RBI); // 打印最后一行文件数据
}

int read_data(TEAM players[], int n, FILE *fp)
{
    int count = 0;
    char fname[LEN], lname[LEN];
    int m, stage_num, hit_num, base_num, rbi;

    while (fscanf(fp, "%d %18s %18s %d %d %d %d",
                  &m, fname, lname, &stage_num, &hit_num, &base_num, &rbi) == 7 &&
           !feof(fp) && count < n)
    {
        if (players[m].stage_num == 0) // 球员信息为空则累计球员数量, 防止超出人数限制19人
        {
            count++;
        }
        strcpy(players[m].fname, fname);
        strcpy(players[m].lname, lname);
        players[m].id = m;
        players[m].stage_num += stage_num;
        players[m].hit_num += hit_num;
        players[m].base_num += base_num;
        players[m].rbi += rbi;
    }
    // 处理最后一行数据
    strcpy(players[m].fname, fname);
    strcpy(players[m].lname, lname);
    players[m].id = m;
    players[m].stage_num += stage_num;
    players[m].hit_num += hit_num;
    players[m].base_num += base_num;
    players[m].rbi += rbi;
    return count;
}

void cal_hit_rate(TEAM players[], int n)
{
    for (int i = 0; i < n; i++)
    {
        players[i].hit_rate = 1.0 * players[i].hit_num / players[i].stage_num;
    }
}

void show_player(TEAM players[], int n)
{
    if (n == 0)
    {
        printf("No data!\n");
        return;
    }
    printf("Data for all players:\n");
    printf("Id   First_name   Last_name   Stage   Hit_rate   Base_num   RBI   Hit_rate\n");
    for (int i = 0; i < n; i++)
    {
        if (players[i].stage_num)
        {
            printf("%-4d %-12s %-10s %5d %7d %11d %8d %8.2f\n",
                   players[i].id, players[i].fname, players[i].lname,
                   players[i].stage_num, players[i].hit_num, players[i].base_num,
                   players[i].rbi, players[i].hit_rate);
        }
    }
}

data.txt:

18 Jessie Joybat 5 2 1 1
3 Jee Jot 6 3 2 1
6 Zhang san 6 3 2 1
1 Lily Neo 10 3 6 2
18 Jessie Joybat 5 2 1 1

运行结果:

在这里插入图片描述

另一种写法,使用了临时变量,最后还统计了所有球员的信息:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>

#define LEN 19
#define SIZE 31

struct athlete
{
    int index;        // 球员号码
    char lname[SIZE]; // 名
    char fname[SIZE]; // 姓
    int play_times;   // 上场次数
    int hit_numbers;  // 击中数
    int base_numbers; // 走垒数
    int rbi;          // 跑点数
    double hit_rate;  // 安打率
};

// 初始化结构数组
void init_athletes(struct athlete *, int);
// 计算每个球员的安打率
void cal_hit_rate(struct athlete *, int);
// 显示每个球员的累计数据
void show(struct athlete *, int);
// 对整个时期显示一行综合统计数据
void show_statistical_data(struct athlete *, int);

int main()
{
    struct athlete athletes[LEN];
    struct athlete temp; // 临时结构
    FILE *fp;
    char file[SIZE];
    int index;

    init_athletes(athletes, LEN);
    // 读取文本文件
    puts("请输入要读取的文本文件:");
    gets(file);
    if ((fp = fopen(file, "r")) == NULL)
    {
        fprintf(stderr, "不能打开文件%s\n", file);
        exit(EXIT_FAILURE);
    }
    // 把文本文件的数据存储到一个结构数组中
    while (fscanf(fp, "%d %s %s %d %d %d %d", &index, temp.fname, temp.lname,
                  &temp.play_times, &temp.hit_numbers, &temp.base_numbers, &temp.rbi) == 7)
    {
        if (strcmp(athletes[index].fname, temp.fname) != 0)
            strcpy(athletes[index].fname, temp.fname);
        if (strcmp(athletes[index].lname, temp.lname) != 0)
            strcpy(athletes[index].lname, temp.lname);
        athletes[index].play_times += temp.play_times;
        athletes[index].hit_numbers += temp.hit_numbers;
        athletes[index].base_numbers += temp.base_numbers;
        athletes[index].rbi += temp.rbi;
    }
    cal_hit_rate(athletes, LEN);
    show(athletes, LEN);
    show_statistical_data(athletes, LEN);

    system("pause");
    return 0;
}

void init_athletes(struct athlete *ath, int n)
{
    for (int i = 0; i < n; i++)
    {
        ath[i].index = i;
        strcpy(ath[i].lname, "");
        strcpy(ath[i].fname, "");
        ath[i].play_times = 0;
        ath[i].hit_numbers = 0;
        ath[i].base_numbers = 0;
        ath[i].rbi = 0;
        ath[i].hit_rate = 0.0;
    }
}

void cal_hit_rate(struct athlete *ath, int n)
{
    for (int i = 0; i < n; i++)
        ath[i].hit_rate = (double)ath[i].hit_numbers / ath[i].play_times;
}

void show(struct athlete *ath, int n)
{
    for (int i = 0; i < n; i++)
    {
        if (ath[i].play_times > 0) // 只打印上过场的球员的信息
        {
            printf("球员%s %s的累计数据为:\n", ath[i].fname, ath[i].lname);
            printf("上场次数:%d\n", ath[i].play_times);
            printf("击中数:%d\n", ath[i].hit_numbers);
            printf("走垒数:%d\n", ath[i].base_numbers);
            printf("跑点数:%d\n", ath[i].rbi);
            printf("安打率:%.2f%%\n", ath[i].hit_rate * 100);
            if (i < 18)
                printf("********************************\n");
        }
    }
}

void show_statistical_data(struct athlete *ath, int n)
{
    struct athlete temp = {0, "", "", 0, 0, 0, 0, 0.0};

    for (int i = 0; i < n; i++)
    {
        temp.play_times += ath[i].play_times;
        temp.hit_numbers += ath[i].hit_numbers;
        temp.base_numbers += ath[i].base_numbers;
        temp.rbi += ath[i].rbi;
    }
    printf("**********************综合统计数据*******************************\n");
    printf("所有球员的上场次数总和为:%d\n", temp.play_times);
    printf("击中数总和为:%d\n", temp.hit_numbers);
    printf("走垒数总和为:%d\n", temp.base_numbers);
    printf("跑点数总和为:%d\n", temp.rbi);
    printf("平均安打率为:%.2f%%\n", (double)temp.hit_numbers / temp.play_times * 100);
}

7. book记录

修改程序清单14.14,从文件中读取每条记录并显示出来,允许用户删除记录或修改记录的内容。如果删除记录,把空出来的空间留给下一个要读入的记录。要修改现有的文件内容,必须用" r+b"模式,而不是"a+b"模式。而且,必须更加注意定位文件指针,防止新加入的记录覆盖现有记录。最简单的方法是改动储存在内存中的所有数据,然后再把最后的信息写入文件。跟踪的一个 方法是在book结构中添加一个成员表示是否该项被删除。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10
#define CONTINUE 0
#define DONE 1

struct book
{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

struct pack
{
    struct book books;
    bool canceled;
};

char *s_gets(char *st, int n);
int get_first(const char *str);
int get_books(struct pack *pb);
void update(struct pack *item);
void eatline(void);

int main(void)
{
    struct pack library[MAXBKS];
    int count = 0;
    int deleted = 0;
    int index, filecount, open;
    FILE *pbooks;
    int size = sizeof(struct book);

    if ((pbooks = fopen("book.dat", "r+b")) != NULL)
    {
        while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1)
        {
            if (count == 0)
            {
                puts("Current contents of book.dat:");
            }
            printf("%s by %s: $%.2f\n", library[count].books.title,
                   library[count].books.author, library[count].books.value);
            printf("Do you want to change or delete this entry(y/n)?\n");
            printf("Please you enter to choose: ");
            if (get_first("yn") == 'y')
            {
                printf("Enter c to change, d to delete entry: ");
                if (get_first("cd") == 'd')
                {
                    library[count].canceled = true; // 作为删除的标记;
                    deleted++;
                    puts("Flag marked for deletion(The space for the next book).");
                }
                else
                {
                    update(&library[count]); // 修改原书籍的内容;
                }
            }
            count++;
        }
        if (fclose(pbooks) != 0)
        {
            fprintf(stderr, "Error in closing file.\n");
        }
    }
    filecount = count - deleted; // 不用删除的书籍数量;
    if (count == MAXBKS)
    {
        fputs("The book.dat file is full.", stderr);
        exit(EXIT_FAILURE);
    }

    if (deleted > 0)
    {
        printf("If you delete some books, you should enter books to replace.\n");
    }
    puts("Please add new book titles.");
    puts("Press [enter] at the start of a line to stop.");
    open = 0;
    while (filecount < MAXBKS)
    {
        if (filecount < count) // 删除书的循环次数,无法直接删除,只能用新书替换;
        {
            while (library[open].canceled == false)
            {
                open++; // 跳转到要删除的书的位置处;
            }
            if (get_books(&library[open]) == DONE)
            {
                break; // 若未输入新书覆盖原有书籍则循环终止;
            }
        }
        else if (get_books(&library[filecount]) == DONE)
        {
            break; // 添加新的书籍;
        }
        filecount++;
        if (filecount < MAXBKS)
        {
            puts("Enter the next book title.");
        }
    }

    puts("Here is the list of your books:\n");
    for (index = 0; index < filecount; index++)
    {
        if (library[index].canceled == false)
        {
            printf("%s by %s: $%.2f\n", library[index].books.title,
                   library[index].books.author, library[index].books.value);
        }
    }
    if ((pbooks = fopen("book.dat", "wb")) == NULL)
    {
        fputs("Can't open book.dat file for output.\n", stderr);
        exit(EXIT_FAILURE);
    }
    for (index = 0; index < filecount; index++)
    {
        if (library[index].canceled == false)
        {
            fwrite(&(library[index].books), size, 1, pbooks); // 直接修改原文本内容;
        }
    }
    if (fclose(pbooks) != 0)
    {
        fprintf(stderr, "Error in closing file.\n");
    }
    puts("Bye.\n");

    system("pause");
    return 0;
}

int get_first(const char *str) // 获取输入选择的函数;
{
    int ch;

    ch = tolower(getchar());
    while (strchr(str, ch) == NULL)
    {
        printf("Invalid data! Please enter again: ");
        eatline();
        ch = tolower(getchar());
    }
    eatline();

    return ch;
}

int get_books(struct pack *pb) // 保存用户输入的书籍的数据;
{
    int status = CONTINUE;

    if (s_gets(pb->books.title, MAXTITL) == NULL || pb->books.title[0] == '\0')
    {
        status = DONE; // 若是输入EOF或换行符则改变status的值并将其返回;
    }
    else
    {
        printf("Now enter the author.\n");
        s_gets(pb->books.author, MAXAUTL);
        printf("Now enter the value.\n");
        while (scanf("%f", &pb->books.value) != 1)
        {
            eatline();
            puts("Please enter a valid value.\n");
        }
        eatline();
        pb->canceled = false;
    }
    return status;
}

void update(struct pack *item)
{
    int ch;
    struct book copy;

    copy = item->books; // 保存原书的内容以便修改;
    puts("============================================");
    puts("t) modify title a) modify author");
    puts("v) modify value s) quit and save changes");
    puts("q) quit and ignore changes");
    puts("============================================");
    printf("Please you enter to choose: ");
    while ((ch = get_first("tavsq")) != 's' && ch != 'q')
    {
        switch (ch)
        {
        case 't':
        {
            printf("Please enter new title: ");
            s_gets(copy.title, MAXTITL);
            break;
        }
        case 'a':
        {
            printf("Please enter new author: ");
            s_gets(copy.author, MAXAUTL);
            break;
        }
        case 'v':
        {
            printf("Please enter new value: ");
            while (scanf("%f", &copy.value) != 1)
            {
                eatline();
                puts("Please enter a valid value: ");
            }
            eatline();
            break;
        }
        }
        puts("============================================");
        puts("t) modify title a) modify author");
        puts("v) modify value s) quit, saving changes");
        puts("q) quit, ignore changes");
        puts("============================================");
        printf("You can choose again: "); // 输入q退出程序且不改变原书的内容;
    }
    if (ch == 's')
    {
        item->books = copy; // 修改原书的内容;
    }
    return;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void eatline(void)
{
    while (getchar() != '\n')
        continue;
    return;
}

运行结果:

在这里插入图片描述

另一段代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10

struct book
{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
struct pack
{
    struct book book;
    bool delete_me;
};
// 删除或修改该记录的选择
int getlet(const char *);
// 修改该记录
void update(struct pack *);
// 从键盘获得输入
char *s_gets(char *, int);

int getbook(struct pack *);

int main(void)
{
    struct pack library[MAXBKS];
    int count = 0;
    int deleted = 0;
    int index, filecount, open;
    FILE *pbooks;
    int size = sizeof(struct book);

    if ((pbooks = fopen("book.dat", "r")) != NULL)
    {
        while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1)
        {
            if (count == 0)
                puts("Current contents of book.dat: ");
            printf("%s by %s: $%.2f\n", library[count].book.title, library[count].book.author, library[count].book.value);
            printf("Do you wish to change or delete this entry?<y/n> ");
            if (getlet("yn") == 'y')
            {
                printf("Enter c to change, d to delete this entry.<c/d> ");
                if (getlet("cd") == 'd') // 删除该记录(并不立即实现该功能)
                {
                    library[count].delete_me = true;
                    deleted++;
                    puts("Entry marked for deletion.");
                }
                else
                    update(&library[count]); // 修改该记录(修改要比删除简单)
            }
            count++;
        }
        fclose(pbooks);
    }

    filecount = count - deleted;
    if (count == MAXBKS)
    {
        fputs("The book.dat file is full.", stderr);
        exit(1);
    }
    puts("Please add new book titles.");
    puts("Press [enter] at the start of a line to stop.");
    open = 0;
    while (filecount < MAXBKS)
    {
        if (filecount < count)
        {
            while (library[open].delete_me == false)
                open++;
            if (getbook(&library[open]) == 1)
                break;
        }
        else if (getbook(&library[filecount]) == 1)
            break;
        filecount++;
        if (filecount < MAXBKS)
            puts("Enter the new book title.");
    }
    puts("Here is the list of your books: ");
    for (index = 0; index < filecount; index++) // 此处应该为count
        if (library[index].delete_me == false)
            printf("%s by %s: $%.2f\n", library[index].book.title, library[index].book.author, library[index].book.value);
    if ((pbooks = fopen("book.dat", "w")) == NULL)
    {
        puts("Can't open book.dat file for output.");
        exit(2);
    }
    for (index = 0; index < filecount; index++) // 此处应该为count
        if (library[index].delete_me == false)
            fwrite(&(library[index].book), size, 1, pbooks);
    puts("Bye.\n");
    fclose(pbooks);

    system("pause");
    return 0;
}
int getlet(const char *s)
{
    char c;

    c = getchar();
    while (strchr(s, c) == NULL)
    {
        printf("Enter the characters in the list %s\n", s);
        while (getchar() != '\n')
            continue;
        c = getchar();
    }
    while (getchar() != '\n')
        continue;
    return c;
}
int getbook(struct pack *item)
{
    int status = 0;

    if (s_gets(item->book.title, MAXTITL) == NULL || item->book.title[0] == '\0')
        status = 1;
    else
    {
        printf("Now enter the author: ");
        s_gets(item->book.author, MAXAUTL);
        printf("Now enter the value: ");
        while (scanf("%f", &item->book.value) != 1)
        {
            puts("Please use numeric input");
            scanf("%*s");
        }
        while (getchar() != '\n')
            continue;
        item->delete_me = false;
    }
    return status;
}
void update(struct pack *item)
{
    struct book copy;
    char c;

    copy = item->book;
    puts("Enter the letter that indicates your choice: ");
    puts("t) modify title       a) modify author");
    puts("v) modify value       s) quit, saving changes");
    puts("q) quit, ignore changes");
    while ((c = getlet("tavsq")) != 's' && c != 'q')
    {
        switch (c)
        {
        case 't':
            puts("Enter new title: ");
            s_gets(copy.title, MAXTITL);
            break;
        case 'a':
            puts("Enter new author: ");
            s_gets(copy.author, MAXAUTL);
            break;
        case 'v':
            puts("Enter new value: ");
            while (scanf("%f", &copy.value) != 1)
            {
                puts("Enter a numeric value: ");
                scanf("%*s"); // *放在%和说明符之间,使得函数跳过相应的输入项目
            }
            while (getchar() != '\n')
                continue;
            break;
        }
        puts("t) modify title       a) modify author");
        puts("v) modify value       s) quit, saving changes");
        puts("q) quit, ignore changes");
    }
    if (c == 's')
        item->book = copy;
}
char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(ret_val, '\n');
        if (find)
            *find = '\0';
        else
            while (getchar() != '\n')
                continue;
    }
    return ret_val;
}

运行结果:

Current contents of book.dat:
Deadly Farce by Dudley Forse: $15.99
Do you wish to change or delete this entry?<y/n> y
Enter c to change, d to delete this entry.<c/d> d
Entry marked for deletion.
Deadly Farce by Dudley Forse: $15.99
Do you wish to change or delete this entry?<y/n> y
Enter c to change, d to delete this entry.<c/d> c
Enter the letter that indicates your choice:
t) modify title       a) modify author
v) modify value       s) quit, saving changes
q) quit, ignore changes
a
Enter new author:
Yan Congcong
t) modify title       a) modify author
v) modify value       s) quit, saving changes
q) quit, ignore changes
v
Enter new value:
25.98
t) modify title       a) modify author
v) modify value       s) quit, saving changes
q) quit, ignore changes
s
Please add new book titles.
Press [enter] at the start of a line to stop.
C++ Primer Plus
Now enter the author: Xiye
Now enter the value: 60.00
Enter the new book title.

Here is the list of your books:
C++ Primer Plus by Xiye: $60.00
Deadly Farce by Yan Congcong: $25.98
Bye.

请按任意键继续. . .

8. 巨人航空公司

巨人航空公司的机群由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)。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LEN 14
#define EMPTY 0
#define TAKEN 1
#define CONTINUE 1
#define DONE 0
#define SEATS 12
#define CHOICES 6

struct planestats
{
    int seat_id;
    int status;
    char last[LEN];
    char first[LEN];
};

int getmenu(void);
int getlet(const char *);
int openings(const struct planestats *, int);
void show_empties(const struct planestats *, int);
void makelist(const struct planestats *, char *, int);
void list_assgin(struct planestats *[], int);
void sort(struct planestats *[], int);
void assign_seat(struct planestats *, int);
void delete_seat(struct planestats *, int);
void show_seat(const struct planestats *, int);
char *s_gets(char *, int);

int main()
{
    struct planestats plane_1[SEATS], *ps[SEATS];
    int choice;
    int i;
    FILE *fp;
    size_t size = sizeof(struct planestats);

    for (i = 0; i < SEATS; i++)
        ps[i] = &plane_1[i];
    /* 若文件air.dat打不开,则初始化结构数组 */
    if ((fp = fopen("air.dat", "rb")) == NULL)
    {
        for (i = 0; i < SEATS; i++)
        {
            plane_1[i].status = EMPTY;
            plane_1[i].seat_id = i + 1; // 编号从1开始
        }
    }
    else
    {
        fread(plane_1, size, SEATS, fp); // 一次写入结构数组plane_1中
        fclose(fp);
    }
    while ((choice = getmenu()) != 'q')
    {
        switch (choice)
        {
        case 'o':
            printf("There are %d empty seats.\n",
                   openings(plane_1, SEATS));
            break;
        case 'e':
            show_empties(plane_1, SEATS);
            break;
        case 'l':
            list_assgin(ps, SEATS);
            break;
        case 'a':
            assign_seat(plane_1, SEATS);
            break;
        case 'd':
            delete_seat(plane_1, SEATS);
            break;
        }
    }
    if ((fp = fopen("air.dat", "wb")) == NULL)
        puts("Can't save data to file.");
    else
    {
        fwrite(plane_1, size, SEATS, fp); // 将结构数组一次写入到文件中
        fclose(fp);
    }
    puts("Bye from Colossus Airlines!");

    system("pause");
    return 0;
}
int getmenu(void)
{
    const char *descript[CHOICES] = {
        "Show number of empty seats",
        "Show list of empty seats",
        "Show alphabetical list of seats",
        "Assign a customer to a seat assignment",
        "Delete a seat assignment",
        "Quit"};
    const char labels[CHOICES + 1] = "oeladq";
    int i;

    puts("To choose a function, enter its letter label: ");
    for (i = 0; i < CHOICES; i++)
        printf("%c) %s\n", labels[i], descript[i]);
    return getlet(labels);
}
int getlet(const char *s)
{
    char c;

    c = getchar();
    while (strchr(s, c) == NULL)
    {
        printf("Enter a character in the list %s\n", s);
        while (getchar() != '\n')
            continue;
        c = getchar();
    }
    while (getchar() != '\n')
        continue;
    return c;
}
int openings(const struct planestats *pl, int n)
{
    int count = 0;
    int seat;

    for (seat = 0; seat < n; seat++)
        if (pl[seat].status == EMPTY)
            count++;
    return count;
}
void show_empties(const struct planestats *pl, int n)
{
    char seating[3 * SEATS];

    if (openings(pl, n) == 0)
        printf("All seats are assigned\n");
    else
    {
        puts("The following seats are available: ");
        makelist(pl, seating, EMPTY);
        puts(seating);
    }
}
void makelist(const struct planestats *pl, char *str, int kind)
{
    int seat;
    char temp[LEN];

    str[0] = '\0';
    for (seat = 0; seat < SEATS; seat++)
        if (pl[seat].status == kind)
        {
            sprintf(temp, " %d", pl[seat].seat_id); // 把格式化输出写到指定的字符串中
            strcat(str, temp);
        }
}
void list_assgin(struct planestats *ps[], int n)
{
    int i;

    if (openings(*ps, n) == n)
        puts("All seats are empty.");
    else
    {
        sort(ps, n);
        for (i = 0; i < n; i++)
            if (ps[i]->status == TAKEN)
                printf("Seat %d: %s, %s\n", ps[i]->seat_id, ps[i]->last, ps[i]->first);
    }
}
void sort(struct planestats *array[], int n)
{
    int top, search;
    struct planestats *temp;

    for (top = 0; top < n - 1; top++)
        for (search = top + 1; search < n; search++)
            if (strcmp(array[top]->last, array[search]->last) > 0)
            {
                temp = array[top];
                array[top] = array[search];
                array[search] = temp;
            }
}
void assign_seat(struct planestats *pl, int n)
{
    char list[3 * SEATS];
    int seat, loop;

    if (openings(pl, n) == 0)
        puts("All seats are assigned.");
    else
    {
        makelist(pl, list, EMPTY);
        puts("Which seat do you want? Choose from the list: ");
        puts(list);
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                scanf("%*s");
                puts("Enter a number from the list: ");
                puts(list);
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == TAKEN)
            {
                puts("Enter a number from the list: ");
                puts(list);
                loop = CONTINUE;
            }
            else
                loop = DONE;

        } while (loop);
        while (getchar() != '\n')
            continue;
        puts("Enter the first name: ");
        s_gets(pl[seat - 1].first, LEN);
        puts("Enter the last name: ");
        s_gets(pl[seat - 1].last, LEN);
        printf("%s %s assigned to seat %d.\n", pl[seat - 1].first, pl[seat - 1].last, seat);
        printf("Enter a to accept assignment, c to cancal it.\n");
        if (getlet("ac") == 'a')
        {
            pl[seat - 1].status = TAKEN;
            pl[seat - 1].seat_id = seat; // 也得把座位编号给填上去吧!!!
            puts("Passenger assigned to seat.");
        }
        else
            puts("Passenger not assigned.");
    }
}
void delete_seat(struct planestats *pl, int n)
{
    char list[3 * SEATS];
    int seat, loop;

    if (openings(pl, n) == SEATS)
        puts("All seats already are empty.");
    else
    {
        show_seat(pl, n);
        makelist(pl, list, TAKEN);
        puts("Enter the number of the seat to be cancelled: ");
        puts(list);
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                scanf("%*s");
                puts("Enter a number from the list: ");
                puts(list);
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == EMPTY)
            {
                puts("Enter a number from the list: ");
                puts(list);
                loop = CONTINUE;
            }
            else
                loop = DONE;
        } while (loop);
        while (getchar() != '\n')
            continue;
        printf("%s %s to be cancelled for seat.\n", pl[seat - 1].first, pl[seat - 1].last, seat);
        puts("Enter d to delete assignment, a to abort.");
        if (getlet("da") == 'd')
        {
            pl[seat - 1].status = EMPTY;
            pl[seat - 1].seat_id = seat; // 也得把座位编号给填上去吧!!!
            puts("Passenger dropped.");
        }
        else
            puts("Passenger retained.");
    }
}
void show_seat(const struct planestats *pl, int n)
{
    for (int i = 0; i < n; i++)
        if (pl[i].status == TAKEN)
            printf("Seat %d: %s %s\n", pl[i].seat_id, pl[i].last, pl[i].first);
}

char *s_gets(char *s, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(s, n, stdin);
    if (ret_val)
    {
        find = strchr(ret_val, '\n');
        if (find)
            *find = '\0';
        else
            while (getchar() != '\n')
                continue;
    }
    return ret_val;
}

运行结果:

C:\Users\81228\Documents\Program\VScode C Program>cd chapter14/14.8

C:\Users\81228\Documents\Program\VScode C Program\chapter14\14.8>14.8
To choose a function, enter its letter label: 
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
o
There are 12 empty seats.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
e
The following seats are available: 
 1 2 3 4 5 6 7 8 9 10 11 12
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
l
All seats are empty.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
a
Which seat do you want? Choose from the list: 
 1 2 3 4 5 6 7 8 9 10 11 12
1
Enter the first name: 
Xi
Enter the last name: 
ye
Xi ye assigned to seat 1.
Enter a to accept assignment, c to cancal it.
a
Passenger assigned to seat.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
o
There are 11 empty seats.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
e
The following seats are available: 
 2 3 4 5 6 7 8 9 10 11 12
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
l
Seat 1: ye, Xi
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
d
Seat 1: ye Xi
Enter the number of the seat to be cancelled:
 1
1
Xi ye to be cancelled for seat.
Enter d to delete assignment, a to abort.
d
Passenger dropped.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
o
There are 12 empty seats.
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
e
The following seats are available: 
 1 2 3 4 5 6 7 8 9 10 11 12
To choose a function, enter its letter label:
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
l
To choose a function, enter its letter label: 
o) Show number of empty seats
e) Show list of empty seats
l) Show alphabetical list of seats
a) Assign a customer to a seat assignment
d) Delete a seat assignment
q) Quit
q
Bye from Colossus Airlines!
请按任意键继续. . .

另一个可以运行的程序:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define LEN 14
#define SEATS 12

typedef struct
{
    int seat_id;
    bool status;
    char last[LEN];
    char first[LEN];
} plane;

int getmenu(void);
int get_first(void);
int openings(const plane pl[], int n);
void show_empty_seats(const plane pl[], int n);
void list_assign(plane *ps[], int n);
void assign_seat(plane pl[], int n);
void delete_seat(plane pl[], int n);
void show_seats(const plane pl[]);
void sort(plane *array[], int n);
void makelist(const plane pl[], char *str, int kind);
char *s_gets(char *st, int n);
void eatline(void);

int main(void)
{
    int i, choice;
    plane plane_seat[SEATS];
    plane *ps[SEATS];

    for (i = 0; i < SEATS; i++)
    {
        ps[i] = &plane_seat[i];
    }
    for (i = 0; i < SEATS; i++)
    {
        plane_seat[i].status = false;
        plane_seat[i].seat_id = i + 1;
    }
    while ((choice = getmenu()) != 'f')
    {
        switch (choice)
        {
        case 'a':
        {
            printf("There are %d empty seats.\n", openings(plane_seat, SEATS));
            break;
        }
        case 'b':
        {
            show_empty_seats(plane_seat, SEATS);
            break;
        }
        case 'c':
        {
            list_assign(ps, SEATS);
            break;
        }
        case 'd':
        {
            assign_seat(plane_seat, SEATS);
            break;
        }
        case 'e':
        {
            delete_seat(plane_seat, SEATS);
            break;
        }
        }
        putchar('\n');
    }
    puts("Bye from Colossus Airlines!");

    return 0;
}

int getmenu(void)
{
    int ch;

    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 seat");
    puts("d) Assign a customer to a seat");
    puts("e) Delete a seat assignment");
    puts("f) Quit");
    printf("Please you enter to choose: ");
    while (ch = get_first(), NULL == strchr("abcdef", ch))
    {
        printf("Invalid data! Please you choose again: ");
    }
    return ch;
}

int get_first(void)
{
    int ch;

    do
    {
        ch = tolower(getchar());
    } while (isspace(ch));
    eatline();

    return ch;
}

int openings(const plane pl[], int n) // 显示空座位的数量;
{
    int seat;
    int count = 0;

    for (seat = 0; seat < n; seat++)
    {
        if (pl[seat].status == false)
        {
            count++;
        }
    }
    return count;
}

void list_assign(plane *ps[], int n) // 显示按照字母序列排序后的座位表;
{
    int i;

    if (openings(*ps, n) == SEATS)
    {
        puts("All seats are empty.");
    }
    else
    {
        sort(ps, n);
        for (i = 0; i < SEATS; i++)
        {
            if (ps[i]->status == true)
            {
                printf("Seat %d: %s, %s\n", ps[i]->seat_id, ps[i]->last, ps[i]->first);
            }
        }
    }
    return;
}

void show_seats(const plane pl[]) // 显示已分配的座位;
{
    int i;

    puts("Seats currently taken:");
    for (i = 0; i < SEATS; i++)
    {
        if (pl[i].status == true)
        {
            printf("Seat %d: %s, %s\n", pl[i].seat_id, pl[i].last, pl[i].first);
        }
    }
    return;
}

void sort(plane *array[], int n) // 按照ASCII码进行座位排序;
{
    int i, j;
    plane *temp;

    for (i = 0; i < n - 1; i++)
    {
        for (j = i + 1; j < n; j++)
        {
            if (strcmp(array[j]->last, array[i]->last) < 0)
            {
                temp = array[j];
                array[j] = array[i];
                array[i] = temp;
            }
        }
    }
    return;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void eatline(void)
{
    while (getchar() != '\n')
        continue;
    return;
}

void show_empty_seats(const plane pl[], int n) // 显示空座位的信息;
{
    char seating[3 * SEATS];

    if (openings(pl, n) == 0)
    {
        puts("All seats are assigned");
    }
    else
    {
        makelist(pl, seating, false);
        printf("The following seats are available: ");
        puts(seating);
    }
    return;
}

void makelist(const plane pl[], char *str, int kind) // 为分配和删除座位提供当前处理的座位数;
{
    int seat;
    char temp[LEN];

    *str = '\0'; // 清空str中的内容;
    for (seat = 0; seat < SEATS; seat++)
    {
        if (pl[seat].status == kind)
        {
            sprintf(temp, "%d ", pl[seat].seat_id);
            strcat(str, temp);
        }
    }
    return;
}

void assign_seat(plane pl[], int n) // 分配空余座位;
{
    int ch, seat, flag;
    char list[3 * SEATS];

    if (openings(pl, n) == false)
    {
        puts("All seats are assigned. Can't assign again!");
    }
    else
    {
        makelist(pl, list, false);
        printf("Available seats: %s\n", list);
        printf("Which seat do you want? Please you enter from the lists: ");
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                eatline();
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists: ");
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == true)
            {
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists: ");
                flag = 1;
            }
            else
            {
                flag = 0;
            }
        } while (1 == flag); // 本循环判断并处理用户的错误输入;

        eatline();
        puts("Enter first name:");
        s_gets(pl[seat - 1].first, LEN);
        puts("Enter last name:");
        s_gets(pl[seat - 1].last, LEN);
        printf("%s %s assigned to seat %d.\n", pl[seat - 1].first, pl[seat - 1].last, seat);

        printf("Enter a to accept assignment, c to cancel it: ");
        ch = get_first();
        while (strchr("ac", ch) == NULL)
        {
            printf("Please enter a or c: ");
            ch = get_first();
        }
        if (ch == 'a')
        {
            pl[seat - 1].status = true;
            puts("Passenger assigned to seat.");
        }
        else if (ch == 'c')
        {
            puts("Passenger not assigned.");
        }
    }
    return;
}

void delete_seat(plane pl[], int n) // 删除已分配的座位;
{
    int ch, seat, flag;
    char list[3 * SEATS];

    if (openings(pl, n) == SEATS)
    {
        puts("All seats already are empty. Can't delete!");
    }
    else
    {
        show_seats(pl);
        makelist(pl, list, true);
        printf("Enter the number of the seat to be deleted: ");
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                eatline();
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists:");
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == false)
            {
                printf("Seats: %s\n", list);
                printf("Enter a number from this list:");
                flag = 1;
            }
            else
            {
                flag = 0;
            }
        } while (1 == flag);

        eatline();
        printf("%s %s to be canceled for seat %d.\n", pl[seat - 1].first, pl[seat - 1].last, seat);
        printf("Enter d to delete assignment, a to abort: ");
        ch = get_first();
        while (strchr("da", ch) == NULL)
        {
            printf("Please enter d or a: ");
            ch = get_first();
        }
        if (ch == 'd')
        {
            pl[seat - 1].status = false;
            puts("Passenger dropped.");
        }
        else if (ch == 'a')
        {
            puts("Passenger retained.");
        }
    }
    return;
}

运行结果:

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: a
There are 12 empty seats.

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: b
The following seats are available: 1 2 3 4 5 6 7 8 9 10 11 12

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: c
All seats are empty.

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: d
Available seats: 1 2 3 4 5 6 7 8 9 10 11 12
Which seat do you want? Please you enter from the lists: 12
Enter first name:
Xi
Enter last name:
ye
Xi ye assigned to seat 12.
Enter a to accept assignment, c to cancel it: a
Passenger assigned to seat.

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: o
Invalid data! Please you choose again: a
There are 11 empty seats.

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: b
The following seats are available: 1 2 3 4 5 6 7 8 9 10 11

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: c
Seat 12: ye, Xi

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose: e
Seats currently taken:
Seat 12: ye, Xi
Enter the number of the seat to be deleted: 1
Seats: 12
Enter a number from this list:12
Xi ye to be canceled for seat 12.
Enter d to delete assignment, a to abort: d
Passenger dropped.

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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
Please you enter to choose:

9. 巨人航空公司2

巨人航空公司(编程练习8)需要另一架飞机(容量相同),每天飞4班(航班102、311、444 和519)。把程序扩展为可以处理4个航班。用一个顶层菜单提供航班选择和退出。选择一个特定 航班,就会出现和编程练习8类似的菜单。但是该菜单要添加一个新选项:确认座位分配。而且, 菜单中的退出是返回顶层菜单。每次显示都要指明当前正在处理的航班号。另外,座位分配显示 要指明确认状态。

代码:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define LEN 14
#define SEATS 12

typedef struct
{
    int seat_id;
    bool status;
    char last[LEN];
    char first[LEN];
} plane;

int getmenu(int choice);
int get_first(void);
int openings(const plane pl[], int n);
void show_empty_seats(const plane pl[], int n);
void list_assign(plane *ps[], int n);
void assign_seat(plane pl[], int n);
void delete_seat(plane pl[], int n);
void show_seats(const plane pl[]);
void sort(plane *array[], int n);
void makelist(const plane pl[], char *str, int kind);
char *s_gets(char *st, int n);
void eatline(void);
void airline(int choice, plane *pl, plane *ps[]);
void init(plane *pl, plane *ps[]);
int show_airline_menu(void);
void confirm_seat(const plane pl[]);

int main(void)
{
    int ch;
    plane airline_102[SEATS];
    plane airline_311[SEATS];
    plane airline_444[SEATS];
    plane airline_519[SEATS];
    plane *ps_102[SEATS];
    plane *ps_311[SEATS];
    plane *ps_444[SEATS];
    plane *ps_519[SEATS];

    init(airline_102, ps_102);
    init(airline_311, ps_311);
    init(airline_444, ps_444);
    init(airline_519, ps_519);
    while ((ch = show_airline_menu()) != 'q')
    {
        putchar('\n');
        switch (ch)
        {
        case 'a':
        {
            airline(ch, airline_102, ps_102);
            break;
        }
        case 'b':
        {
            airline(ch, airline_311, ps_311);
            break;
        }
        case 'c':
        {
            airline(ch, airline_444, ps_444);
            break;
        }
        case 'd':
        {
            airline(ch, airline_519, ps_519);
            break;
        }
        }
        putchar('\n');
    }
    puts("Bye from Colossus Airlines!");

    return 0;
}

void init(plane *pl, plane *ps[])
{
    int i;

    for (i = 0; i < SEATS; i++)
    {
        ps[i] = &pl[i];
    }
    for (i = 0; i < SEATS; i++)
    {
        pl[i].status = false;
        pl[i].seat_id = i + 1;
    }
    return;
}

int show_airline_menu(void)
{
    int ch;

    puts("There are some airlines for you to choose.");
    puts("a) Airline 102.");
    puts("b) Airline 311.");
    puts("c) Airline 444.");
    puts("d) Airline 519.");
    puts("q) Quit the program.");
    printf("Please you enter to choose: ");
    ch = get_first();
    while (strchr("abcdq", ch) == NULL)
    {
        printf("Please enter a, b, c, d or q: ");
        ch = get_first();
    }
    return ch;
}

void airline(int choice, plane *pl, plane *ps[])
{
    int ch;

    while ((ch = getmenu(choice)) != 'f')
    {
        switch (ch)
        {
        case 'a':
        {
            printf("There are %d empty seats.\n", openings(pl, SEATS));
            break;
        }
        case 'b':
        {
            show_empty_seats(pl, SEATS);
            break;
        }
        case 'c':
        {
            list_assign(ps, SEATS);
            break;
        }
        case 'd':
        {
            assign_seat(pl, SEATS);
            break;
        }
        case 'e':
        {
            delete_seat(pl, SEATS);
            break;
        }
        case 'g':
        {
            confirm_seat(pl);
            break;
        }
        }
        putchar('\n');
    }
    return;
}

int getmenu(int choice)
{
    int ch;

    if (choice == 'a')
    {
        printf("The airline 102 is being processed.\n");
    }
    else if (choice == 'b')
    {
        printf("The airline 311 is being processed.\n");
    }
    else if (choice == 'c')
    {
        printf("The airline 444 is being processed.\n");
    }
    else if (choice == 'd')
    {
        printf("The airline 519 is being processed.\n");
    }
    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 seat");
    puts("d) Assign a customer to a seat");
    puts("e) Delete a seat assignment");
    puts("f) Quit");
    puts("g) Confirm seat assignment");
    printf("Please you enter to choose: ");
    ch = get_first();
    while (strchr("abcdefg", ch) == NULL)
    {
        printf("Please enter a, b, c, d, e, f or g: ");
        ch = get_first();
    }
    return ch;
}

int get_first(void) //获取输入的第一个字符,丢弃剩余字符;
{
    int ch;

    do
    {
        ch = tolower(getchar());
    } while (isspace(ch));
    eatline();

    return ch;
}

int openings(const plane pl[], int n) //显示空座位的数量;
{
    int seat;
    int count = 0;

    for (seat = 0; seat < n; seat++)
    {
        if (pl[seat].status == false)
        {
            count++;
        }
    }
    return count;
}

void list_assign(plane *ps[], int n) //显示按照字母序列排序后的座位表;
{
    int i;

    if (openings(*ps, n) == SEATS)
    {
        puts("All seats are empty.");
    }
    else
    {
        sort(ps, n);
        for (i = 0; i < SEATS; i++)
        {
            if (ps[i]->status == true)
            {
                printf("Seat %d: %s, %s\n", ps[i]->seat_id, ps[i]->last, ps[i]->first);
            }
        }
    }
    return;
}

void show_seats(const plane pl[]) //显示已分配的座位;
{
    int i;

    puts("Seats currently taken:");
    for (i = 0; i < SEATS; i++)
    {
        if (pl[i].status == true)
        {
            printf("Seat %d: %s, %s\n", pl[i].seat_id, pl[i].last, pl[i].first);
        }
    }
    return;
}

void confirm_seat(const plane pl[]) //确认座位分配;
{
    int i;

    puts("Seats assignment lists:");
    for (i = 0; i < SEATS; i++)
    {
        if (pl[i].status == true)
        {
            printf("Seat %-2d: assigned.\n", pl[i].seat_id);
        }
        else
        {
            printf("Seat %-2d: unassigned.\n", pl[i].seat_id);
        }
    }
    return;
}

void sort(plane *array[], int n) //按照ASCII码进行座位排序;
{
    int i, j;
    plane *temp;

    for (i = 0; i < n - 1; i++)
    {
        for (j = i + 1; j < n; j++)
        {
            if (strcmp(array[j]->last, array[i]->last) < 0)
            {
                temp = array[j];
                array[j] = array[i];
                array[i] = temp;
            }
        }
    }
    return;
}

char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if (find)
        {
            *find = '\0';
        }
        else
        {
            while (getchar() != '\n')
                continue;
        }
    }
    return ret_val;
}

void eatline(void)
{
    while (getchar() != '\n')
        continue;
    return;
}

void show_empty_seats(const plane pl[], int n) //显示空座位的信息;
{
    char seating[3 * SEATS];

    if (openings(pl, n) == 0)
    {
        puts("All seats are assigned");
    }
    else
    {
        makelist(pl, seating, false);
        printf("The following seats are available: ");
        puts(seating);
    }
    return;
}

void makelist(const plane pl[], char *str, int kind) //为分配和删除座位提供当前处理的座位数;
{
    int seat;
    char temp[LEN];

    *str = '\0'; //清空str中的内容;
    for (seat = 0; seat < SEATS; seat++)
    {
        if (pl[seat].status == kind)
        {
            sprintf(temp, "%d ", pl[seat].seat_id);
            strcat(str, temp);
        }
    }
    return;
}

void assign_seat(plane pl[], int n) //分配空余座位;
{
    int ch, seat, flag;
    char list[3 * SEATS];

    if (openings(pl, n) == false)
    {
        puts("All seats are assigned. Can't assign again!");
    }
    else
    {
        makelist(pl, list, false);
        printf("Available seats: %s\n", list);
        printf("Which seat do you want? Please you enter from the lists: ");
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                eatline();
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists: ");
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == true)
            {
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists: ");
                flag = 1;
            }
            else
            {
                flag = 0;
            }
        } while (1 == flag); //本循环判断并处理用户的错误输入;

        eatline();
        puts("Enter first name:");
        s_gets(pl[seat - 1].first, LEN);
        puts("Enter last name:");
        s_gets(pl[seat - 1].last, LEN);
        printf("%s %s assigned to seat %d.\n", pl[seat - 1].first, pl[seat - 1].last, seat);

        printf("Enter a to accept assignment, c to cancel it: ");
        ch = get_first();
        while (strchr("ac", ch) == NULL)
        {
            printf("Please enter a or c: ");
            ch = get_first();
        }
        if (ch == 'a')
        {
            pl[seat - 1].status = true;
            puts("Passenger assigned to seat.");
        }
        else if (ch == 'c')
        {
            puts("Passenger not assigned.");
        }
    }
    return;
}

void delete_seat(plane pl[], int n) //删除已分配的座位;
{
    int ch, seat, flag;
    char list[3 * SEATS];

    if (openings(pl, n) == SEATS)
    {
        puts("All seats already are empty. Can't delete!");
    }
    else
    {
        show_seats(pl);
        makelist(pl, list, true);
        printf("Enter the number of the seat to be deleted: ");
        do
        {
            while (scanf("%d", &seat) != 1)
            {
                eatline();
                printf("Seats: %s\n", list);
                printf("Enter a number from the lists:");
            }
            if (seat < 1 || seat > SEATS || pl[seat - 1].status == false)
            {
                printf("Seats: %s\n", list);
                printf("Enter a number from this list:");
                flag = 1;
            }
            else
            {
                flag = 0;
            }
        } while (1 == flag);

        eatline();
        printf("%s %s to be canceled for seat %d.\n", pl[seat - 1].first, pl[seat - 1].last, seat);
        printf("Enter d to delete assignment, a to abort: ");
        ch = get_first();
        while (strchr("da", ch) == NULL)
        {
            printf("Please enter d or a: ");
            ch = get_first();
        }
        if (ch == 'd')
        {
            pl[seat - 1].status = false;
            puts("Passenger dropped.");
        }
        else if (ch == 'a')
        {
            puts("Passenger retained.");
        }
    }
    return;
}

运行结果:

There are some airlines for you to choose.
a) Airline 102.
b) Airline 311.
c) Airline 444.
d) Airline 519.
q) Quit the program.
Please you enter to choose: a

The airline 102 is being processed.
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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
g) Confirm seat assignment
Please you enter to choose: a
There are 12 empty seats.

The airline 102 is being processed.
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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
g) Confirm seat assignment
Please you enter to choose: d
Available seats: 1 2 3 4 5 6 7 8 9 10 11 12
Which seat do you want? Please you enter from the lists: 7
Enter first name:
Xi
Enter last name:
ye
Xi ye assigned to seat 7.
Enter a to accept assignment, c to cancel it: a
Passenger assigned to seat.

The airline 102 is being processed.
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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
g) Confirm seat assignment
Please you enter to choose: c
Seat 7: ye, Xi

The airline 102 is being processed.
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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
g) Confirm seat assignment
Please you enter to choose: g
Seats assignment lists:
Seat 1 : unassigned.
Seat 2 : unassigned.
Seat 3 : unassigned.
Seat 4 : unassigned.
Seat 5 : unassigned.
Seat 6 : unassigned.
Seat 7 : assigned.
Seat 8 : unassigned.
Seat 9 : unassigned.
Seat 10: unassigned.
Seat 11: unassigned.
Seat 12: unassigned.

The airline 102 is being processed.
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 seat
d) Assign a customer to a seat
e) Delete a seat assignment
f) Quit
g) Confirm seat assignment
Please you enter to choose: f

There are some airlines for you to choose.
a) Airline 102.
b) Airline 311.
c) Airline 444.
d) Airline 519.
q) Quit the program.
Please you enter to choose: q

10. 函数指针数组

编写一个程序,通过一个函数指针数组实现菜单。例如,选择菜单中的a,将激活由该数组第 1个元素指向的函数。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define NUM 4

double twice(double x) { return 2.0 * x; }
double half(double x) { return x / 2.0; }
double thrice(double x) { return 3.0 * x; }

void showmenu(void);

int main()
{
    double (*fp[NUM])(double) = {twice, half, thrice, sqrt};
    double val, ans;
    int choice;

    puts("Enter a number (negative to quit): ");
    while (scanf("%lf", &val) == 1 && val > 0)
    {
        showmenu();
        while (scanf("%d", &choice) == 1 && choice >= 0 && choice <= 3)
        {
            ans = (*fp[choice])(val); // ans = fp[choice](val);
            printf("answer = %.2f\n", ans);
            showmenu();
        }
        puts("Enter a number (negative to quit): ");
    }
    puts("Bye.");

    system("pause");
    return 0;
}

void showmenu(void)
{
    puts("Enter one of the following choices: ");
    puts("0) double the value            1) halve the value");
    puts("2) triple the value            3) squareroot the value");
    puts("4) next number");
}

运行结果:

在这里插入图片描述

11. transform()

编写一个名为transform()的函数,接受4个参数:内含double类型数据的源数组名、内含 double类型数据的目标数组名、一个表示数组元素个数的int 类型参数、函数名(或等价的函数指针)。transform()函数应把指定函数应用于源数组中的每个元素,并把返回值储存在目标数组 中。例如: transform(source, target, 100, sin); 该声明会把target[ 0]设置为sin( source[0]),等等,共有100个元素。在一个程序中调用transform()4次,以测试该函数。分别使用math.h函数库 中的两个函数以及自定义的两个函数作为参数。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define NUM 100

double twice(double x) { return 2.0 * x; }
double half(double x) { return x / 2.0; }
void init(double *arr, int n);
void transform(double *source, double *target, int n, double (*fp)(double));
void show(const double *arr, int n);

int main()
{
    double source[NUM];
    double target0[NUM];
    double target1[NUM];
    double target2[NUM];
    double target3[NUM];
    double (*fp[NUM])(double) = {twice, half, sqrt, sin};

    init(source, NUM);
    transform(source, target0, NUM, twice);
    transform(source, target1, NUM, half);
    transform(source, target2, NUM, sqrt);
    transform(source, target3, NUM, sin);
    puts("--------------------------target0数组--------------------------");
    show(target0, NUM);
    puts("--------------------------target1数组--------------------------");
    show(target1, NUM);
    puts("--------------------------target2数组--------------------------");
    show(target2, NUM);
    puts("--------------------------target3数组--------------------------");
    show(target3, NUM);
    puts("Bye.");

    system("pause");
    return 0;
}
void init(double *arr, int n)
{
    for (int i = 0; i < NUM; i++)
        arr[i] = i + 1;
}

void transform(double *source, double *target, int n, double (*fp)(double))
{
    for (int i = 0; i < n; i++)
        target[i] = (*fp)(source[i]);
}

void show(const double *arr, int n)
{
    int i;

    for (i = 0; i < n; i++)
    {
        printf("%7.2f", arr[i]);
        if (i % 10 == 9)
            putchar('\n');
    }
    if (i % 10 != 9)
        putchar('\n');
}

运行结果:

C:\Users\81228\Documents\Program\VScode C Program>cd chapter14      

C:\Users\81228\Documents\Program\VScode C Program\chapter14>14.11
--------------------------target0数组--------------------------
   2.00   4.00   6.00   8.00  10.00  12.00  14.00  16.00  18.00  20.00
  22.00  24.00  26.00  28.00  30.00  32.00  34.00  36.00  38.00  40.00
  42.00  44.00  46.00  48.00  50.00  52.00  54.00  56.00  58.00  60.00
  62.00  64.00  66.00  68.00  70.00  72.00  74.00  76.00  78.00  80.00
  82.00  84.00  86.00  88.00  90.00  92.00  94.00  96.00  98.00 100.00
 102.00 104.00 106.00 108.00 110.00 112.00 114.00 116.00 118.00 120.00
 122.00 124.00 126.00 128.00 130.00 132.00 134.00 136.00 138.00 140.00
 142.00 144.00 146.00 148.00 150.00 152.00 154.00 156.00 158.00 160.00
 162.00 164.00 166.00 168.00 170.00 172.00 174.00 176.00 178.00 180.00
 182.00 184.00 186.00 188.00 190.00 192.00 194.00 196.00 198.00 200.00

--------------------------target1数组--------------------------
   0.50   1.00   1.50   2.00   2.50   3.00   3.50   4.00   4.50   5.00
   5.50   6.00   6.50   7.00   7.50   8.00   8.50   9.00   9.50  10.00
  10.50  11.00  11.50  12.00  12.50  13.00  13.50  14.00  14.50  15.00
  15.50  16.00  16.50  17.00  17.50  18.00  18.50  19.00  19.50  20.00
  20.50  21.00  21.50  22.00  22.50  23.00  23.50  24.00  24.50  25.00
  25.50  26.00  26.50  27.00  27.50  28.00  28.50  29.00  29.50  30.00
  30.50  31.00  31.50  32.00  32.50  33.00  33.50  34.00  34.50  35.00
  35.50  36.00  36.50  37.00  37.50  38.00  38.50  39.00  39.50  40.00
  40.50  41.00  41.50  42.00  42.50  43.00  43.50  44.00  44.50  45.00
  45.50  46.00  46.50  47.00  47.50  48.00  48.50  49.00  49.50  50.00

--------------------------target2数组--------------------------
   1.00   1.41   1.73   2.00   2.24   2.45   2.65   2.83   3.00   3.16
   3.32   3.46   3.61   3.74   3.87   4.00   4.12   4.24   4.36   4.47
   4.58   4.69   4.80   4.90   5.00   5.10   5.20   5.29   5.39   5.48
   5.57   5.66   5.74   5.83   5.92   6.00   6.08   6.16   6.24   6.32
   6.40   6.48   6.56   6.63   6.71   6.78   6.86   6.93   7.00   7.07
   7.14   7.21   7.28   7.35   7.42   7.48   7.55   7.62   7.68   7.75
   7.81   7.87   7.94   8.00   8.06   8.12   8.19   8.25   8.31   8.37
   8.43   8.49   8.54   8.60   8.66   8.72   8.77   8.83   8.89   8.94
   9.00   9.06   9.11   9.17   9.22   9.27   9.33   9.38   9.43   9.49
   9.54   9.59   9.64   9.70   9.75   9.80   9.85   9.90   9.95  10.00

--------------------------target3数组--------------------------
   0.84   0.91   0.14  -0.76  -0.96  -0.28   0.66   0.99   0.41  -0.54
  -1.00  -0.54   0.42   0.99   0.65  -0.29  -0.96  -0.75   0.15   0.91
   0.84  -0.01  -0.85  -0.91  -0.13   0.76   0.96   0.27  -0.66  -0.99
  -0.40   0.55   1.00   0.53  -0.43  -0.99  -0.64   0.30   0.96   0.75
  -0.16  -0.92  -0.83   0.02   0.85   0.90   0.12  -0.77  -0.95  -0.26
   0.67   0.99   0.40  -0.56  -1.00  -0.52   0.44   0.99   0.64  -0.30
  -0.97  -0.74   0.17   0.92   0.83  -0.03  -0.86  -0.90  -0.11   0.77
   0.95   0.25  -0.68  -0.99  -0.39   0.57   1.00   0.51  -0.44  -0.99
  -0.63   0.31   0.97   0.73  -0.18  -0.92  -0.82   0.04   0.86   0.89
   0.11  -0.78  -0.95  -0.25   0.68   0.98   0.38  -0.57  -1.00  -0.51

Bye.
请按任意键继续. . .
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值