美文网首页gaoshijie365.techC语言
《C语言入门经典(第4版)》课后练习参考答案

《C语言入门经典(第4版)》课后练习参考答案

作者: 小狮子365 | 来源:发表于2016-10-05 22:06 被阅读9003次

    第1章 C语言编程

    练习1.1 编写一个程序,用两个printf()语句分别输出自己的名字和地址。

    #include <stdio.h>
    
    int main(void) {
        printf("姓名:小狮子\n");
        printf("地址:月亮之上\n");
        return 0;
    }
    
    

    练习1.2 将上一个练习修改成所有的输出只用一个printf()语句。

    #include <stdio.h>
    
    int main(void) {
        printf("姓名:小狮子\n地址:月亮之上\n");
        return 0;
    }
    

    练习1.3 编写一个程序,输出下列文本,格式如下所示:"It's freezing in here," he said coldly.

    #include <stdio.h>
    
    int main(void) {
        printf("\"It's freezing in here,\" he said coldly.\n");
        return 0;
    }
    

    第2章 编程初步

    习题2.1 编写一个程序,提示用户用英寸输入一个距离,然后将该距离值输出为码、英尺和英寸的形式。

    #include <stdio.h>
    
    /*
     * 1码=3英尺=36英寸
     */
    int main()
    {
        float len_inch = 0.0f;  // 英寸
        float len_foot = 0.0f;  // 英尺
        float len_yard = 0.0f;  // 码
        
        // 提示用户用英寸输入一个距离
        printf("请用英寸输入一个距离:");
        scanf("%f", &len_inch);
        
        // 计算英尺
        len_foot = len_inch / 12;
        
        // 计算码
        len_yard = len_foot / 3;
        
        // 输出计算后的结果
        printf("%.2f英寸 = %.2f英尺 = %.2f码\n", len_inch, len_foot, len_yard);
        
        return 0;
    }
    

    习题2.2 编写一个程序,提示用户用英尺和英寸输入一个房间的长和宽,然后计算并输出面积,单位是平方码,精度为小数点后两位数。

    #include <stdio.h>
    
    int main()
    {
        float length_in_foot = 0.0f;    // 房间的宽度 单位英尺
        float width_in_inch = 0.0f; // 房间的宽度 单位英寸
        float area_in_yard = 0.0f;  // 房间的面积 单位平方码
        
        // 提示用户输入房间的长度
        printf("请输入房间的长度(单位:foot):");
        scanf("%f", &length_in_foot);
        
        // 提示用户输入房间的宽度
        printf("请输入房间的宽度(单位:inch):");
        scanf("%f", &width_in_inch);
        
        // 计算房间的面积 1码=3英尺=36英寸
        area_in_yard = (length_in_foot / 3) * (width_in_inch / 36);
        
        // 输出房间的面积
        printf("房间的面积是:%.2f平方码。\n", area_in_yard);
        
        return 0;
    }
    

    习题2.3 一个产品有两个版本:其一是标准版,价格是$3.5,其二是豪华版,价格是$5.5。编写一个程序,使用学到的知识提示用户输入产品的版本和数量,然后根据输入的产品数量,计算并输出价格。

    #include <stdio.h>
    
    int main()
    {
        float price_of_normal = 3.5;    // 普通版单价
        float price_of_deluxe = 5.5f;   // 豪华版单价
        int number_of_normal = 0;    // 普通版的数量
        int number_of_deluxe = 0;   // 豪华版的数量
        float total_price = 0.0f;   // 总价
        
        // 提示用户输入产品的数量
        printf("请输入普通版的数量:");
        scanf("%d", &number_of_normal);
        printf("请输入豪华版的数量:");
        scanf("%d", &number_of_deluxe);
        
        // 计算总价
        total_price = number_of_normal * price_of_normal + number_of_deluxe + price_of_deluxe;
        
        // 输出总价
        printf("总价为:$%.2f\n", total_price);
        
        return 0;
    }
    

    习题2.4 编写一个程序,提示用户从键盘输入一个星期的薪水(以美元为单位)和工作时数,它们均为浮点数,然后计算并输出每个小时的平均时薪,输出格式如下所示:

    Your average hourly pay rate is 7 dollars and 54 cents.

    #include <stdio.h>
    
    int main()
    {
        float salary = 0.0f;    // 一个星期的薪水(以美元为单位)
        float hours = 0.0f; // 工作时数
        float salary_per_hour = 0.0f;   // 每个小时的平均时薪
        
        // 提示用户输入一个星期的薪水
        printf("请输入一个星期的薪水(以美元为单位):");
        scanf("%f", &salary);
        
        // 提示用户输入工作时数
        printf("请输入工作时数:");
        scanf("%f", &hours);
        
        // 计算每个小时的平均时薪
        salary_per_hour = salary / hours;
        
        // 输出结果
        printf("Your average hourly pay rate is %d dollars and %d cents.\n", (int)salary_per_hour, (int)(salary_per_hour * 100) % 100);
        
        return 0;
    }
    

    第3章 条件判断

    习题3.1 编写一个程序,首先给用户以下两种选择:

    (1)将温度从摄氏度转换为华氏度。

    (2)将温度从华氏度转换为摄氏度。

    接着,程序提示用户输入温度值,并输出转换后的数值。从摄氏度转换为华氏度,可以乘以 1.8 再加上 32。从华氏度转换为摄氏度,可以先减去 32 后,再乘以 5,除以 9。

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        float temperature = 0.0f;   // 用户输入的温度值
        char ch = '\0';
        float result = 0.0f;    // 转换后的温度值
    
        // 提示用户都有哪种转换方式
        printf("程序提供如下两种转换方式:\n");
        printf("    A. 将温度从摄氏度转换为华氏度\n    B. 将温度从华氏度转换为摄氏度\n");
    
        // 提示用户输入选择的转换方式
        printf("请选择转换方式(A or B):");
        scanf("%c", &ch);
    
        if (tolower(ch) == 'a')
        {
            printf("请输入温度值:");
            scanf("%f",  &temperature);
            result = temperature * 1.8 + 32;
            printf("%.2f摄氏度 = %.2f华氏度\n", temperature, result);
        }
        else if (tolower(ch) == 'b')
        {
            printf("请输入温度值:");
            scanf("%f", &temperature);
            result = (temperature - 32) * 5 / 9;
            printf("%.2f华氏度 = %.2f摄氏度\n", temperature, result);
        } 
        else
        {
            printf("选择错误\n");
        }
    
        return 0;
    }
    

    习题3.2 编写一个程序,提示用户输入3个整数值,分别代表月、日、年。例如用户输入了12、31、2003,程序就以31st December 2003 的格式输出该日期。

    必须在日期值的后面加上th、nd、st 和 rd。例如1st、2nd、3rd、4th、11th、12th、13th、14th、21st、22nd、23rd、24th。

    #include <stdio.h>
    
    int main()
    {
        int year = 0;
        int month = 0;
        int day = 0;
        // 定义一个代表12个月份的枚举类型,枚举器值从1开始
        enum Month { January = 1, February, March, April, May, June, July, August, September, October, November, December };    
    
        // 提示用户输入月、日、年
        printf("请输入月、日、年:");
        scanf("%d%d%d", &month, &day, &year);
    
        // 输出日
        if (day < 1 || day > 31)
        {
            printf("输入日期有误 ");
        } 
        else if (day % 10 == 1 && day != 11)
        {
            printf("%dst ", day);
        }
        else if (day % 10 == 2 && day != 12)
        {
            printf("%dnd ", day);
        }
        else if (day % 10 == 3 && day != 13)
        {
            printf("%drd ", day);
        }
        else 
        {
            printf("%dth ", day);
        }
    
        // 输出月
        switch (month)
        {
        case January:
            printf("January ");
            break;
        case February:
            printf("February ");
            break;
        case March:
            printf("March ");
            break;
        case April:
            printf("April ");
            break;
        case May:
            printf("May ");
            break;
        case June:
            printf("June ");
            break;
        case July:
            printf("July ");
            break;
        case August:
            printf("August ");
            break;
        case September:
            printf("September ");
            break;
        case October:
            printf("October ");
            break;
        case November:
            printf("November ");
            break;
        case December:
            printf("December ");
            break;
        default:
            printf("输入月份有误 ");
            break;
        }
    
        // 输出年
        printf("%d\n", year);
    
        return 0;
    }
    

    习题3.3 编写一个程序,根据从键盘输入的一个数值,计算总价(单价是$5),数值超过30的折扣是10%,数值超过50的折扣是15%。

    #include <stdio.h>
    
    int main()
    {
        float unit_price = 5.0f;    // 商品单价
        float discount = 0.0f;  // 商品折扣
        int number = 0; // 商品数量
    
        // 提示用户输入商品数量
        printf("请输入商品数量:");
        scanf("%d", &number);
    
        // 计算折扣
        if (number <= 30)
        {
            discount = 0.0f;
        }
        else if (number <= 50)
        {
            discount = 0.1f;
        }
        else
        {
            discount = 0.15f;
        }
    
        // 输出总价
        printf("商品的总价为:%.2f\n", number * unit_price * (1 - discount));
    
        return 0;
    }
    

    习题3.4 修改本章最后的计算器例子,让用户选择输入y或Y,以执行另一个计算,输入n或N就结束程序。(注意:这需要实用goto语句,下一章将介绍一个更好的方法。)

    #include <stdio.h>
    
    int main()
    {
        double number1 = 0.0;
        double number2 = 0.0;
        char operation = 0;
        char choice = 0;
    
        begin:
        printf("Enter the caculation\n");
        scanf("%lf %c %lf", &number1, &operation, &number2);
    
        switch (operation)
        {
        case '+':
            printf("= %lf\n", number1 + number2);
            break;
        case '-':
            printf("= %lf\n", number1 - number2);
            break;
        case '*':
            printf("= %lf\n", number1 * number2);
            break;
        case '/':
            if (number2 == 0)
                printf("\n\n\aDivision by zero error!\n");
            else
                printf("= %lf\n", number1 / number2);
            break;
        case '%':
            if ((long)number1 == 0)
                printf("\n\n\aDivision by zero error!\n");
            else
                printf("= %ld\n", (long)number1 % (long)number2);
            break;
        default:
            printf("\n\n\aIllegal operation!\n");
            break;
        }
    
        printf("Do you want to continue? (y or n): ");
        scanf(" %c", &choice);  // 注意:%c 前面的空格不能去掉
    
        if (choice == 'y' || choice == 'Y')
            goto begin;
    
        return 0;
    }
    

    第4章 循环

    习题4.1 编写一个程序,生成一个乘法表,其大小由用户输入来决定。例如,如果表的大小是4,该表就有4行4列。行和列标记为1~4.表中的每一个单元格都包含行列之积,因此第三行第4列的单元格包含12。

    #include <stdio.h>
    
    int main()
    {
        int num_row = 0;
        int num_col = 0;
        
        printf("请输入行数和列数:");
        scanf("%d%d", &num_row, &num_col);
        
        printf("    ");
        for (int i = 1; i <= num_col; i++)
        {
            printf("%3d ", i);
        }
        printf("\n");
        
        for (int i = 1; i <= num_row; i++)
        {
            printf("%-4d", i);
            for (int j = 1; j <= num_col; j++)
            {
                printf("%3d ", i * j);
            }
            printf("\n");
        }
        return 0;
    }
    

    习题4.2 编写一个程序,为0~127之间的字符码输出可打印的字符。输出每个字符码和它的符号,这两个字符占一行。列要对齐(提示:可以使用在ctype.h中声明的isgraph()函数,确定哪个字符是可以打印的)。

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        for (int i = 0; i <= 127; i++)
        {
            if (isgraph(i))
            {
                printf("%d  %c\n", i, i);
            }
        }
        return 0;
    }
    

    习题4.3 扩展上一题,给每个空白字符输出对应的名称,例如newline,space,tab等。

    // 本题略
    

    习题4.4 使用嵌套循环输出一个用星号绘制的盒子,与程序4.2类似,但是它的宽和高由用户输入。

    #include <stdio.h>
    
    int main()
    {
        int height = 0;
        int width = 0;
        
        printf("请输入盒子的宽和高:");
        scanf("%d%d", &width, &height);
        
        for (int i = 1; i <= height; i++)
        {
            for (int j = 1; j <= width; j++)
            {
                if (i == 1 || i == height)
                {
                    printf("*");
                }
                else
                {
                    if (j == 1 || j == width)
                    {
                        printf("*");
                    }
                    else
                    {
                        printf(" ");
                    }
                }
            }
            printf("\n");
        }
        return 0;
    }
    

    习题4.5 修改程序4.7的猜谜游戏,在玩家猜错数字后,可以用一个选项让玩家继续玩下去,且想玩多久就玩多久。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <time.h>
    
    int main()
    {
        int chosen = 0;
        int guess = 0;
        int limit = 20;
        char another_game = 'Y';
        
        srand(time(NULL));
        chosen = 1 + rand() % limit;
        
        printf("\nThis is a guessing game."
               "\nI have chosen a number between 1 and 20 which you must guess.\n");
        
        do
        {
            printf("\nEnter a guess: ");
            scanf("%d", &guess);
            
            if (guess == chosen)
            {
                printf("\nYou guessed it!\n");
                return 0;
            }
            
            if (guess < 1 || guess > 20)
            {
                printf("\nI said between 1 and 20.\n");
            }
            else
            {
                printf("\nSorry. %d is wrong.\n", guess);
            }
            
            printf("\nDo you want to play again(y/n)? ");
            scanf(" %c", &another_game);
        }while(toupper(another_game) == 'Y');
        return 0;
    }
    

    第5章 数组

    习题5.1 编写一个程序,从键盘上读入5个double类型的值,将它们存储到一个数组中。计算每个值的倒数(值x的倒数是 1.0/x),将结果存储到另一个数组中。输出这些倒数,并计算和输出倒数的总和。

    #include <stdio.h>
    
    int main()
    {
        double original[5] = { 0.0 };
        double result[5] = { 0.0 };
        double sum = 0.0;
    
        for (int i = 0; i < 5; i++)
        {
            printf("%d -> ", i + 1);
            scanf("%lf", &original[i]);
        }
    
        for (int i = 0; i < 5; i++)
        {
            result[i] = 1.0 / original[i];
        }
    
        for (int i = 0; i < 5; i++)
        {
            printf("result[%d] = %lf\n", i, result[i]);
            sum += result[i];
        }
    
        printf("sum = %lf\n", sum);
    
        return 0;
    }
    

    习题5.2 定义一个数组 data,它包含 100 个 double 类型的元素。编写一个循环,将以下的数值序列存储到数组的对应元素中:

    1/(2*3*4) 1/(4*5*6) 1/(6*7*8) ... up to 1/(200*201*202)

    编写另一个循环,计算:

    data[0] - data[1] + data[2] - data[3] + ... - data[99]

    将这个结果乘以 4.0,加 3.0,输出最后的结果。

    #include <stdio.h>
    
    int main()
    {
        double data[100] = { 0.0 };
        double sum = 0.0;
        double result = 0.0;
        
        for (int i = 1; i <= 100; i++)
        {
            data[i - 1] = 1.0 / ((2 * i) * (2 * i + 1)*(2 * i + 2));
        }
        
        for (int i = 0; i < 100; i++)
        {
            sum += (i % 2 ? -1 : 1) * data[i];
        }
        
        result = sum * 4.0 + 3.0;
        
        printf("计算结果为:%lf\n", result);
        return 0;
    }
    

    习题5.3 编写一个程序,从键盘上读入 5 个值,将它们存储到一个 float 类型的数组 amounts 中。创建两个包含 5 个 long 元素的数组 dollars 和 cents。将 amounts 数组元素的整数部分存储到 dollars 的对应元素中,amounts 数组元素的小数部分存储到 cents 中,只保存两位数字(例如:amounts[1] 的值是 2.75,则把 2 存储到 dollars[1] 中,把 75 存储 cents[1]中)。以货币格式输出这两个 long 类型数组的值(如$2.75)。

    #include <stdio.h>
    
    int main()
    {
        float amounts[5] = {0.0f};
        long dollars[5] = {0L};
        long cents[5] = {0L};
        
        for (int i = 0; i < 5; i++)
        {
            printf("%d -> ", i + 1);
            scanf("%f", &amounts[i]);
        }
        
        for (int i = 0; i < 5; i++)
        {
            dollars[i] = (long) amounts[i];
            cents[i] = (long)(amounts[i] * 100) % 100;
        }
        
        for (int i = 0; i < 5; i++)
        {
            printf("$%ld.%ld\n", dollars[i], cents[i]);
        }
        return 0;
    }
    

    习题5.4 定义一个 double 类型的二维数组 data[11][5]。用 2.0~3.0 的值初始化第一列元素(每步增加 0.1)。如果行中的第一个元素值是 x,改行的其它元素值分别是 1/x,x²,x³ 和 x⁴。输出数组中的值,每一行放在一行上,每一列要有标题。

    #include <stdio.h>
    #include <math.h>
    
    int main()
    {
        double data[11][5] = {0.0};
        
        for (int i = 0; i < 11; i++)
        {
            data[i][0] = (1 + 0.1 * i);
        }
        
        for (int i = 0; i < 11; i++)
        {
            data[i][1] = 1 / data[i][0];
            for (int j = 2; j < 5; j++)
            {
                data[i][j] = pow(data[i][0], i);
            }
        }
        
        printf("        ");
        for (int i = 0; i < 5; i++)
        {
            printf("   %02d   ", i + 1);
        }
        printf("\n");
        
        for (int i = 0; i < 11; i++)
        {
            printf("   %02d   ", i + 1);
            for (int j = 0; j < 5; j++)
            {
                printf(" %6.2lf ", data[i][j]);
            }
            printf("\n");
        }
        
        return 0;
    }
    

    习题5.5 编写一个程序,计算任意多个班级的学生的平均分。该程序应读取所有班级里学生的所有成绩,再计算平均值。给每个班级输出每个学生的平均分,以及班级的平均分。

    #include <stdio.h>
    #define CLASS_NUM 2
    #define STUDENT_NUM 2
    #define COURSE_NUM 2
    
    int main()
    {
        int score[CLASS_NUM][STUDENT_NUM][COURSE_NUM] = {0};
        int average_class = 0;
        int average_student = 0;
        
        for (int i = 0; i < CLASS_NUM; i++)
        {
            for (int j = 0; j < STUDENT_NUM; j++)
            {
                for (int k = 0; k < COURSE_NUM; k++)
                {
                    printf("Class %02d  Student %02d  Course %02d  -> ", i, j, k);
                    scanf("%d", &score[i][j][k]);
                }
            }
        }
        
        for (int i = 0; i < CLASS_NUM; i++)
        {
            average_class = 0;
            for (int j = 0; j < STUDENT_NUM; j++)
            {
                average_student = 0;
                for (int k = 0; k < COURSE_NUM; k++)
                {
                    average_class += score[i][j][k];
                    average_student += score[i][j][k];
                }
                printf("Class %02d Student %02d 的平均分是 %.2f\n", i, j, average_student * 1.0 / COURSE_NUM);
            }
            printf("Class %02d 的平均分是 %.2f\n", i, average_class * 1.0 / STUDENT_NUM / COURSE_NUM);
        }
        return 0;
    }
    

    第6章 字符串和文本的应用

    习题6.1 编写一个程序,从键盘上读入一个小于1000的正整数,然后创建并输出一个字符串,说明该整数的值。例如,输入941,程序产生的字符串是“Nine hundred and forty one”。

    #include <stdio.h>
    
    void one2nineteen(int n)
    {
        switch (n)
        {
            case 1:
                printf("one");
                break;
            case 2:
                printf("two");
                break;
            case 3:
                printf("three");
                break;
            case 4:
                printf("four");
                break;
            case 5:
                printf("five");
                break;
            case 6:
                printf("six");
                break;
            case 7:
                printf("seven");
                break;
            case 8:
                printf("eight");
                break;
            case 9:
                printf("nine");
                break;
            case 10:
                printf("ten");
                break;
            case 11:
                printf("eleven");
                break;
            case 12:
                printf("twelve");
                break;
            case 13:
                printf("thirteen");
                break;
            case 14:
                printf("fourteen");
                break;
            case 15:
                printf("fifteen");
                break;
            case 16:
                printf("sixteen");
                break;
            case 17:
                printf("seventeen");
                break;
            case 18:
                printf("eighteen");
                break;
            case 19:
                printf("nineteen");
                break;
                
            default:
                printf("one2nineteen操作失败");
                break;
        }
    }
    
    void fun(int n)
    {
        switch (n) {
            case 20:
                printf("twenty");
                break;
            case 30:
                printf("thirty");
                break;
            case 40:
                printf("fourty");
                break;
            case 50:
                printf("fifty");
                break;
            case 60:
                printf("sixty");
                break;
            case 70:
                printf("seventy");
                break;
            case 80:
                printf("eighty");
                break;
            case 90:
                printf("ninety");
                break;
            default:
                printf("fun执行出错");
                break;
        }
    }
    
    void fun2(int n)
    {
        if (n < 20)
        {
            one2nineteen(n);
        }
        else if (n < 100)
        {
            if (n % 10 == 0)
            {
                fun(n);
            }
            else
            {
                fun(n - n % 10);
                printf("-");
                one2nineteen(n % 10);
            }
        }
    }
    
    void int2str(int n)
    {
        if (n < 100)
        {
            fun2(n);
        }
        else if (n < 1000)
        {
            if (n % 100 == 0)
            {
                one2nineteen(n / 100);
                printf(" hundred");
            }
            else
            {
                one2nineteen(n / 100);
                printf(" hundred and ");
                fun2(n % 100);
            }
        }
    }
    
    int main()
    {
        for (int i = 1; i < 1000; i++)
        {
            printf("%3d -> ", i);
            int2str(i);
            printf("\n");
        }
        return 0;
    }
    

    习题6.2 编写一个程序,输入一系列单词,单词之间以逗号分割,然后提取这些单词,并将它们分行输出,删除头尾的空格。例如,如果输入是

    John , Jack , Jill

    输出将是:

    John

    Jack

    Jill

    #include <stdio.h>
    #include <ctype.h>
    #include <stdbool.h>
    
    int main()
    {
        char sequence[100] = { 0 };
        bool first = true;
        
        printf("请输入一系列单词,单词之间以逗号分隔:\n");
        if (fgets(sequence, sizeof(sequence), stdin) == NULL)
        {
            printf("输入过程出错\n");
            return 1;
        }
        else
        {
            for (int i = 0; i < 100 && sequence[i] != '\0'; i++)
            {
                if (isalpha(sequence[i])) {
                    first = true;
                    printf("%c", sequence[i]);
                }
                else
                {
                    if (first)
                    {
                        first = false;
                        printf("\n");
                    }
                }
            }
            printf("\n");
        }
        return 0;
    }
    

    习题6.3 编写一个程序,从一组至少有5个字符串的数组里,输出任意挑选的一个字符串。

    #include <stdio.h>
    
    int main()
    {
        char arr[][50] = {
            "Hello",
            "Hello World",
            "Hello World, Hello World!"
        };
        
        printf("%s\n", arr[2]);
        return 0;
    }
    

    习题6.4 回文是正读反读均相同的句子,忽略空白和标点符号。例如,“Madam, I'm Adam”和“Are we no drawn onward, we few? Drawn onward to new era?”都是回文。编写一个程序,确定从键盘输入的字符串是否是回文。

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdbool.h>
    
    int main()
    {
        char sequence[100] = { 0 };
        unsigned long head = 0;
        unsigned long last = 0;
        bool flag = true;
        
        printf("请输入一个字符串:\n");
        if (gets(sequence) == NULL)
        {
            printf("输入过程出错\n");
            return 1;
        }
        else
        {
            last = strlen(sequence);
            
            for (; head < last; )
            {
                for (;!isalpha(sequence[head]);)
                {
                    head++;
                }
                
                for (; !isalpha(sequence[last]);)
                {
                    last--;
                }
                
                if (toupper(sequence[head]) == toupper(sequence[last]))
                {
                    head++;
                    last--;
                }
                else
                {
                    flag = false;
                    break;
                }
            }
            
            if (flag)
            {
                printf("是回文\n");
            }
            else
            {
                printf("不是回文\n");
            }
        }
        return 0;
    }
    

    第7章 指针

    习题7.1 编写一个程序,计算从键盘输入的任意个浮点数的平均值。将所有的数存储到动态分配的内存中,之后计算并显示平均值。用户不需要事先指定要输入多少个数。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        float number = 0.0f;
        float *pNumber = NULL;
        int count = 0;
        float sum = 0.0f;
    
        pNumber = (float *)malloc(sizeof(float));
        if (pNumber == NULL)
        {
            printf("内存分配失败\n");
            return 1;
        }
    
        do
        {
            scanf("%f", &number);
            count++;
            pNumber = realloc(pNumber, count * sizeof(float));
    
            *(pNumber + count - 1) = number;
        } while(number != 0.0f);
    
        for (int i = 0; i < count - 1; i++)
        {
            sum += *(pNumber + i);
        }
    
        printf("平均值是 %f\n", sum / (count - 1));
    
        free(pNumber);
        return 0;
    }
    

    习题7.2 编写一个程序,从键盘读入任意个谚语,并将它们存储到执行期间分配的内存中。然后,将它们以字长顺序由短到长地输出。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        char **pStr = NULL;
        char *pBuffer = NULL;
        int count = 0;
    
        pStr = malloc(sizeof(char *));
    
        do
        {
            pBuffer = malloc(100 * sizeof(char));
            gets(pBuffer);
            count++;
            pStr = realloc(pStr, count * sizeof(char *));
            *(pStr + count - 1) = pBuffer;
        }while(strlen(pBuffer) != 0);
    
        for (int i = 0; i < count - 2; i++)
        {
            for (int j = 0; j < count - 2 - i; j++)
            {
                if (strlen(*(pStr + j)) > strlen(*(pStr + j + 1)))
                {
                    pBuffer = *(pStr + j);
                    *(pStr + j) = *(pStr + j + 1);
                    *(pStr + j + 1) = pBuffer;
                }
            }
        }
    
        for (int i = 0; i < count - 1; i++)
        {
            printf("%s\n", *(pStr + i));
        }
        return 0;
    }
    

    习题7.3 编写一个程序,从键盘读入一个字符串,显示删除了所有空格和标点符号的字符串。所有的操作都使用指针完成。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    int main()
    {
        char *pStr = NULL;
    
        pStr = malloc(100*sizeof(char));
    
        gets(pStr);
    
        while(*pStr)
        {
            if (isalpha(*pStr))
            {
                putchar(*pStr);
            }
            pStr++;
        }
    
        putchar('\n');
    
        return 0;
    }
    

    习题7.4 编写一个程序,读入任意天数的浮点温度记录值,每天有6个记录。温度记录存储在动态分配内存的数组中,数组的大小刚好等于输入的温度数。计算出每天的平均温度,然后输出每天的记录,在单独一行上输出平均值,该平均值精确到小数点后一位。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        float **pTemp = NULL;
        float sum = 0.0f;
        int count = 0;
        
        pTemp = malloc(sizeof(float));
        
        do
        {
            count++;
            pTemp = realloc(pTemp, count * sizeof(float *));
            *(pTemp + count - 1) = malloc(6 * sizeof(float));
            
            printf("Day %d :\n", count);
            for (int i = 0; i < 6; i++)
            {
                printf("%d -> ", i + 1);
                scanf("%f", (*(pTemp + count - 1) + i));
            }
        }while(**(pTemp + count - 1) != 0.0f);
        
        for (int i = 0; i < count - 1; i++)
        {
            printf("Day %d :\n", i + 1);
            sum = 0;
            for (int j = 0; j < 6; j++)
            {
                sum += *(*(pTemp+i) + j);
                printf("%d -> %f\n", j + 1, *(*(pTemp+i) + j));
            }
            printf("average = %.1f\n", sum / 6);
        }
        return 0;
    }
    

    第8章 程序的结构

    习题8.1 定义一个函数,给函数传送任意多个浮点数,计算出这些数的平均值。从键盘输入任意个值,并输出平均值,以说明这个函数的执行过程。

    #include <stdio.h>
    #include <stdlib.h>
    
    float average(float *, int);
    
    int main()
    {
        float *pNum = NULL;
        int count = 0;
        pNum = malloc(count * sizeof(float));
    
        do
        {
            count++;
            pNum = realloc(pNum, count * sizeof(float));
            scanf("%f", pNum + count - 1);
        } while(*(pNum + count - 1) != 0.0f);
    
        printf("average = %f\n", average(pNum, count - 1));
    
        return 0;
    }
    
    float average(float *pNum, int count)
    {
        float sum = 0.0f;
        for (int i = 0; i < count; i++)
        {
            sum += *(pNum + i);
        }
        return sum / count;
    }
    

    习题8.2 定义一个函数,返回其整数变元的字符串表示。例如,如果这个变元是25,函数就返回"25"。如果变元是-98,函数就返回"-98"。用适当的main()版本说明函数的执行过程。

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    char *intToString(int);
    
    int main()
    {
        printf("%s\n", intToString(-32768));
        return 0;
    }
    
    char *intToString(int number)
    {
        char *pStr = malloc(7 * sizeof(char));
        int var = 10000;
        int weishu = 5;
        int count = 0;
        if (number < 0)
        {
            *(pStr + 0) = '-';
            count = 1;
            number = -number;
        }
    
        while (number / var == 0) {
            weishu--;
            var /= 10;
        }
    
        for (; count < 7; count++)
        {
            *(pStr + count) = '0' + number / (int)(pow(10, weishu - 1));
            number %= (int)(pow(10, weishu - 1));
            weishu--;
            if (weishu <= 0) {
                break;
            }
        }
        *(pStr + count + 1) = '\0';
    
        return pStr;
    }
    

    习题8.3 扩展为上一题定义的函数,使函数接受第二个变元,以指定结果的字段宽度,使返回的字符串表示右对齐。例如,如果第一个变元的值是-98,字段宽度变元是5,返回的字符串就应该是" -98"。用适当的main()版本说明函数的执行过程。

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    char *intToString(int, int);
    
    int main()
    {
        printf("%s\n", intToString(-98, 5));
        return 0;
    }
    
    char *intToString(int number, int width)
    {
        char *pStr = malloc(7 * sizeof(char));
        int var = 10000;
        int weishu = 5;
        int count = 0;
        int len = 0;
        if (number < 0)
        {
            *(pStr + 0) = '-';
            count = 1;
            number = -number;
        }
    
        while (number / var == 0) {
            weishu--;
            var /= 10;
        }
    
        for (; count < 7; count++)
        {
            *(pStr + count) = '0' + number / (int)(pow(10, weishu - 1));
            number %= (int)(pow(10, weishu - 1));
            weishu--;
            if (weishu <= 0) {
                break;
            }
        }
        *(pStr + count + 1) = '\0';
    
        len = (int)strlen(pStr);
        if (len < width)
        {
            pStr = realloc(pStr, (width + 1) * sizeof(char));
            *(pStr + width) = '\0';
            int j = width - 1;
            for (int i = len; i > 0; i--, j--)
            {
                *(pStr + j) = *(pStr + i - 1);
            }
            for (;j >= 0; j--)
            {
                *(pStr + j) = ' ';
            }
        }
    
        return pStr;
    }
    

    习题8.4 定义一个函数,其参数是一个字符串,返回该字符串中的单词数(单词以空格或标点符号来分隔。假设字符串不包含单双引号,也就是数没有像isn't这样的单词)。定义第二个函数,它的第一个参数是一个字符串,第二个参数是一个数组,该函数将第一个字符串变元分隔成单词,把这些单词存储在第二个数组变元中,最后返回存储在数组中的单词。定义第三个函数,其参数是一个字符串,返回该字符串中的字母数。使用这些函数实现一个程序,从键盘读入含有文本的字符串,输出文本中的所有单词,输出顺序是按照单词中的字母数,由短到长。

    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include <stdbool.h>
    #include <stdlib.h>
    
    int wordCount(const char *);
    void stringToArray(char *, char **);
    int alphaCount(char *);
    
    int main()
    {
        char buffer[100] = "";
        char *pStr = buffer;
        char **pWord = NULL;
        char *pTemp = NULL;
        int words = 0;
        pWord = malloc(20 * sizeof(char *));
        gets(buffer);
        words = wordCount(pStr);
        stringToArray(pStr, pWord);
    
        for (int i = 0; i < words - 1; i++)
        {
            for (int j = 0; j < words - 1 - i; j++)
            {
                if (strlen(*(pWord + j)) > strlen(*(pWord + j + 1)))
                {
                    pTemp = *(pWord + j);
                    *(pWord + j) = *(pWord + j + 1);
                    *(pWord + j + 1) = pTemp;
                }
            }
        }
    
        for (int i = 0; i < words; i++)
        {
            printf("%s\n", *(pWord + i));
        }
    
        return 0;
    }
    
    int wordCount(const char *pStr)
    {
        int count = 0;
        bool isFirst = true;
        while (*pStr) {
            if (isalpha(*pStr)) {
                if (isFirst) {
                    isFirst = false;
                    count++;
                }
            }
            else
            {
                isFirst = true;
            }
            pStr++;
        }
        return count;
    }
    
    void stringToArray(char *pStr, char **pWord)
    {
        char *pBuffer = malloc(20 * sizeof(char));
        int wordCount = 0;
        int i = 0;
    
        while (*pStr) {
            if (isalpha(*pStr))
            {
                while (isalpha(*pStr)) {
                    *(pBuffer + i) = *pStr;
                    i++;
                    pStr++;
                }
                *(pBuffer + i) = '\0';
                *(pWord + wordCount) = pBuffer;
                wordCount++;
                pBuffer = malloc(20 * sizeof(char));
                i = 0;
            }
            else
            {
                pStr++;
            }
        }
    }
    
    int alphaCount(char *pStr)
    {
        int count = 0;
        while (*pStr++) {
            count++;
        }
        return count;
    }
    

    第9章 函数再探

    习题9.1 函数原型:

    double power(doulbe x, int n);

    会计算并返回xn。因此power(5.0, 4)会计算5.0*5.0*5.0*5.0,它的结果是625.0。将power()函数实现为递归函数,再用适当的main版本演示它的操作。

    #include <stdio.h>
    
    double power(double, int);
    
    int main()
    {
        printf("power(5.0, 4) = %lf\n", power(5.0, 4));
        return 0;
    }
    
    double power(double x, int n)
    {
        if (n == 1)
        {
            return x;
        }
        else
        {
            return x * power(x, n - 1);
        }
    }
    

    习题9.2 函数原型:

    double add(double a, double b); // returns a + b
    double subtract(double a, double b);  // returns a - b
    double multiply(double a, double b);  // returns a * b
    double array_op(double array[], int size, double (\*pfun) (double, double));
    

    array_op()函数的参数是:要运算的数组、数组元素数目以及一个函数指针,该函数指针指向的函数定义了在连续几个元素上进行的操作。在实现array_op()函数时,将subtract()函数传送为第三个参数,subtract()函数会用交替符号组合这些元素。因此,对于有4个元素x1、x2、x3、x4的数组,subtract()函数会计算x1-x2+x3-x4的值。

    用适当的main()版本演示这些函数的运作。

    #include <stdio.h>
    
    double add(double, double);
    double subtract(double, double);
    double multiply(double, double);
    double array_op(double[], int, double (*) (double, double));
    
    int main()
    {
        double array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        printf("array_op() = %lf\n", array_op(array, 5, subtract));
        return 0;
    }
    
    double add(double a, double b)
    {
        return a + b;
    }
    
    double subtract(double a, double b)
    {
        return a - b;
    }
    
    double multiply(double a, double b)
    {
        return a * b;
    }
    
    double array_op(double array[], int size, double (*pfun) (double, double))
    {
        double sum = 0.0;
        for (int i = 0; i < size / 2; i++)
        {
            sum += subtract(array[i * 2], array[i * 2 + 1]);
        }
        if (size % 2 != 0) {
            sum += array[size - 1];
        }
        return sum;
    }
    

    习题9.3 定义一个函数,它的参数是字符串数组指针,返回一个将所有字符串合并起来的字符串指针,每个字符串都用换行符来终止。如果输入数组中的原字符串将换行符作为最后一个字符,函数就不能给字符串添加另一个换行符。编写一个程序,从键盘读入几个字符串,用这个函数输出合并后的字符串。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define ARR_LEN 5
    #define BUF_LEN 100
    
    char *custom_concat(char *[]);
    
    int main()
    {
        char *pStr[ARR_LEN] = { NULL };
        for (int i = 0; i < ARR_LEN; i++)
        {
            pStr[i] = malloc(BUF_LEN * sizeof(char));
            gets(pStr[i]);
        }
    
        printf("%s\n", custom_concat(pStr));
        return 0;
    }
    
    char *custom_concat(char *pStr[])
    {
        char *pResult = NULL;
        char *pTemp = NULL;
        int totalLen = 0;
        for (int i = 0; i < ARR_LEN; i++)
        {
            totalLen += strlen(pStr[i]);
        }
        pResult = malloc((totalLen + 1) * sizeof(char));
        pTemp = pResult;
        for (int i = 0; i < ARR_LEN; i++)
        {
            strncpy(pTemp, pStr[i], strlen(pStr[i]));
            pTemp += strlen(pStr[i]);
        }
    
        return pResult;
    }
    

    习题9.4 一个函数的原型是:

    char *to_string(int count, double first, ...);

    这个函数返回一个字符串,这个字符串含有第二及其后参数的字符串表示,每个参数都有两位小数,参数间用逗号隔开。第一个参数是从第二个参数算起的参数个数。编写一个main()函数,演示这个函数的运作。

    #include <stdio.h>
    #include <stdarg.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *to_string(int , double, ...);
    
    int main()
    {
        printf("%s\n", to_string(4, 1.0, 2.0, 3.0, 4.0));
        return 0;
    }
    
    char *to_string(int count, double first, ...)
    {
        char *pStr = malloc(100 * sizeof(char));
        char buffer[100] = "";
        va_list parg;
    
        va_start(parg, first);
        sprintf(buffer, "%.2f", first);
        strcat(pStr, buffer);
    
        for (int i = 1; i < count; i++) {
            sprintf(buffer, ", %.2f", va_arg(parg, double));
            strcat(pStr, buffer);
        }
    
        va_end(parg);
        return pStr;
    }
    

    第10章 基本输入输出操作

    习题10.1 编写一个程序,读入、存储以及输出下列5种类型的字符串,每个字符串占一行,字符串间不能有空格。

    • 类型1:一串小写字母,后跟一个数字(如 number1)
    • 类型2:两个单词,每个单词的第一个字母大写,单词间用-分隔(如Seven-Up)
    • 类型3:小数(如7.35)
    • 类型4:一串大小写字母以及空格(如Oliver Hardy)
    • 类型5:一串除了空格及数字外的任何字符(如floating-point)

    以下是这5种输入类型的例子,要分开读入这些字符串:

    baby1on5Jhon-Boy3.14159Stan Laurel'Winner!'

    #include <stdio.h>
    
    int main()
    {
        char str[5][100] = {""};
        for (int i = 0; i < 5; i++)
        {
            printf("%d -> ", i + 1);
            gets(str[i]);
        }
    
        for (int i = 0;i < 5; i++)
        {
            printf("%s", str[i]);
        }
        printf("\n");
        return 0;
    }
    

    习题10.2 编写一个程序,读入以下数值,并输出它们的和:

    $3.50, $ 0.75, %9.95, %2. 50

    #include <stdio.h>
    
    int main()
    {
        float number[4] = { 0.0f };
        float sum = 0.0f;
        char str[100] = "";
        int i = 0;
        for ( ; i < 99; )
        {
            str[i] = getchar();
            if (('0' <= str[i] && str[i] <= '9') || str[i] == '.')
            {
                i++;
            }
            else if (str[i] == '\n')
            {
                break;
            }
        }
        str[i] = '\0';
    
        sscanf(str, "%4f%4f%4f%4f", &number[0], &number[1], &number[2], &number[3]);
    
        for (int i = 0;i < 4; i++)
        {
            sum += number[i];
        }
    
        printf("average = %.2f\n", sum / 4);
        return 0;
    }
    

    习题10.3 定义一个函数,其参数是一个double类型的数组,输出该数组和数组中的元素个数。这个函数的原型如下:

    void show(double array[], int array_size, int field_width);

    输出的值5个一行,每个值有两位小数,字符宽度是12。在程序中使用这个函数输出从1.5到4.5的值,每次增加0.3(如:1.5、1.8、2.1、...、4.5)。

    #include <stdio.h>
    
    void show(double[], int, int);
    
    int main()
    {
        double array[] = {1.5, 1.8, 2.1, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.2, 4.5};
        show(array, 11, 12);
    
        return 0;
    }
    
    void show(double array[], int array_size, int field_width)
    {
        char buffer[10] = "";
        sprintf(buffer, "%%%d.2f", field_width);
        for (int i = 0; i < array_size; i++)
        {
            if (i % 5 == 0) {
                printf("\n");
            }
            printf(buffer, array[i]);
        }
        printf("\n");
    }
    

    习题10.4 定义一个函数,使用getchar()函数从stdin中读入一个字符串,这个字符串用特定的字符终止,这个特定的终止字符作为第二个变元传给这个函数。因此,函数的原型如下:

    char *getString(char *buffer, char end_char);

    返回值是一个指针,它是这个函数的第一个变元。编写一个程序,使用这个函数从键盘上读取并输出5个以冒号终止的字符串。

    #include <stdio.h>
    
    char *getString(char *, char);
    
    int main()
    {
        char buffer[5][100];
        for (int i = 0; i < 5; i++)
        {
            getString(buffer[i], ':');
        }
    
        for (int i = 0; i < 5; i++)
        {
            printf("%s\n", buffer[i]);
        }
    
        return 0;
    }
    
    char *getString(char *buffer, char end_char)
    {
        char *pStr = buffer;
        char ch = '\0';
        for (;;)
        {
            ch = getchar();
            if (ch != end_char) {
                *pStr++ = ch;
            }
            else
            {
                *pStr = '\0';
                break;
            }
        }
        return buffer;
    }
    

    第11章 结构化数据

    习题11.1 定义一个结构类型Length,它用码、英尺和英寸表示长度。定义一个add()函数,它相加两个Length变元,返回Length类型的总和。定义第二个函数show(),显示其Length变元的值。编写一个程序,从键盘输入任意个单位的码、英尺以及英寸的长度,使用Length类型、add()、和show()函数去汇总这些长度,并输出总长。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    struct Length
    {
        int yard;
        int foot;
        int inch;
    };
    
    struct Length *add(struct Length *, struct Length *);
    void show(struct Length *);
    
    int main()
    {
        struct Length *pSum = NULL;
        struct Length **pLength = NULL;
        int count = 0;
        char ch = '\0';
    
        pSum = malloc(sizeof(struct Length));
        pSum->yard = 0;
        pSum->foot = 0;
        pSum->inch = 0;
        pLength = (struct Length **) malloc(sizeof(struct Length *));
        do
        {
            count++;
            pLength = (struct Length **) realloc(pLength, count * sizeof(struct Length *));
            *(pLength + count - 1) = malloc(sizeof(struct Length));
            printf("请输入Length:\n");
            printf("Length.yard -> ");
            scanf("%d", &(*(pLength + count - 1))->yard);
            printf("Length.foot -> ");
            scanf("%d", &(*(pLength + count - 1))->foot);
            printf("Length.inch -> ");
            scanf("%d", &(*(pLength + count - 1))->inch);
            getchar();
            ch = getchar();
        } while(tolower(ch) == 'y');
    
        for (int i = 0; i < count; i++)
        {
            pSum = add(pSum, *(pLength + i));
        }
    
        show(pSum);
        return 0;
    }
    
    struct Length *add(struct Length *a, struct Length *b)
    {
        struct Length *pLength = (struct Length *)malloc(sizeof(struct Length));
    
        pLength->yard = a->yard + b->yard;
        pLength->foot = a->foot + b->foot;
        pLength->inch = a->inch + b->inch;
    
        return pLength;
    }
    
    void show(struct Length *length)
    {
        printf("yard=%d, foot=%d, inch=%d\n", length->yard, length->foot, length->inch);
    }
    

    习题11.2 定义一个结构类型,它含有一个人的姓名及电话号码。在程序中使用这个结构,输入一个或多个姓以及对应的电话号码,将输入的数据存储到一个结构数组中。程序允许输入姓氏,输出对应于该姓氏的所有电话号码,可以选择是否要输出所有的姓名及他们的电话号码。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    struct Contacts
    {
        char *name;
        int phoneCount;
        char **phone;
    };
    
    struct Contacts *newContacts();
    void printContacts(struct Contacts *);
    
    int main()
    {
        struct Contacts **pContacts = NULL;
        char isContinue = '\0';
        int count = 0;
        char buffer[100] = "";
    
        pContacts = malloc(sizeof(struct Contacts *));
        do
        {
            count++;
            pContacts = realloc(pContacts, count * sizeof(struct Contacts *));
            *(pContacts + count - 1) = newContacts();
            printf("是否继续输入联系人信息(y/n):");
            isContinue = getchar();
            getchar();
        } while (tolower(isContinue) == 'y');
    
        printf("请输入姓名:");
        gets(buffer);
        for (int i = 0; i < count; i++)
        {
            if (strcmp(buffer, (*(pContacts + i))->name) == 0) {
                printContacts(*(pContacts + i));
            }
        }
    
        return 0;
    }
    
    struct Contacts *newContacts()
    {
        struct Contacts *pContacts = NULL;
        char buffer[100] = "";
        int count = 0;
        char isContinue = '\0';
        pContacts = malloc(sizeof(struct Contacts));
    
        printf("请输入姓名:");
        gets(buffer);
        pContacts->name = malloc((strlen(buffer) + 1) * sizeof(char));
        strcpy(pContacts->name, buffer);
    
        pContacts->phone = malloc(sizeof(char *));
        do
        {
            count++;
            pContacts->phone = realloc(pContacts->phone, count * sizeof(char *));
            printf("请输入电话号码:");
            gets(buffer);
            *(pContacts->phone + count - 1) = malloc((strlen(buffer) + 1) * sizeof(char));
            strcpy(*(pContacts->phone + count - 1), buffer);
            printf("是否继续输入电话号码(y/n):");
            isContinue = getchar();
            getchar();
        } while(tolower(isContinue) == 'y');
        pContacts->phoneCount = count;
        return pContacts;
    }
    
    void printContacts(struct Contacts *pContacts)
    {
        printf("==========\n");
        printf("name = %s\n", pContacts->name);
        for (int i = 0; i < pContacts->phoneCount; i++)
        {
            printf("phone = %s\n", *(pContacts->phone + i));
        }
        printf("==========\n");
    }
    

    习题11.3 修改上一题的程序,将数据存储到链表中,按照姓名的字母顺序由小到大排序。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    struct Contacts
    {
        char *name;
        int phoneCount;
        char **phone;
        struct Contacts *next;
    };
    
    struct Contacts *newContacts();
    void printContacts(struct Contacts *);
    
    int main()
    {
        struct Contacts *pHead = NULL;
        struct Contacts *pCurrent = NULL;
        struct Contacts *p = NULL;
        struct Contacts *q = NULL;
        char isContinue = '\0';
        int count = 0;
    
        pHead = malloc(sizeof(struct Contacts));
        do
        {
            count++;
            pCurrent = newContacts();
            if (count == 1) {
                pHead->next = pCurrent;
            }
            else
            {
                p = pHead;
                q = pHead->next;
                while (q) {
                    if (strcmp(pCurrent->name, q->name) > 0) {
                        p = q;
                        q = q->next;
                    }
                    else
                    {
                        break;
                    }
                }
                pCurrent->next = q;
                p->next = pCurrent;
            }
            printf("是否继续输入联系人信息(y/n):");
            isContinue = getchar();
            getchar();
        } while (tolower(isContinue) == 'y');
    
        pCurrent = pHead;
        for (int i = 0; i < count; i++)
        {
            printContacts(pCurrent->next);
            pCurrent = pCurrent->next;
        }
    
        return 0;
    }
    
    struct Contacts *newContacts()
    {
        struct Contacts *pContacts = NULL;
        char buffer[100] = "";
        int count = 0;
        char isContinue = '\0';
        pContacts = malloc(sizeof(struct Contacts));
    
        printf("请输入姓名:");
        gets(buffer);
        pContacts->name = malloc((strlen(buffer) + 1) * sizeof(char));
        strcpy(pContacts->name, buffer);
    
        pContacts->phone = malloc(sizeof(char *));
        do
        {
            count++;
            pContacts->phone = realloc(pContacts->phone, count * sizeof(char *));
            printf("请输入电话号码:");
            gets(buffer);
            *(pContacts->phone + count - 1) = malloc((strlen(buffer) + 1) * sizeof(char));
            strcpy(*(pContacts->phone + count - 1), buffer);
            printf("是否继续输入电话号码(y/n):");
            isContinue = getchar();
            getchar();
        } while(tolower(isContinue) == 'y');
        pContacts->phoneCount = count;
        pContacts->next = NULL;
        return pContacts;
    }
    
    void printContacts(struct Contacts *pContacts)
    {
        printf("==========\n");
        printf("name = %s\n", pContacts->name);
        for (int i = 0; i < pContacts->phoneCount; i++)
        {
            printf("phone = %s\n", *(pContacts->phone + i));
        }
        printf("==========\n");
    }
    

    习题11.4 编写一个程序,从键盘上输入一段文本,然后使用结构计算每个单词的出现次数。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    #include <stdbool.h>
    
    struct WordUnit
    {
        int count;
        char *word;
        struct WordUnit *next;
    };
    
    void statistics(struct WordUnit *, char *);
    void printWordUnit(struct WordUnit *);
    
    int main()
    {
        char buffer[100] = "";
        char temp[10] = "";
        struct WordUnit *pHead = NULL;
        struct WordUnit *pCurrent = NULL;
    
        pHead = malloc(sizeof(struct WordUnit));
        pHead->next = NULL;
        gets(buffer);
    
        for (int i = 0, j = 0; i < strlen(buffer) && j < strlen(buffer);)
        {
            for (int i = 0; i < 10; i++)
            {
                temp[i] = '\0';
            }
    
            if (isalpha(buffer[i]))
            {
                for (j = i; j < strlen(buffer) && isalpha(buffer[j]); j++)
                    ;
    
                for (int k = i; k < j; k++)
                {
                    temp[k - i] = buffer[k];
                }
                statistics(pHead, temp);
                i = j;
            }
            else
            {
                i++;
            }
        }
    
        printWordUnit(pHead->next);
    
        return 0;
    }
    
    void statistics(struct WordUnit *head, char *word)
    {
        bool isNewWord = true;
        struct WordUnit *p = head->next;
        struct WordUnit *q = head;
        while (p) {
            if (strcmp(p->word, word) == 0) {
                p->count++;
                isNewWord = false;
                break;
            }
            q = p;
            p = p->next;
        }
        if (isNewWord) {
            p = malloc(sizeof(struct WordUnit));
            p->count = 1;
            p->word = malloc((strlen(word) + 1) * sizeof(char));
            strcpy(p->word, word);
            q->next = p;
        }
    }
    
    void printWordUnit(struct WordUnit *p)
    {
        while (p) {
            printf("%10s %2d\n", p->word, p->count);
            p = p->next;
        }
    }
    

    习题11.5 编写一个程序,读取任意多个姓名。用一个二叉树按升序输出所有的姓名,排序时先排姓氏,后排名字(例如 Ann Choosy 在 Bill Champ 的后面,在 Arthur Choosy 的前面)。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    struct Name
    {
        char *firstName;
        char *lastName;
        struct Name *leftChild;
        struct Name *rightChild;
    };
    
    struct Name *readName();
    void printName(struct Name *);
    void insertName(struct Name *, struct Name *);
    
    int main()
    {
        struct Name *root = NULL;
        char isContinue = '\0';
        int count = 0;
        do
        {
            if (count == 0) {
                root = readName();
            }
            else
            {
                insertName(root, readName());
            }
            count++;
            printf("是否继续输入姓名:");
            isContinue = getchar();
            getchar();
        } while(tolower(isContinue) == 'y');
    
        printName(root);
    
        return 0;
    }
    
    struct Name *readName()
    {
        struct Name *p = malloc(sizeof(struct Name));
        char buffer[20] = "";
        printf("请输入姓氏:");
        gets(buffer);
        p->lastName = malloc((strlen(buffer) + 1) * sizeof(char));
        strcpy(p->lastName, buffer);
        printf("请输入名字:");
        gets(buffer);
        p->firstName = malloc((strlen(buffer) + 1) *sizeof(char));
        strcpy(p->firstName, buffer);
        p->leftChild = NULL;
        p->rightChild = NULL;
    
        return p;
    }
    
    void printName(struct Name *p)
    {
        if (p != NULL) {
            printName(p->leftChild);
            printf("%s %s\n", p->lastName, p->firstName);
            printName(p->rightChild);
        }
        return;
    }
    
    void insertName(struct Name *root, struct Name *p)
    {
        if (root != NULL) {
            if (strcmp(root->lastName, p->lastName) >= 0)
            {
                if (root->leftChild != NULL) {
                    insertName(root->leftChild, p);
                }
                else{
                    root->leftChild = p;
                }
            }
            else
            {
                if (root->rightChild != NULL) {
                    insertName(root->rightChild, p);
                }
                else
                {
                    root->rightChild = p;
                }
            }
        }
        return ;
    }
    

    第12章 处理文件

    习题12.1 编写一个程序,将任意数目的字符串写入文件。字符串由键盘输入,程序不能删除这个文件,因为下一题还要使用这个文件。

    #include <stdio.h>
    #include <stdbool.h>
    
    int main()
    {
        char buffer[100] = "";
        const char fileName[10] = "data.txt";
        FILE *pFile = NULL;
    
        pFile = fopen(fileName, "a");
        if (!pFile) {
            printf("打开文件失败\n");
            return 1;
        }
        do {
            fgets(buffer, 100, stdin);
            if (buffer[0] == '\n')
            {
                break;
            }
            fputs(buffer, pFile);
        } while (true);
    
        fclose(pFile);
        return 0;
    }
    

    习题12.2 编写一个程序,读取上一题创建的文件。每次都以反向的顺序读取一个字符串,然后按照读取顺序将它们写入一个新文件。例如,程序读取最后一个字符串,将它写入新文件,再读取倒数第二个字符串,将它写入新文件,依次类推。

    #include <stdio.h>
    #include <stdbool.h>
    
    int count(char *);
    
    int main()
    {
        char buffer[100] = "";
        char fileName[10] = "data.txt";
        char fileNameNew[10] = "data2.txt";
        FILE *pFile = NULL;
        FILE *pFileNew = NULL;
    
        pFile = fopen(fileName, "a");
        if (!pFile) {
            printf("打开文件失败\n");
            return 1;
        }
        do {
            fgets(buffer, 100, stdin);
            if (buffer[0] == '\n')
            {
                break;
            }
            fputs(buffer, pFile);
        } while (true);
    
        fclose(pFile);
    
        pFile = fopen(fileName, "r");
        if (!pFile) {
            printf("打开文件失败\n");
            return 1;
        }
        fclose(pFile);
    
        pFileNew = fopen(fileNameNew, "a");
        for (int i = count(fileName) - 1; i >= 0; i--)
        {
            pFile = fopen(fileName, "r");
            for (int j = 0; j < i; j++)
            {
                fgets(buffer, 100, pFile);
            }
    
            fgets(buffer, 100, pFile);
            fclose(pFile);
            fputs(buffer, pFileNew);
        }
        fclose(pFileNew);
    
        return 0;
    }
    
    int count(char *pName)
    {
        FILE *pFile = NULL;
        pFile = fopen(pName, "r");
        int count = 0;
        char buffer[100] = "";
        while (fgets(buffer, 100, pFile)) {
            count++;
        }
        fclose(pFile);
        return count;
    }
    

    习题12.3 编写一个程序,从键盘读入姓名和电话号码,将它们写入一个文件。如果这个文件不存在,就写入一个新文件。如果文件已存在,就将它们写入该文件。这个程序需要提供列出所有数据的选项。

    #include <stdio.h>
    
    struct Contacts
    {
        char name[20];
        char phone[3][15];
    };
    
    char fileName[20] = "contacts.txt";
    
    void add();
    
    int main()
    {
        add();
        return 0;
    }
    
    void add()
    {
        struct Contacts con;
        FILE *pFile = NULL;
        pFile = fopen(fileName, "a");
        printf("\n请输入姓名:");
        fgets(con.name, 20, stdin);
        for (int i = 0; i < 3; i++)
        {
            printf("请输入第 %d 个电话号码:", i + 1);
            fgets(con.phone[i], 15, stdin);
        }
    
        fprintf(pFile, "%20s%15s%15s%15s", con.name, con.phone[0], con.phone[1], con.phone[2]);
        fclose(pFile);
    }
    

    习题12.4 扩展上一题的程序,提取对应指定的姓名的所有电话号码。这个程序允许进一步查询,添加新的姓名和电话号码,删除已有的项。

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    #include <stdbool.h>
    
    struct Contacts
    {
        char name[20];
        char phone[3][15];
    };
    
    char fileName[20] = "contacts.txt";
    
    void add();
    void printContacts(struct Contacts *);
    bool searchByContactsName(char *, struct Contacts *, char *);
    void printAll(char *);
    void deleteByContactsName(char *fileName, char *contactsName);
    
    int main()
    {
        // 此处省略了函数的调用
        return 0;
    }
    
    void add()
    {
        struct Contacts con;
        FILE *pFile = NULL;
        pFile = fopen(fileName, "a");
        printf("\n请输入姓名:");
        fgets(con.name, 20, stdin);
        for (int i = 0; i < 3; i++)
        {
            printf("请输入第 %d 个电话号码:", i + 1);
            fgets(con.phone[i], 15, stdin);
        }
    
        fprintf(pFile, "%20s%15s%15s%15s", con.name, con.phone[0], con.phone[1], con.phone[2]);
        fclose(pFile);
    }
    
    void printContacts(struct Contacts *p)
    {
        printf("姓名:%s\n\t电话1:%s\n\t电话2:%s\n\t电话3:%s\n", p->name, p->phone[0], p->phone[1], p->phone[2]);
    }
    
    void deleteByContactsName(char *fileName, char *name)
    {
        FILE *pFileOld = NULL;
        FILE *pFileNew = NULL;
        struct Contacts c;
        char tempFileName[20] = "temp.txt";
        if (!searchByContactsName(fileName, &c, name))
            return;
    
        pFileOld = fopen(fileName, "r");
        pFileNew = fopen(tempFileName, "a");
    
        while(fscanf(pFileOld, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]) != EOF)
        {
            if (strcmp(name, c.name)) {
                fprintf(pFileNew, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]);
            }
        }
    
        fclose(pFileOld);
        fclose(pFileNew);
    
        remove(fileName);
        rename(tempFileName, fileName);
    }
    
    bool searchByContactsName(char *fileName, struct Contacts *c, char *name)
    {
        FILE *pFile = fopen(fileName, "r");
        while(fscanf(pFile, "%20s%15s%15s%15s", c->name, c->phone[0], c->phone[1], c->phone[2]) != EOF)
        {
            if (strcmp(c->name, name) == 0) {
                return true;
            }
        }
        return false;
    
    }
    
    void printAll(char *fileName)
    {
        struct Contacts c;
        FILE *pFile = NULL;
        pFile = fopen(fileName, "r");
        while(fscanf(pFile, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]) != EOF)
        {
            printContacts(&c);
        }
        fclose(pFile);
    }
    

    第13章 支持功能

    习题13.1 定义一个COMPARE(x, y)宏。如果x<y,就返回-1,如果x==y,就返回0,如果x>y就返回1.编写一个例子,说明这个宏可以正常工。这个宏会优于完成相同任务的函数码?

    #include <stdio.h>
    
    #define COMPARE(x, y) (x) > (y) ? 1 : ((x) == (y) ? 0 : -1)
    
    int main()
    {
        printf("%d\n", COMPARE(5, 3));
        return 0;
    }
    

    习题13.2 定义一个函数,返回含有当前时间的字符串,如果变元是0,它的格式就是12小时制(a.m./p.m.),如果变元是1,它的格式就是24小时制。编写一个程序,说明这个函数可以正常工作。

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    char *getTimeString(int format);
    
    int main()
    {
        printf("%s\n%s\n", getTimeString(0), getTimeString(1));
        return 0;
    }
    
    char *getTimeString(int format)
    {
        char *pStr = NULL;
        char buffer[20] = "";
        struct tm *t = NULL;
        time_t val = time(NULL);
        t = localtime(&val);
        if (format == 0) {
            sprintf(buffer, "%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
        }
        else
        {
            sprintf(buffer, "%02d:%02d:%02d", t->tm_hour > 12 ? t->tm_hour - 12 : t->tm_hour, t->tm_min, t->tm_sec);
        }
    
        pStr = (char *)malloc((strlen(buffer) + 1) * sizeof(char));
        strcpy(pStr, buffer);
        return pStr;
    }
    

    习题13.3 定义一个print_value(expr)宏,在新的一行上输出 exp = result,其中result的值由expr算出。编写一个例子,说明这个宏可以正常工作。

    #include <stdio.h>
    
    #define print_value(expr) printf("exp = %d\n", expr)
    
    int main()
    {
        print_value(3 + 2);
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:《C语言入门经典(第4版)》课后练习参考答案

        本文链接:https://www.haomeiwen.com/subject/wfceyttx.html