1.重新编写复习题5,用月份名的拼写代替月份号(别忘了使用strcmp( ))。在一个简单的程序中测试该函数。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 12
struct month
{
char name[10];
char abbrev[4];
int days;
int monumb;
};
const 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}
};
int days(char *name, int *temp);
int main(void)
{
int tp;
int daytotal;
char input[LEN];
printf("请输入一个月份名(按q退出本程序):");
while ((scanf("%11s", input) == 1) && (input[0] != 'q'))
{
daytotal = days(input, &tp);
if (daytotal > 0)
{
printf("一年中到%d月(包括%d月)总共有%d天.\n", tp, tp, daytotal);
}
else
{
printf("%s不是一个月份名!\n", input);
}
printf("您可以再次输入一个月份名(或按q退出):");
while (getchar() != '\n')
continue;
}
printf("本程序完成!\n");
return 0;
}
int days(char *m, int *temp)
{
int i = 1;
int num = 0;
int total = 0;
m[0] = toupper(m[0]);
while (m[i])
{
m[i] = tolower(m[i]);
i++;
}
for (i = 0; i < LEN; i++)
{
if (0 == strcmp(m, months[i].name))
{
num = months[i].monumb;
*temp = i + 1;
break;
}
}
if (num == 0)
{
total = -1;
}
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}
};
int days_result(char *month, int days, int *tp);
int main(void)
{
int n, val;
int day, year;
char month[LEN];
printf("请您输入日,月和年(按q退出本程序):\n");
while (scanf("%d %11s %d", &day, month, &year) == 3)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
months[1].days = 29; //判断是否是闰年;
}
val = days_result(month, day, &n);
if (val < 0)
{
printf("您输入的数据有误!\n");
}
else
{
printf("从%d年初到%d月%d日总共有%d天.\n", year, n, day, val);
}
months[1].days = 28; //2月份天数还原为非闰年时的天数;
printf("您可以继续输入日,月和年(或按q退出):\n");
}
printf("本程序完成!\n");
return 0;
}
int days_result(char *month, int days, int *tp)
{
int i;
int total = 0;
int temp = atoi(month);
month[0] = toupper(month[0]);
if (days < 1 || days > 31)
{
return -1; //输入的天数有误则终止本函数;
}
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
{
*tp = i + 1;
return total + days; //累加到此月后加上本月天数;
}
}
else
{
total += months[i].days;
}
}
return -1; //输入月份有误后的终止条件;
}
3.修改程序清单14.2中的图书目录程序,使其按照输入图书的顺序输出图书的信息,然后按照标题字母的声明输出图书的信息,最后按照价格的升序输出图书的信息。
#include <stdio.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(void)
{
struct book library[MAXBKS];
struct book *book[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 && 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");
}
return 0;
}
void sort_title(struct book *pb[], int n)
{
int i, j;
struct book *temp;
for (i = 0; i < n - 1; i++)
{
for (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)
{
int i, j;
struct book *temp;
for (i = 0; i < n - 1; i++)
{
for (j = i + 1; j < n; j++)
{
if (pb[j]->value < pb[i]->value)
{
temp = pb[j];
pb[j] = pb[i];
pb[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;
}
4.编写一个程序,创建一个有两个成员的结构模板:
a.第1个成员是社会保险号,第2个成员是一个有3个成员的结构,第1个成员代表名,第2个成员代表中间名,第3个成员表示姓。创建并初始化一个内含5个该类型结构的数组。该程序以下面的格式打印数据:
Dribble,Flossie M. --302039823
如果有中间名,只打印它的第1个字母,后面加一个点(.);如果没有中间名,则不用打印点。编写一个程序进行打印,把结构数组传递给这个函数。
b.修改a部分,传递结构的值而不是结构的地址。
#include <stdio.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 pt[], int n);
int main(void)
{
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");
}
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 pt[], int n)
{
int i;
printf("All numbers messages:\n");
for (i = 0; i < n; i++)
{
if (pt[i].name.mname[0] == '\0')
{
printf("%s, %s", pt[i].name.fname, pt[i].name.lname);
printf(" -- %s\n", pt[i].ins_num);
}
else
{
printf("%s, %s %c.", pt[i].name.fname, pt[i].name.lname, pt[i].name.mname[0]);
printf(" -- %s\n", pt[i].ins_num);
}
}
return;
}
5.编写一个程序满足下面的要求。
a,外部定义一个有两个成员的结构模板name:一个字符串储存名,一个字符串储存姓。
b.外部定义一个有3个成员的结构模板student:一个name类型的结构,一个grade数组储
存3个浮点型分数,一个变量储存3个分数平均数。
c.在main ()函数中声明一个内含cSIZE (CSIzE = 4)个student类型结构的数组,并初始
化这些结构的名字部分。用函数执行g、e、f和g中描述的任务。
d.以交互的方式获取每个学生的成绩,提示用户输入学生的姓名和分数。把分数储存到grade数
组相应的结构中。可以在main ()函数或其他函数中用循环来完成。
e.计算每个结构的平均分,并把计算后的值赋给合适的成员。
f.打印每个结构的信息。
g.打印班级的平均分,即所有结构的数值成员的平均值。
#include <stdio.h>
#include <string.h>
#define LEN 15
#define CSIZE 4
#define SCORES 3
struct name
{
char fname[LEN];
char lname[LEN];
};
struct student
{
struct name mes;
float grade[SCORES];
float aver;
};
void set_students(struct student ar[], int n);
void find_averages(struct student ar[], int n);
void show_messages(const struct student ar[], int n);
void show_averages(const struct student ar[], int n);
int main(void)
{
struct student classes[CSIZE] =
{
{"Flip", "Snide"},
{"Clare", "Voyans"},
{"Bingo", "Higgs"},
{"Fawn", "Hunter"}
};
set_students(classes, CSIZE);
find_averages(classes, CSIZE);
show_messages(classes, CSIZE);
show_averages(classes, CSIZE);
return 0;
}
void set_students(struct student ar[], int n)
{
int i, j;
for (i = 0; i < n; i++)
{
printf("请为%s %s输入3个成绩:\n", ar[i].mes.fname, ar[i].mes.lname);
for (j = 0; j < SCORES; j++)
{
while (scanf("%f", &ar[i].grade[j]) != 1)
{
while (getchar() != '\n')
continue;
printf("数据无效!请重新输入:");
}
}
}
return;
}
void find_averages(struct student ar[], int n)
{
int i, j;
float sum;
for (i = 0; i < n; i++)
{
for (j = 0, sum = 0.0f; j < SCORES; j++)
{
sum += ar[i].grade[j];
}
ar[i].aver = sum / SCORES;
}
return;
}
void show_messages(const struct student ar[], int n)
{
int i, j;
for (i = 0; i < n; i++)
{
printf("\n%s %s的3科成绩是:", ar[i].mes.fname, ar[i].mes.lname);
for (j = 0; j < SCORES; j++)
{
printf("%g ", ar[i].grade[j]);
}
printf("\n平均分是:%g\n", ar[i].aver);
}
return;
}
void show_averages(const struct student ar[], int n)
{
int i;
float total;
for (i = 0, total = 0.0f; i < n; i++)
{
total += ar[i].aver;
}
printf("\n班级平均分是:%g\n", total / n);
return;
}
6.一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:
4 Jessie Joybat 5 2 1 1
第Ⅰ项是球员号,为方便起见,其范围是0~18。第2项是球员的名。第3项是球员的姓。名和姓都是一个单词。第4项是官方统计的球员上场次数。接着3项分别是击中数、走垒数和打点(RBD)。文件可能包含多场比赛的数据,所以同一位球员可能有多行数据,而且同一位球员的多行数据之间可能有其他球员的数据。编写一个程序,把数据储存到一个结构数组中。该结构中的成员要分别表示球员的名、姓、上场次数、击中数、走垒数、打点和安打率(稍后计算)。可以使用球员号作为数组的索引。该程序要读到文件结尾,并统计每位球员的各项累计总和。
世界棒球统计与之相关。例如,一次走垒和触垒中的失误不计入上场次数,但是可能产生一个RBl。但是该程序要做的是像下面描述的一样读取和处理数据文件,不会关心数据的实际含义。
要实现这些功能,最简单的方法是把结构的内容都初始化为零,把文件中的数据读入临时变量中,然后将其加入相应的结构中。程序读完文件后,应计算每位球员的安打率,并把计算结果储存到结构的相应成员中。计算安打率是用球员的累计击中数除以上场累计次数。这是一个浮点数计算。最后,程序结合整个球队的统计数据,一行显示一位球员的累计数据。
#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; //球员的打点;
float hit_rate; //球员的安打率;
} TEAM;
int read_datas(TEAM players[], int n, FILE *fp);
void count_hit_rate(TEAM players[], int n);
void show_messages(TEAM players[], int n);
static TEAM players[LEN]; //全局静态变量中数据已清0;
int main(void)
{
FILE *fp;
int len;
if ((fp = fopen("datas.txt", "r")) == NULL)
{
fprintf(stderr, "Can't open file datas.txt.\n");
exit(EXIT_FAILURE);
}
len = read_datas(players, LEN, fp); //统计文件中不同球员的数量;
count_hit_rate(players, len);
show_messages(players, len);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can't close file datas.txt.\n");
exit(EXIT_FAILURE);
}
return 0;
}
int read_datas(TEAM players[], int n, FILE *fp)
{
int ch = 0;
int count = 0;
float hit_rate;
char fname[LEN], lname[LEN];
int m, stage_num, hit_num, base_num, rbi;
count = fscanf(fp, "%d %18s %18s %d %d %d %d",
&m, fname, lname, &stage_num, &hit_num, &base_num, &rbi);
while ((count == 7) && !feof(fp) && (ch < n))
{
if (players[m].stage_num == 0)
{
ch++;
}
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;
count = fscanf(fp, "%d %18s %18s %d %d %d %d",
&m, fname, lname, &stage_num, &hit_num, &base_num, &rbi);
}
return ch;
}
void count_hit_rate(TEAM players[], int n)
{
int i;
if (n > 0)
{
for (i = 0; i < n; i++)
{
players[i].hit_rate = (float)players[i].hit_num / (float)players[i].stage_num;
//计算每个运动员的安打率;
}
}
return;
}
void show_messages(TEAM players[], int n)
{
int i;
if (0 == n)
{
printf("No datas!\n");
}
else
{
printf("Datas for all players:\n");
printf("Id First_name Last_name Stage Hit_rate Base_num RBI Hit_rate\n");
for (i = 0; i < n; i++)
{
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);
}
}
return;
}
7.修改程序清单14.14,从文件中读取每条记录并显示出来,允许用户删除记录或修改记录的内容。
如果删除记录,把空出来的空间留给下一个要读入的记录。要修改现有的文件内容,必须用"r+b"模式,而不是"a+b"模式。而且,必须更加注意定位文件指针,防止新加入的记录覆盖现有记录。最简单的方法是改动储存在内存中的所有数据,然后再把最后的信息写入文件。跟踪的一个方法是在. book 结构中添加一个成员表示是否该项被删除。
#include <stdio.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", "rb")) != 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:");
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");
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: ");
s_gets(pb->books.author, MAXAUTL);
printf("Now enter the value: ");
while (scanf("%f", &pb->books.value) != 1)
{
eatline();
puts("Please enter a valid value: ");
}
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", ©.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;
}
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 toa seat assignmente )Delete a seat assignment
f) Quit
c.该程序能成功执行上面给出的菜单。选择d)和 e)要提示用户进行额外输入,每个选项都能让
用户中止输入。
d.执行特定程序后,该程序再次显示菜单,除非用户选择f)。
#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: ");
ch = get_first();
while (strchr("abcdef", ch) == NULL)
{
printf("Invalid data! Please you choose again: ");
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 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;
}
9.巨人航空公司(编程练习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(q to quit).");
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 %d: assigned.\n", pl[i].seat_id);
}
else
{
printf("Seat %d: 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;
}
10.编写一个程序,通过一个函数指针数组实现菜单。例如,选择菜单中的 a,将激活由该数组第I个元素指向的函数。
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define NUM 4
double twice(double x);
double half(double x);
double square(double x);
int showmenu(void);
int get_first(void);
void eatline(void);
void show(int i, double x, double (*pf[NUM])(double));
int main(void)
{
int choice;
double number;
double (*pf[NUM])(double) = {twice, half, square, sqrt};
while ((choice = showmenu()) != 'q')
{
printf("请您输入一个数:");
while (scanf("%lf", &number) != 1)
{
eatline();
printf("数据无效!请重新输入:");
}
switch (choice)
{
case 'a':
{
show(0, number, pf);
break;
}
case 'b':
{
show(1, number, pf);
break;
}
case 'c':
{
show(2, number, pf);
break;
}
case 'd':
{
show(3, number, pf);
break;
}
}
}
printf("本程序完成!\n");
return 0;
}
int showmenu(void)
{
int ch;
puts("===============================");
puts("本程序对用户输入的数进行操作");
puts("以下是可供选择的选项:");
puts("a) 翻倍此数 b) 折半此数");
puts("c) 平方此数 d) 开平方此数");
puts("q) 退出本程序");
puts("===============================");
printf("请您输入选择:");
while (ch = get_first(), (NULL == strchr("abcdq", ch)))
{
printf("请您重新输入a,b,c,d或q:");
}
return ch;
}
double twice(double x)
{
return 2.0 * x;
}
double half(double x)
{
return x / 2.0;
}
double square(double x)
{
return x * x;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
return;
}
int get_first(void)
{
int ch;
do
{
ch = tolower(getchar());
} while (isspace(ch));
eatline();
return ch;
}
void show(int i, double x, double (*pf[NUM])(double))
{
x = (*pf[i])(x);
printf("操作完成后此数是:%g\n\n", x);
return;
}
11.编写一个名为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 <math.h>
#define LEN 5
double square(double x);
double triple(double x);
void transform(double x[], double y[], int n, double (*p)(double));
void show_array(double temp[], int n);
int main(void)
{
double x[LEN] = {2.0, 4.0, 6.0, 8.0, 9.0};
double y[LEN] = {0.0};
printf("此数组是:\n");
show_array(x, LEN);
printf("\n原目标数组是:\n");
show_array(y, LEN);
transform(x, y, LEN, sqrt);
printf("\n赋值后目标数组开平方后是:\n");
show_array(y, LEN);
transform(x, y, LEN, cbrt);
printf("\n赋值后目标数组开立方后是:\n");
show_array(y, LEN);
transform(x, y, LEN, square);
printf("\n赋值后目标数组平方后是:\n");
show_array(y, LEN);
transform(x, y, LEN, triple);
printf("\n赋值后目标数组立方后是:\n");
show_array(y, LEN);
return 0;
}
double square(double x)
{
return x * x;
}
double triple(double x)
{
return x * x * x;
}
void transform(double x[], double y[], int n, double (*p)(double))
{
int i;
for (i = 0; i < n; i++)
{
y[i] = p(x[i]);
}
return;
}
void show_array(double temp[], int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("%-8g ", temp[i]);
}
putchar('\n');
return;
}