> 技术文档 > C Primer Plus 第6版 编程练习——第14章(上)

C Primer Plus 第6版 编程练习——第14章(上)

本章共11题,分上下两篇

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

typedef struct { int month_num; char month[10]; char month_short[4]; int days;} Month;int get_days_of_month(const char* month){ Month month_list[] = { {1, \"January\", \"Jan\", 31}, {2, \"February\", \"Feb\", 28}, {3, \"March\", \"Mar\", 31}, {4, \"April\", \"Apr\", 30}, {5, \"May\", \"May\", 31}, {6, \"June\", \"Jun\", 30}, {7, \"July\", \"Jul\", 31}, {8, \"August\", \"Aug\", 31}, {9, \"September\", \"Sep\", 30}, {10, \"October\", \"Oct\", 31}, {11, \"November\", \"Nov\", 30}, {12, \"December\", \"Dec\", 31} }; for (int i = 0; i < 12; i++) { if (strcmp(month_list[i].month, month) == 0) { return month_list[i].days; } } return -1;}int main(){ int days = get_days_of_month(\"January\"); printf(\"The days of January is %d\\n\", days); days = get_days_of_month(\"February\"); printf(\"The days of February is %d\\n\", days); days = get_days_of_month(\"March\"); printf(\"The days of March is %d\\n\", days); days = get_days_of_month(\"April\"); printf(\"The days of April is %d\\n\", days); days = get_days_of_month(\"May\"); printf(\"The days of May is %d\\n\", days); days = get_days_of_month(\"June\"); printf(\"The days of June is %d\\n\", days); days = get_days_of_month(\"July\"); printf(\"The days of July is %d\\n\", days); days = get_days_of_month(\"August\"); printf(\"The days of August is %d\\n\", days); days = get_days_of_month(\"September\"); printf(\"The days of September is %d\\n\", days); days = get_days_of_month(\"October\"); printf(\"The days of October is %d\\n\", days); days = get_days_of_month(\"November\"); printf(\"The days of November is %d\\n\", days); days = get_days_of_month(\"December\"); printf(\"The days of December is %d\\n\", days);}

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

typedef struct { int month_num; char month[10]; char month_short[4]; int days;} Month;int get_days_of_year(int year, int month, int day){ Month month_list[] = { {1, \"January\", \"Jan\", 31}, {2, \"February\", \"Feb\", 28}, {3, \"March\", \"Mar\", 31}, {4, \"April\", \"Apr\", 30}, {5, \"May\", \"May\", 31}, {6, \"June\", \"Jun\", 30}, {7, \"July\", \"Jul\", 31}, {8, \"August\", \"Aug\", 31}, {9, \"September\", \"Sep\", 30}, {10, \"October\", \"Oct\", 31}, {11, \"November\", \"Nov\", 30}, {12, \"December\", \"Dec\", 31} }; if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { month_list[1].days = 29; } int days = 0; for (int i = 1; i < month; i++) { days += month_list[i].days; } return days + day;}int main(){ printf(\"Days of 2020.05.29: %d\\n\", get_days_of_year(2020, 5, 29)); printf(\"Days of 2020.05.29: %d\\n\", get_days_of_year(2023, 5, 29));}

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

#include #include 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;}#define MAXTITL 40#define MAXAUTL 40#define MAXBKS 100struct book { char title[MAXTITL]; char author[MAXAUTL]; float value;};int compare_books(void const* value1, void const* value2){ return strcmp(((struct book const*)value1)->title, ((struct book const*)value2)->title);}int compare_books_by_price(void const* value1, void const* value2){ return ((struct book const*)value1)->value - ((struct book const*)value2)->value;}int main(void){ struct book library[MAXBKS]; int count = 0; 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_s(\"%f\", &library[count++].value); while (getchar() != \'\\n\') continue; if (count  0) { printf(\"Here is the list of your books:\\n\"); for (int i = 0; i < count; i++) printf(\"%s by %s: $%.2f\\n\", library[i].title, library[i].author, library[i].value); //按照书名的字母顺序输出图书信息 qsort(library, count, sizeof(book), compare_books); printf(\"Here is the list of your books, order by name of book:\\n\"); for (int i = 0; i < count; i++) printf(\"%s by %s: $%.2f\\n\", library[i].title, library[i].author, library[i].value); //按照价格升序输出图书信息 qsort(library, count, sizeof(book), compare_books_by_price); printf(\"Here is the list of your books, order by price:\\n\"); for (int i = 0; i < count; i++) printf(\"%s by %s: $%.2f\\n\", library[i].title, library[i].author, library[i].value); } else printf(\"No books? Too bad.\\n\"); return 0;}

4.编写一个程序,创建一个有两个成员的结构模板:
a.第1个成员是社会保险号,第2个成员是一个有3个成员的结构,第1个成员代表名,第2个成员代表中间名,第3个成员表示姓。创建并初始化一个内含5个该类型结构的数组。该程序以下面的格式打印数据:
Dribble, Flossie M. -- 302039823
如果有中间名,只打印它的第1个字母,后面加一个点(.);如果没有中间名,则不用打印点。编写一个程序进行打印,把结构数组传递给这个函数。
b.修改a部分,传递结构的值而不是结构的地址。
 

typedef struct _name { char first[20]; char middle[20]; char last[20];} name;typedef struct _person { int no; name name;} person;void print_info(person*p){ printf(\"%s, %s %c. -- %d\\n\", p->name.last, p->name.first, p->name.middle[0], p->no);}void print_info_b(person p){ printf(\"%s, %s %c. -- %d\\n\", p.name.last, p.name.first, p.name.middle[0], p.no);}int main(){ person stPerson = { 302039823, { \"Flossie\", \"Mickey\", \"Dribble\" } }; print_info(&stPerson); print_info_b(stPerson); return 0;}

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.打印班级的平均分,即所有结构的数值成员的平均值。
 

typedef struct _name { char first[20]; char last[20];}name;typedef struct _Student { name stname; double grade[3]; double avg;}student;#define CSIZE 4int main() { system(\"chcp 65001\"); student st[CSIZE]; double class_avg = 0.0; for (int i = 0; i < CSIZE; i++) { printf(\"请输入第%d个学生的姓和名:\", i + 1); scanf_s(\"%s%s\", st[i].stname.first, 20, st[i].stname.last, 20); printf(\"请输入第%d个学生的3门课成绩:\", i + 1); for (int j = 0; j < 3; j++) { scanf_s(\"%lf\", &st[i].grade[j]); class_avg += st[i].grade[j]; } st[i].avg = (st[i].grade[0] + st[i].grade[1] + st[i].grade[2]) / 3; } printf(\"学号\\t姓\\t名\\t平均成绩\\n\"); for (int i = 0; i < CSIZE; i++) { printf(\"%d\\t%s\\t%s\\t%.2lf\\n\", i + 1, st[i].stname.first, st[i].stname.last, st[i].avg); } printf(\"班级平均成绩为%.2lf\\n\", class_avg / CSIZE / 3); return 0;}

6.一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:
4 Jessie Joybat 5 2 1 1
第1项是球员号,为方便起见,其范围是0~18。第2项是球员的名。第3项是球员的姓。名和姓都是一个单词。第4项是官方统计的球员上场次数。接着3项分别是击中数、走垒数和打点(RBI。文件可能包含多场比赛的数据,所以同一位球员可能有多行数据,而且同一位球员的多行数据之间可能有其他球员的数据。编写一个程序,把数据存储到一个结构数组中。该结构中的成员要分别表示球员的名、姓、上场次数、击中数、走垒数、打点和安打率(稍后计算)。可以使用球员号作为数组的索引。该程序要读到文件结尾,并统计每位球员的各项累计总和。
世界棒球统计与之相关。例如,一次走垒和触垒中的失误不计入上场次数,但是可能产生一个RBI。但是该程序要做的是像下面描述的一样读取和处理数据文件,不会关心数据的实际含义。
要实现这些功能,最简单的方法是把结构的内容都初始化为零,把文件中的数据读入临时变量中,然后将其加入相应的结构中。程序读完文件后,应计算每位球员的安打率,并把计算结果存储到结构的相应成员中。计算安打率是用球员的累计击中数除以上场累计次数。这是一个浮点数计算。最后,程序结合整个球队的统计数据,一行显示一位球员的累计数据。
 

#include #include #include #include #define MAX_PLAYERS 19 // 球员号范围0-18// 球员结构体定义typedef struct { char first_name[50]; char last_name[50]; int at_bats; // 上场次数 int hits;  // 击中数 int walks; // 走垒数 int rbis;  // 打点(RBI) float avg; // 安打率} Player;int main(int argc, char* argv[]) { system(\"chcp 65001\"); // 初始化球员数组 Player players[MAX_PLAYERS] = { 0 }; // 打开数据文件 FILE* file; fopen_s(&file, \"team_data.txt\", \"r\"); if (file == NULL) { perror(\"打开文件失败\"); return 1; } // 临时变量存储读取的数据 int id, at_bats, hits, walks, rbis; char first[50], last[50]; // 读取并处理文件数据 while (fscanf_s(file, \"%d %s %s %d %d %d %d\", &id, first, 50, last, 50, &at_bats, &hits, &walks, &rbis) == 7) { // 验证球员号范围 if (id  18) { fprintf(stderr, \"警告: 无效球员号 %d,跳过此行\\n\", id); continue; } // 如果是第一次遇到该球员,记录姓名 if (players[id].first_name[0] == \'\\0\') { strcpy_s(players[id].first_name, first); strcpy_s(players[id].last_name, last); } // 累加统计数据 players[id].at_bats += at_bats; players[id].hits += hits; players[id].walks += walks; players[id].rbis += rbis; } fclose(file); // 计算安打率 for (int i = 0; i  0) { players[i].avg = (float)players[i].hits / players[i].at_bats; } else { players[i].avg = 0.0f; } } // 打印球队统计报告 printf(\"\\n===== 垒球队球员统计报告 =====\\n\"); printf(\"%-4s %-13s %-13s %10s %10s %10s %10s %11s\\n\", \"No\", \"名\", \"姓\", \"上场\", \"击中\", \"走垒\", \"打点\", \"安打率\"); printf(\"---------------------------------------------------------------------------\\n\"); int total_at_bats = 0, total_hits = 0, total_walks = 0, total_rbis = 0; for (int i = 0; i  0 ? (float)total_hits / total_at_bats : 0.0f; printf(\"---------------------------------------------------------------------------\\n\"); printf(\"%-34s %8d %8d %8d %8d %8.3f\\n\", \"球队总计:\", total_at_bats, total_hits, total_walks, total_rbis, team_avg); return 0;}