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

发布于:2025-07-30 ⋅ 阅读:(19) ⋅ 点赞:(0)

本章共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 <stdio.h>
#include <string.h>
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 100

struct 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 < MAXBKS)
            printf("Enter the next title.\n");
    }
    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 4
int 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#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 < 0 || 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 < MAX_PLAYERS; i++) {
        if (players[i].at_bats > 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 < MAX_PLAYERS; i++) {
        // 只显示有数据的球员
        if (players[i].first_name[0] != '\0') {
            printf("%-4d %-12s %-12s %8d %8d %8d %8d %8.3f\n",
                i,
                players[i].first_name,
                players[i].last_name,
                players[i].at_bats,
                players[i].hits,
                players[i].walks,
                players[i].rbis,
                players[i].avg);

            // 累加球队总计
            total_at_bats += players[i].at_bats;
            total_hits += players[i].hits;
            total_walks += players[i].walks;
            total_rbis += players[i].rbis;
        }
    }

    // 计算球队总安打率
    float team_avg = total_at_bats > 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;
}


网站公告

今日签到

点亮在社区的每一天
去签到