《C Primer Plus》(第六版)第十四章:结构与其他数据类型|复习题与编程练习答案参考

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[10];
char abbrev[4];
int days;
int monumb;
};
4. 定义一个数组,内含 12 个结构(第 3 题的结构类型)并初始化为一个年份(非闰年)。
struct month months[12] =
{
{ "January", "jan", 31, 1 },
{ "February", "feb", 28, 2 },
{ "March", "mar", 31, 3 },
1506 { "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 题的结构模版和一个该类型结构的数组。
extern struct month months [];
int days(int month)
{
int index, total;
if (month < 1 || month > 12)
return(-1);
else
{
for (index = 0, total = 0; index < month; index++)
total += months[index].days;
return(total);
}
}
注意, index 比月数小 1 ,因为数组下标从 0 开始。然后,用 index < month代替index <= month
6.a. 假设有下面的 typedef ,声明一个内含 10 个指定结构的数组。然后,单独给成员赋值(或等价字符串),使第3 个元素表示一个焦距长度有500mm,孔径为 f/2.0 Remarkata 镜头。
typedef struct lens { /* 描述镜头 */
float foclen; /* 焦距长度,单位为 mm */
float fstop; /* 孔径 */
char brand[30]; /* 品牌名称 */
} LENS;
b. 重写 a ,在声明中使用一个待指定初始化器的初始化列表,而不是对每个成员单独赋值。
a. 要包含 string.h 头文件,提供 strcpy() 的原型:
typedef struct lens { /* lens 描述 */
float foclen; /* 焦距长度,单位: mm */
float fstop; /* 孔径 */
char brand[30];/* 品牌 */
} LENS;
LENS bigEye[10];
bigEye[2].foclen = 500;
bigEye[2].fstop = 2.0;
strcpy(bigEye[2].brand, "Remarkatar");
b.LENS bigEye[10] = { [2] = {500, 2, "Remarkatar"} };
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"
void printinfo(const struct bem *pbem)
{
  printf(" %s %s is a %d-limbed %s. ",pbem->title.first,pbem->title.last,pbem->limbs,pbem->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",&p->name.lname)
g.
willie.name.fname[2]
h.
strlen(willie.name.fname)+strlen(willie.name.fname)
9. 定义一个结构模板以储存这些项:汽车名、马力、 EPA (美国环保局)城市交通MPG (每加仑燃料行驶的英里数)评级、轴距和出厂年份。使用car 作为该模版的标记。
struct car {
    char name[20];
    double horsepower;
    int grade;
    double wheelbase;
    int year;
};
10. 假设有如下结构:
struct gas {
float distance;
float gals;
float mpg;
};
a. 设计一个函数,接受 struct gas类型的参数。假设传入的结构包含distance和 gals 信息。该函数为 mpg 成员计算正确的值,并把值返回该结构。
b. 设计一个函数,接受 structgas类型的参数。假设传入的结构包含distance和 gals 信息。该函数为 mpg 成员计算正确的值,并把该值赋给合适的成员。
struct gas {
float distance;
float gals;
float mpg;
};
struct gas mpgs(struct gas trip)
{
if (trip.gals > 0)
trip.mpg = trip.distance / trip.gals;
else
trip.mpg = -1.0;
return trip;
}
void set_mpgs(struct gas * ptrip)
{
if (ptrip->gals > 0)
ptrip->mpg = ptrip->distance / ptrip->gals;
else
ptrip->mpg = -1.0;
}
注意,第 1 个函数不能直接改变其主调程序中的值,所以必须用返回值
才能传递信息。
struct gas idaho = {430.0, 14.8}; // 设置前两个成员
idaho = mpgs(idaho); // 重置数据结构
但是,第 2 个函数可以直接访问最初的结构:
struct gas ohio = {583, 17.6}; // 设置前两个成员
set_mpgs(&ohio);// 设置第 3 个成员
11. 声明一个标记为 choices 的枚举,把枚举常量 no yes maybe 分别设置为0 1 2
enum choices {
    no=0,yes,maybe
};
12. 声明一个指向函数的指针,该函数返回指向 char 的指针,接受一个指向char 的指针和一个 char 类型的值。
char* (*pfunction)(char* p, char c);
13. 声明 4 个函数,并初始化一个指向这些函数的指针数组。每个函数都接受两个double 类型的参数,返回 double 类型的值。另外,用两种方法使用该数组调用带10.0 2.5 实参的第 2 个函数。

double fun1(double, double);
double fun2(double, double);
double fun3(double, double);
double fun4(double, double);

typedef double(*ptype)(double,double);
ptype pfun[4] = {fun1,fun2,fun3,fun4};

第一种方法:pfun[1](10.0, 2.5);
第二种方法:(*pfun[1])(10.0, 2.5);

编程练习
1. 重新编写复习题5,用月份名的拼写代替月份号(别忘了使用strcmp())。在一个简单的程序中测试该函数。
#include <stdio.h>
#include <string.h>

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

struct month months[12] = {
    {"January", 31},
    {"February", 28},
    {"March", 31},
    {"April", 30},
    {"May", 31},
    {"June", 30},
    {"July", 31},
    {"August", 31},
    {"September", 30},
    {"October", 31},
    {"November", 30},
    {"December", 31}
};

int daysInMonth(char moname[]) {
    for (int i = 0; i < 12; i++) {
        if (strcmp(moname, months[i].name) == 0) {
            int total = 0;
            for (int j = 0; j <= i; j++) {
                total += months[j].days;
            }
            return total;
        }
    }
    printf("月份名不匹配\n");
    return -1;  // 如果不匹配,返回-1并打印错误消息
}

int main(void) {
    char name[10];
    printf("输入月份(第一个字母大写):\n");
    scanf_s("%s", name,(unsigned)sizeof(name));
    int totalDays = daysInMonth(name);
    if (totalDays != -1) {
        printf("到%s月底的总天数是:%d\n", name, totalDays);
    }
    return 0;
}

2. 编写一个函数,提示用户输入日、月和年。月份可以是月份号、月份名或月份名缩写。然后该程序应返回一年中到用户指定日子(包括这一天)的总天数。
3. 修改程序清单 14.2 中的图书目录程序,使其按照输入图书的顺序输出图书的信息,然后按照标题字母的声明输出图书的信息,最后按照价格的升序输出图书的信息。
4. 编写一个程序,创建一个有两个成员的结构模板:
a. 1 个成员是社会保险号,第 2 个成员是一个有 3 个成员的结构,第 1 个成员代表名,第2 个成员代表中间名,第 3 个成员表示姓。创建并初始化一个内含5 个该类型结构的数组。该程序以下面的格式打印数据:
Dribble, Flossie M.–– 302039823
如果有中间名,只打印它的第 1 个字母,后面加一个点( . );如果没有中间名,则不用打印点。编写一个程序进行打印,把结构数组传递给这个函数。
b. 修改 a 部分,传递结构的值而不是结构的地址。
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. 打印班级的平均分,即所有结构的数值成员的平均值。
6. 一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:
4 Jessie Joybat 5 2 1 1
1 项是球员号,为方便起见,其范围是 0 18 。第 2 项是球员的名。第 3项是球员的姓。名和姓都是一个单词。第4 项是官方统计的球员上场次数。接着3 项分别是击中数、走垒数和打点( RBI )。文件可能包含多场比赛的数据,所以同一位球员可能有多行数据,而且同一位球员的多行数据之间可能有其他球员的数据。编写一个程序,把数据储存到一个结构数组中。该结构中的成员要分别表示球员的名、姓、上场次数、击中数、走垒数、打点和安打率(稍后计算)。可以使用球员号作为数组的索引。该程序要读到文件结尾,并统计每位球员的各项累计总和。世界棒球统计与之相关。例如,一次走垒和触垒中的失误不计入上场次数,但是可能产生一个RBI 。但是该程序要做的是像下面描述的一样读取和处理数据文件,不会关心数据的实际含义。要实现这些功能,最简单的方法是把结构的内容都初始化为零,把文件中的数据读入临时变量中,然后将其加入相应的结构中。程序读完文件后,应计算每位球员的安打率,并把计算结果储存到结构的相应成员中。计算安打率是用球员的累计击中数除以上场累计次数。这是一个浮点数计算。最后,程序结合整个球队的统计数据,一行显示一位球员的累计数据。
7. 修改程序清单 14.14 ,从文件中读取每条记录并显示出来,允许用户删除记录或修改记录的内容。如果删除记录,把空出来的空间留给下一个要读入的记录。要修改现有的文件内容,必须用"r+b" 模式,而不是 "a+b" 模式。而且,必须更加注意定位文件指针,防止新加入的记录覆盖现有记录。最简单的方法是改动储存在内存中的所有数据,然后再把最后的信息写入文件。跟踪的一个方法是在book 结构中添加一个成员表示是否该项被删除。
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) 要提示用户进行额外
输入,每个选项都能让用户中止输入。
1131 d. 执行特定程序后,该程序再次显示菜单,除非用户选择 f)
9. 巨人航空公司(编程练习 8 )需要另一架飞机(容量相同),每天飞4 班(航班 102 311 444 519 )。把程序扩展为可以处理 4 个航班。用一个顶层菜单提供航班选择和退出。选择一个特定航班,就会出现和编程练习8类似的菜单。但是该菜单要添加一个新选项:确认座位分配。而且,菜单中的退出是返回顶层菜单。每次显示都要指明当前正在处理的航班号。另外,座位分配显示要指明确认状态。
10. 编写一个程序,通过一个函数指针数组实现菜单。例如,选择菜单中的 a ,将激活由该数组第 1 个元素指向的函数。
#include <stdio.h>
#include <stdlib.h>
void option1() {
	printf("您选择了选项a\n");
}
void option2() {
	printf("您选择了选项b\n");
}
void option3()
{
	printf("您选择了选项c\n");
}
void exitprogram() {
	printf("退出\n");
	exit(0);
}

typedef void (*MenuFun)();//函数指针。创建一个新的指针类型,指向一个无参数、无返回值的函数
int main() {
	MenuFun menu[] = { option1,option2,option3,exitprogram };//数组的元素类型是MenuFun类型
	int numOptions = sizeof(menu) / sizeof(menu[0]);
	char choice;
	do {
		printf("\n显示菜单\n");
		for (int i = 0; i < numOptions; ++i) {
			printf("%c:选项:%d\n", 'a' + i, i);
		}
		printf("q.退出\n");
		printf("请选择一个选项:\n");
		scanf_s(" %c", &choice,(unsigned)sizeof(choice));

		if (choice>='a' && choice < 'a' + numOptions) {
			menu[choice - 'a']();
		}
		else if (choice == 'q') {
			exitprogram();
		}
		else {
			printf("无效输入,请重试。\n");
		}
	} while (choice != 'q' && choice != 'Q');

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值