第十四章编程练习
第一个问题让我们改写复习题5,创建一个函数去计算一年到某个月份的天数,在一个结构数组中去存储相关数据。完整程序代码以及运行结果如下:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
struct month
{
char name[20];
char abbr[4];
int days;
int number;
};
const 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}
};
int jiSuan(const char *);
int main(void){
char input[20];
int total;
printf("请输入一个月份:\n");
while (scanf("%s",input) == 1 && input[0] != 'q'){
total = jiSuan(input);
if (total>0){
printf("到%s月为止,一共有%d天。\n",input,total);
}else{
printf("输入的月份可能存在错误,请检查。\n");
}
printf("请输入下一个月份。输入q结束循环\n");
}
printf("Done!!!");
return 0;
}
int jiSuan(const char * in){
int n = 0;
int r = 0;
for (int i = 0; i < 12; i++){
if(strcmp(in,months[i].name) == 0){
n = months[i].number;
}
}
for (int i = 0; i < n; i++){
r += months[i].days;
}
return r;
}
接下来,我们来看一下第二题的要求,获取输入的日、月和年,月份可以是三种格式,然后返回一年中到指定日子的总天数。这里就有一个问题了,输入了年份,那么平闰年要处理吗,题目里并没有明确的说明。我们简单的对其处理一下,完整程序代码以及运行结果如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
struct month
{
char name[20];
char abbr[4];
int days;
char number[3];
};
const 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"}
};
int jiSuan(const char *, int, int);
int main(void){
char input[20];
int ri,year;
int total;
int flag;
printf("请输入一个月份:\n");
while (scanf("%s",input) == 1 && input[0] != 'q'){
printf("请输入截止到这个月的几号:\n");
flag = 0;
scanf("%d",&ri);
printf("请输入年份:\n");
scanf("%d",&year);
if ((year % 4 == 0 && year % 100 != 0)||year % 400 == 0){
flag = 1;
}
total = jiSuan(input,ri,flag);
if (total>0){
printf("到%s月为止,一共有%d天。\n",input,total);
}else{
printf("输入的月份可能存在错误,请检查。\n");
}
printf("请输入下一个月份。输入q结束循环\n");
}
printf("Done!!!");
return 0;
}
int jiSuan(const char * in, int ri, int flag){
int n = 0;
int r = ri;
for (int i = 0; i < 12; i++){
if(strcmp(in,months[i].name) == 0 ||strcmp(in,months[i].abbr) == 0||strcmp(in,months[i].number) == 0){
n = atoi(months[i].number);
}
}
for (int i = 0; i < n-1; i++){
r += months[i].days;
}
if (flag == 1 && n > 2){
r += 1;
}
return r;
}
下面,我们来看一下第三题的要求,让我们修改程序清单14.2,然后按照几种顺序去输出图书信息。完整程序代码以及运行结果如下:
/* manybook.c -- 包含多本书的图书目录 */
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100 /* 书籍的最大数量 */
struct book { /* 建立 book 模板 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
void ziMu(struct book library[MAXBKS],int count);
void jgMu(struct book library[MAXBKS],int count);
int main(void)
{
struct book library[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) != NULL
&& 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);
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);
ziMu(library,count);
jgMu(library,count);
}
else
printf("No books? Too bad.\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) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; // 处理输入行中剩余的字符
}
return ret_val;
}
void ziMu(struct book library[MAXBKS],int count){
struct book libraryz[MAXBKS];
struct book lz;
for (int i = 0; i < count; i++){
libraryz[i] = library[i];
}
for (int i = 0; i < count; i++){
for (int j = i+1; j < count; j++){
if (strcmp(libraryz[i].title,libraryz[j].title)>0){
lz = libraryz[i];
libraryz[i] = libraryz[j];
libraryz[j] = lz;
}
}
}
printf("Here is the list of your books(按照字母顺序):\n");
for (int index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", libraryz[index].title,
libraryz[index].author, libraryz[index].value);
}
void jgMu(struct book library[MAXBKS],int count){
struct book libraryj[MAXBKS];
struct book lz;
for (int i = 0; i < count; i++){
libraryj[i] = library[i];
}
for (int i = 0; i < count; i++){
for (int j = i+1; j < count; j++){
if (libraryj[i].value > libraryj[j].value){
lz = libraryj[i];
libraryj[i] = libraryj[j];
libraryj[j] = lz;
}
}
}
printf("Here is the list of your books(按照图书价格):\n");
for (int index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", libraryj[index].title,
libraryj[index].author, libraryj[index].value);
}
接着,来看一下第四题的内容,分析一下要求
创建一个含有两个成员的结构模版,其中一个成员是一个有三个成员的结构,初始化一个数组,内含五组数据,然后按照格式打印数据。说实话,这老外的名字格式我属实看的有点懵。那个是名字,那个又是姓,啥又是中间名啊。算了,按照自己的理解来吧。完整程序代码以及运行结果如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define SIZE 44
struct name{
char ming[SIZE];
char zhong[SIZE];
char xing[SIZE];
};
struct test
{
char shebao[100];
struct name hpe;
};
struct test arr[5] ={
{"302039823",{"Dribble","M","Flossie"}},
{"231907821",{"Rell","C","Black"}},
{"124324221",{"Dick","","James"}},
{"124454545",{"Rose","","Kell"}},
{"456565451",{"Pell","II","Gala"}}
};
void daYin(const struct test (*ptr));
void daYint(struct test ac[5]);
int main(void){
struct test (*ptr) = arr;
printf("----------程序开始----------\n");
daYin(ptr);
printf("----------------------------\n");
daYint(arr);
printf("----------程序结束----------\n");
return 0;
}
void daYin(const struct test (*ptr)){
for (int i = 0; i < 5; i++){
if (strlen((ptr+i)->hpe.zhong) > 0){
printf("%s, %s %s. -- %s\n",(ptr+i)->hpe.ming,(ptr+i)->hpe.xing
,(ptr+i)->hpe.zhong,(ptr+i)->shebao);
}else{
printf("%s, %s -- %s\n",(ptr+i)->hpe.ming,(ptr+i)->hpe.xing
,(ptr+i)->shebao);
}
}
}
void daYint(struct test ac[5]){
for (int i = 0; i < 5; i++){
if (strlen(ac[i].hpe.zhong) > 0){
printf("%s, %s %s. -- %s\n",ac[i].hpe.ming,ac[i].hpe.xing
,ac[i].hpe.zhong,ac[i].shebao);
}else{
printf("%s, %s -- %s\n",ac[i].hpe.ming,ac[i].hpe.xing
,ac[i].shebao);
}
}
}
下面,我们来分析一下下一个问题的要求,主要是要去计算学生的平均成绩,用一个嵌套结构去记录数值。完整程序代码以及运行结果如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define SIZE 44
#define CSIZE 4
struct name
{
char ming[SIZE];
char xing[SIZE];
};
struct student
{
struct name stu;
float grade[3];
float average;
};
int main(void){
struct student students[CSIZE] = {
{{"Rose","Hadden"}},
{{"Hadvi","Dick"}},
{{"James","Kell"}},
{{"Yang","Auto"}}
};
for (int i = 0; i < CSIZE; i++){
int sum = 0, count = 0;
printf("请输入 %s %s 同学的成绩:\n",students[i].stu.ming,students[i].stu.xing);
for (int j = 0; j < 3; j++){
if (scanf("%f",&students[i].grade[j]) != 0){
sum += students[i].grade[j];
count++;
}
}
students[i].average = sum/count;
}
printf("名字 姓氏 成绩1 成绩2 成绩3 平均成绩\n");
for (int i = 0; i < CSIZE; i++){
printf("%s %s %.2f %.2f %.2f %.2f\n",students[i].stu.ming,students[i].stu.xing,
students[i].grade[0],students[i].grade[1],students[i].grade[2],
students[i].average);
}
int sumb = 0;
for (int i = 0; i < CSIZE; i++){
sumb += students[i].average;
}
float ave = sumb / CSIZE;
printf("班级的平均成绩为:%.2f\n",ave);
return 0;
}
好的,接下来,来看一下第六题的要求是什么,处理一个垒球队的球员上场数据,计算后续的数据,比如安打率之类的高级数据。完整程序代码以及运行结果如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define SIZE 44
#define TXT "D:\\C\\test14.txt"
struct player
{
int number;
char ming[SIZE];
char xing[SIZE];
int shang;
int ji;
int zou;
int rbi;
float adl;
};
struct player players[19] = {
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},
{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0},{0,"","",0,0,0,0,0}
};
int main(void){
FILE * in;
int count;
int n, s, j, z, r;
float a;
char m[SIZE], x[SIZE];
if((in = fopen(TXT,"r")) == NULL){
fprintf(stderr,"无法打开文件%s",TXT);
exit(EXIT_FAILURE);
}
rewind(in);
while (feof(in) != 1 &&(count = fscanf(in,"%d %s %s %d %d %d %d",&n,m,x,&s,&j,&z,&r)) && count == 7){
players[n].number = n;
strcpy(players[n].ming,m);
strcpy(players[n].xing,x);
players[n].shang += s;
players[n].ji += j;
players[n].zou += z;
players[n].rbi += r;
}
printf("号码 名字 姓氏 上场数 击中数 走垒数 RBI 安打率\n");
for (int i = 0; i < 19; i++){
if (players[i].shang > 0){
a = (float)players[i].ji/(float)players[i].shang;
}else{
a = 0;
}
players[i].adl = a;
printf("%-5d %-6s %-6s %5d %7d %9d %6d %7.2f\n",players[i].number,players[i].ming,
players[i].xing,players[i].shang,players[i].ji,players[i].zou,players[i].rbi,a);
}
return 0;
}
接着,我们来看一下第七题的要求以及具体实现思路,要求我们去修改程序清单14.14,然后增加一个修改以及删除文件中的图书信息,这一个确实比较复杂,用了很长时间,也没有做出最终的效果,只是粗略的实现了一下这部分的功能,其实还有很大的优化空间。我们来看一下程序的完整代码以及运行结果:
/* booksave.c -- 在文件中保存结构中的内容 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10 /* 最大书籍数量 */
char * s_gets(char * st, int n);
struct book { /* 建立 book 模板 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
int delete;
};
void update(struct book * lbi,int n);
int main(void)
{
struct book library[MAXBKS]; /* 结构数组 */
int count = 0;
int index, filecount;
FILE * pbooks;
int size = sizeof(struct book);
char yn,ud;
int delcount = 0;
if ((pbooks = fopen("book.dat", "r+b")) == NULL)
{
fputs("Can't open book.dat file\n", stderr);
exit(1);
}
rewind(pbooks); /* 定位到文件开始 */
while (count < MAXBKS && fread(&library[count], size,
1, pbooks) == 1)
{
if (count == 0)
puts("Current contents of book.dat:");
if (library[count].delete == 0){
printf("%s by %s: $%.2f\n", library[count].title,
library[count].author, library[count].value);
printf("是否要对该条内容执行修改或删除操作(y/n):\n");
scanf("%c",&yn);
while (getchar() != '\n'){
continue;
}
if (yn == 'y'){
printf("如要执行修改操作请输入u,删除操作请输入d。\n");
scanf("%c",&ud);
while (getchar() != '\n'){
continue;
}
if (ud == 'u'){
printf("开始修改\n");
update(library,count);
printf("已修改\n");
}else if (ud == 'd'){
printf("已删除\n");
library[count].delete = 1;
delcount++;
}
}
count++;
}
}
filecount = count - delcount;
if (filecount == MAXBKS)
{
fputs("The book.dat file is full.", stderr);
exit(2);
}
int newcount = 0, newH =0;
if (delcount > 0){
while (library[newcount].delete == 0){
newcount++;
}
count = newcount;
}
puts("Please add new book titles.");
puts("Press [enter] at the start of a line to stop.");
while (filecount < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
&& library[count].title[0] != '\0')
{
puts("Now enter the author.");
s_gets(library[count].author, MAXAUTL);
puts("Now enter the value.");
scanf("%f", &library[count].value);
library[count].delete = 0;
while (getchar() != '\n')
continue; /* 清理输入行 */
if (count < MAXBKS)
puts("Enter the next title.");
newH++;
if (delcount > 0){
while (library[newcount].delete == 0){
newcount++;
}
count = newcount;
}else{
count++;
}
}
int nownumber = filecount + newH;
if (nownumber > 0)
{
rewind(pbooks);
puts("Here is the list of your books:");
for (index = 0; index < nownumber; index++){
printf("%s by %s: $%.2f\n", library[index].title,
library[index].author, library[index].value);
fwrite(&library[index], size, 1, pbooks);
}
}
else
puts("No books? Too bad.\n");
puts("Bye.\n");
fclose(pbooks);
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) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; // 清理输入行
}
return ret_val;
}
void update(struct book * lbi,int n){
struct book the;
printf("暂不支持修改单个数据,请重新输入该条图书数据。\n");
puts("请输入要修改的图书名。");
s_gets(the.title,MAXTITL);
puts("请输入图书作者。");
s_gets(the.author, MAXAUTL);
puts("请输入图书价格。");
scanf("%f", &the.value);
the.delete = 0;
while (getchar() != '\n')
continue;
*(lbi + n) = the;
}
首先是,从零添加图书,结果如下
然后再次运行程序,回显这些文件,并测试修改以及删除操作
观察得知,修改操作已经没有问题,但是还可以优化,比如单独修改其中的某个值,这里就先不讨论了,我们再去改一下删除的问题。又仔细看了一下,发现好像是在选择操作的时候输错了值,跳过了一步,导致删除没有成功,我们再单独测试一遍删除操作。
由此可见,没有问题,再测试一下只删除,不添加的操作。
好,综上,这一个问题就简单的实现了基本的要求,当然如果时间充裕的话,还可以像我说的一样,进行用户使用体验的优化,比如可以选择修改某个值,其实实现起来也不是很难,毕竟你全部更新都实现了,更新单个值的内容的话,只是还要加一步选择操作。自己思考这来实现吧。下面,我们来看一下第八题的要求。
巨人航空公司,哈哈,讲道理不怕艾伦塔塔开你吗?开玩笑哈,我们接着看要求。飞机上有十二个座位,每天飞行一个航班,给了我们结构的数据内容,实现菜单的内容,:选择方法,输入其字母标签,a:显示空座位数,b:显示空座位列表,c:显示按字母顺序排列的座位列表,d:为客户分配座位,e:删除座位分配,f:退出,选择d或者e提示用户进行额外输入,好,下面来看一下具体实现以及运行结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define SEATNUMBER 12
#define SIZE 44
struct seat
{
char number[SIZE];
int flag;//0表示没有被预定,1表示已经被预定
char ming[SIZE];
char xing[SIZE];
};
struct seat seats[SEATNUMBER] = {
{"JR-A1",0,"",""},{"JR-B1",0,"",""},{"JR-C1",0,"",""},
{"JR-A2",0,"",""},{"JR-B2",0,"",""},{"JR-C2",0,"",""},
{"JR-A3",0,"",""},{"JR-B3",0,"",""},{"JR-C3",0,"",""},
{"JR-A4",0,"",""},{"JR-B4",0,"",""},{"JR-C4",0,"",""}
};
void showMenu(void);
char getCz(void);
char * s_gets(char * st, int n);
void functionA();
void functionB();
void functionC();
void functionD();
void functionE();
int main(void){
char ch;
printf("巨人航空公司欢迎您,请选择您要办理的业务\n");
showMenu();
ch = getCz();
while (getchar() != '\n')
continue;
while (ch != 'f'){
switch (ch)
{
case 'a':
functionA();
break;
case 'b':
functionB();
break;
case 'c':
functionC();
break;
case 'd':
functionD();
break;
case 'e':
functionE();
break;
default:
break;
}
showMenu();
ch = getCz();
while (getchar() != '\n')
continue;
}
printf("Done!!!\n");
return 0;
}
void showMenu(void){
printf("-------------------------菜单-------------------------\n");
printf("请选择要进行的操作,输入其字母标签\n");
printf("a)显示空座位数 b)显示空座位列表 \n");
printf("c)显示按字母顺序排列的座位列表 d)为客户分配座位 \n");
printf("e)删除座位分配 f)退出 \n");
printf("------------------------------------------------------\n");
}
char getCz(void){
char input;
while (scanf("%c",&input)!=1||(input != 'a'&&input != 'b'&&input != 'c'&&
input != 'd'&&input != 'e'&&input != 'f')){
printf("您输入的值不合法,请重新输入!!\n");
while (getchar() != '\n')
continue;
}
return input;
}
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) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; // 清理输入行
}
return ret_val;
}
void functionA(){
int number = 0;
for (int i = 0; i < SEATNUMBER; i++){
if (seats[i].flag == 0){
number++;
}
}
printf("当前航班上还有%d个座位没有被预定\n",number);
}
void functionB(){
int number = 0;
printf("当前航班上空座位列表如下:\n");
for (int i = 0; i < SEATNUMBER; i++){
if (seats[i].flag == 0){
number++;
printf("%2d)%s\n",number,seats[i].number);
}
}
}
void functionC(){
struct seat copy[SEATNUMBER];
struct seat cc;
for (int i = 0; i < SEATNUMBER; i++){
copy[i] = seats[i];
}
for (int i = 0; i < SEATNUMBER; i++){
for (int j = i + 1; j < SEATNUMBER; j++){
if (strcmp(copy[i].number,copy[j].number) > 0){
cc = copy[i];
copy[i] = copy[j];
copy[j] = cc;
}
}
}
int number = 0;
for (int i = 0; i < SEATNUMBER; i++){
number++;
if (copy[i].flag == 1){
printf("%2d)%s 已预订\n",number,copy[i].number);
}else{
printf("%2d)%s 可预订\n",number,copy[i].number);
}
}
}
void functionD(){
int count = 0;
printf("请为客户分配座位,输入空行结束\n");
printf("请输入客户的名字\n");
while (count < SEATNUMBER && s_gets(seats[count].ming, SIZE) != NULL &&
seats[count].ming[0] != '\0' &&seats[count].flag != 1){
printf("请输入客户的姓氏\n");
s_gets(seats[count].xing, SIZE);
seats[count].flag = 1;
count++;
printf("这位客户的座位已经分配好,请输入下一位客户的信息\n");
}
printf("座位分配结束或者座位已满\n");
}
void functionE(){
int count = 0;
int number = 0;
char yn;
printf("请开始删除座位分配\n");
while (count < SEATNUMBER){
if (seats[count].flag == 1){
number++;
printf("%2d) %s 已预订 %s %s\n",number,seats[count].number,
seats[count].ming,seats[count].xing);
printf("是否删除该座位分配(y/n):\n");
scanf("%c",&yn);
while (getchar() != '\n')
continue;
if (yn == 'y'){
seats[count].flag = 0;
}
}
count++;
}
}
ok,我们依次进行了每个菜单的功能演示,从展示空座位列表,到预订,然后再次展示空座位数以及空座位列表,然后删除预订之后,再次展示空座位数以及空座位列表,没有问题,小细节可以优化的部分暂时不唠了,毕竟这一章的编程练习搞了好长时间了,还没有搞完。接下来,我们来看第九题的要求。将第八题扩展为可以满足四个航班,下面我们看一下程序实现以及运行结果:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define SEATNUMBER 12
#define SIZE 44
struct seat
{
char number[SIZE];
int flag;//0表示没有被预定,1表示已经被预定
char ming[SIZE];
char xing[SIZE];
};
struct seat seats[SEATNUMBER] = {
{"JR-A1",0,"",""},{"JR-B1",0,"",""},{"JR-C1",0,"",""},
{"JR-A2",0,"",""},{"JR-B2",0,"",""},{"JR-C2",0,"",""},
{"JR-A3",0,"",""},{"JR-B3",0,"",""},{"JR-C3",0,"",""},
{"JR-A4",0,"",""},{"JR-B4",0,"",""},{"JR-C4",0,"",""}
};
char hb[4][SIZE] = {
"巨航102","巨航311","巨航444","巨航519"
};
void showHb(void);
void showMenu(int hbn);
char getCz(void);
char * s_gets(char * st, int n);
void functionA(int hbn);
void functionB(int hbn);
void functionC(int hbn);
void functionD(int hbn);
void functionE(int hbn);
void functionF(int hbn);
int main(void){
char ch;
char hh;
printf("巨人航空公司欢迎您,请选择您要办理的业务\n");
showHb();
hh = getCz();
while (getchar() != '\n')
continue;
while (hh != 'f'){
int hbn = (int)hh - (int)'a';
showMenu(hbn);
ch = getCz();
while (getchar() != '\n')
continue;
while (ch != 'g'){
switch (ch)
{
case 'a':
functionA(hbn);
break;
case 'b':
functionB(hbn);
break;
case 'c':
functionC(hbn);
break;
case 'd':
functionD(hbn);
break;
case 'e':
functionE(hbn);
break;
case 'f':
functionF(hbn);
break;
default:
break;
}
showMenu(hbn);
ch = getCz();
while (getchar() != '\n')
continue;
}
showHb();
hh = getCz();
while (getchar() != '\n')
continue;
}
printf("Done!!!\n");
return 0;
}
void showHb(void){
char n = 'a';
printf("-----------------------航班信息------------------------\n");
for (int i = 0; i < 4; i++){
printf("%c) %s\n",n,hb[i]);
n++;
}
printf("%c) 退出程序\n",n);
printf("-------------------------------------------------------\n");
}
void showMenu(int hbn){
printf("------------------%s-----菜单-------------------------\n",hb[hbn]);
printf("请选择要进行的操作,输入其字母标签\n");
printf("a)显示空座位数 b)显示空座位列表 \n");
printf("c)显示按字母顺序排列的座位列表 d)为客户分配座位 \n");
printf("e)删除座位分配 f)确认座位分配 \n");
printf("g)退出 \n");
printf("------------------------------------------------------\n");
}
char getCz(void){
char input;
while (scanf("%c",&input)!=1 || input < 'a' || input > 'g'){
printf("您输入的值不合法,请重新输入!!\n");
while (getchar() != '\n')
continue;
}
return input;
}
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) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; // 清理输入行
}
return ret_val;
}
void functionA(int hbn){
int number = 0;
for (int i = 0; i < SEATNUMBER; i++){
if (seats[i].flag == 0){
number++;
}
}
printf("%s航班上还有%d个座位没有被预定\n",hb[hbn],number);
}
void functionB(int hbn){
int number = 0;
printf("%s航班上空座位列表如下:\n",hb[hbn]);
for (int i = 0; i < SEATNUMBER; i++){
if (seats[i].flag == 0){
number++;
printf("%2d)%s %s\n",number,hb[hbn],seats[i].number);
}
}
}
void functionC(int hbn){
struct seat copy[SEATNUMBER];
struct seat cc;
for (int i = 0; i < SEATNUMBER; i++){
copy[i] = seats[i];
}
for (int i = 0; i < SEATNUMBER; i++){
for (int j = i + 1; j < SEATNUMBER; j++){
if (strcmp(copy[i].number,copy[j].number) > 0){
cc = copy[i];
copy[i] = copy[j];
copy[j] = cc;
}
}
}
int number = 0;
for (int i = 0; i < SEATNUMBER; i++){
number++;
if (copy[i].flag == 1){
printf("%2d) %s %s 已预订\n",number,hb[hbn],copy[i].number);
}else{
printf("%2d) %s %s 可预订\n",number,hb[hbn],copy[i].number);
}
}
}
void functionD(int hbn){
int count = 0;
printf("请为客户在航班%s上分配座位,输入空行结束\n",hb[hbn]);
printf("请输入客户的名字\n");
while (count < SEATNUMBER && s_gets(seats[count].ming, SIZE) != NULL &&
seats[count].ming[0] != '\0' &&seats[count].flag != 1){
printf("请输入客户的姓氏\n");
s_gets(seats[count].xing, SIZE);
seats[count].flag = 1;
count++;
printf("这位客户的座位已经分配好,请输入下一位客户的信息\n");
}
printf("%s航班座位分配结束或者座位已满\n",hb[hbn]);
}
void functionE(int hbn){
int count = 0;
int number = 0;
char yn;
printf("请开始删除%s航班上的座位分配\n",hb[hbn]);
while (count < SEATNUMBER){
if (seats[count].flag == 1){
number++;
printf("%2d) %s %s 已预订 %s %s\n",number,seats[count].number,
hb[hbn],seats[count].ming,seats[count].xing);
printf("是否删除该座位分配(y/n):\n");
scanf("%c",&yn);
while (getchar() != '\n')
continue;
if (yn == 'y'){
seats[count].flag = 0;
}
}
count++;
}
}
void functionF(int hbn){
int count = 0;
int number = 0;
char yn;
printf("请开始确认%s航班上的座位分配\n",hb[hbn]);
while (count < SEATNUMBER){
if (seats[count].flag == 1){
number++;
printf("%2d) %s %s 已预订 %s %s\n",number,seats[count].number,
hb[hbn],seats[count].ming,seats[count].xing);
printf("是否确认该座位分配(y/n):\n");
scanf("%c",&yn);
while (getchar() != '\n')
continue;
if (yn == 'y'){
seats[count].flag = 1;
}else{
seats[count].flag = 0;
}
}
count++;
}
}
上面,我们依次展示航班,菜单,展示空座位数以及空座位列表,然后为用户预订座位,然后在确认座位的时候一个确认,一个不进行确认,再次展示空座位数以及空座位列表,接着退出菜单,再次退出程序,结束程序。接着,我们再看一下第十题要求我们做一些什么操作。编写一个程序,通过函数指针数组去实现菜单,然后选择菜单中的值,激活对应的函数。我们简单的去实现一下这个思想要求的内容,所以具体的函数没有使用复杂的。完整程序代码以及运行结果如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
void showMenu(void);
char getCz(void);
void functionA(void);
void functionB(void);
void functionC(void);
int main(void){
void (* ptr[3]) (void) = {functionA,functionB,functionC};
char ch;
showMenu();
ch = getCz();
while (getchar() != '\n')
continue;
while (ch != 'd'){
int n = (int)ch - (int)'a';
switch (ch)
{
case 'a':
ptr[n]();
break;
case 'b':
ptr[n]();
break;
case 'c':
ptr[n]();
break;
default:
break;
}
showMenu();
ch = getCz();
while (getchar() != '\n')
continue;
}
return 0;
}
void showMenu(void){
printf("------------------------------------------\n");
printf("a) 方法A \n");
printf("b) 方法B \n");
printf("c) 方法C \n");
printf("d) 退出 \n");
printf("------------------------------------------\n");
}
char getCz(void){
char input;
while (scanf("%c",&input)!=1 || input < 'a' || input > 'd'){
printf("您输入的值不合法,请重新输入!!\n");
while (getchar() != '\n')
continue;
}
return input;
}
void functionA(void){
printf("-------------方法A开始运行----------------\n");
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
printf("-------------方法A结束运行----------------\n");
}
void functionB(void){
printf("-------------方法B开始运行----------------\n");
printf("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n");
printf("-------------方法B结束运行----------------\n");
}
void functionC(void){
printf("-------------方法C开始运行----------------\n");
printf("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n");
printf("-------------方法C结束运行----------------\n");
}
接着,我们再看一下本章的最后一个编程练习的要求,编写一个函数,函数名已经给了我们,所接受的四个参数也已经规定了,分别是,内含double数据的源数组名、内含double数据的目标数组名、表示数组元素个数的int数据、函数指针。函数把指定函数应用于源数组的每个元素,将返回值放到目标数组之中,测试该函数四次,使用两个math.h中的函数,两个自定义的函数。下面看一下完整程序以及运行结果:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#define SIZE 40
void transform(const double * trage,double * source,int count,double (* ptr)(double));
double functionE(double n);
double functionD(double n);
void showArr(const double * ac,int n);
int main(void){
double arr[SIZE];
for (int i = 0; i < SIZE; i++){
arr[i]= i;
}
double ac[SIZE];
printf("--------第一次调用-------------\n");
transform(arr,ac,SIZE,sin);
showArr(ac,SIZE);
printf("--------第二次调用-------------\n");
transform(arr,ac,SIZE,cos);
showArr(ac,SIZE);
printf("--------第三次调用-------------\n");
transform(arr,ac,SIZE,functionE);
showArr(ac,SIZE);
printf("--------第四次调用-------------\n");
transform(arr,ac,SIZE,functionD);
showArr(ac,SIZE);
return 0;
}
void transform(const double * source,double * trage,int count,double (* ptr)(double)){
for (int i = 0; i < count; i++){
*(trage + i) = ptr(*(source + i));
}
}
double functionE(double n){
double r;
r = 2*n;
return r;
}
double functionD(double n){
double r;
r = 1/n;
return r;
}
void showArr(const double * ac,int n){
for (int i = 0; i < n; i++){
printf("%.2f ",*(ac+i));
if (i%9==0 && i != 0){
printf("\n");
}
}
printf("\n");
}
最后一个问题并不是很麻烦,在实现的时候呢,我们先是调用了math.h中的sin()函数和cos()函数,然后自己写了两个函数,分别求取值的二倍以及倒数,分别调用并展示处理之后得到的数据。以上就是本章的编程练习,总体来说还是比较有东西的,毕竟搞了这么好几天呢。第十四章暂时告一段落,接着,我们就要去看一下书上关于第十五章位操作的内容了。