欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言程序设计:现代方法(第2版)第三章全部习题答案

程序员文章站 2022-04-04 14:59:50
前言 本人在通过《C语言程序设计:现代方法(第2版)》自学C语言时,发现国内并没有该书完整的课后习题答案,所以就想把自己在学习过程中所做出的答案分享出来,以供大家参考。这些答案是本人自己解答,并参考GitHub上相关的分享和Chegg.com相关资料。因为并没有权威的答案来源,所以可能会存在错误的地 ......

前言

本人在通过《C语言程序设计:现代方法(第2版)》自学C语言时,发现国内并没有该书完整的课后习题答案,所以就想把自己在学习过程中所做出的答案分享出来,以供大家参考。这些答案是本人自己解答,并参考GitHub上相关的分享和Chegg.com相关资料。因为并没有权威的答案来源,所以可能会存在错误的地方,如有错误还希望大家能够帮助指出。

第三章练习题和编程题答案

练习题

3.1节

1.下面的printf函数调用产生的输出分别是什么?

(a)  printf("6d,%4d", 86, 1040);

(b) printf("%12.5e", 30.253);

(c) printf("%.4f", 83.162);

(d) printf("%-6.2g", .0000009979);

答:

(a) ┗━┛┗━┛┗━┛┗━┛86, 1040                   “%6d”表示右对齐、最小6个字段宽,数字86只占了2个字段宽,所以前面用4个空格(┗━┛)补齐。同理“%4d”也是右对齐、最小4个字段宽,数字1040正好为4个字段宽,所有没有空格。
(b) 3.02530e+001                                             %12.5e”表示右对齐、最小12个字段宽,同时小数点后显示5位数字,因为.0253不足5位,所以小数部分末尾会添加零占位。
(c) 83.1620                                                       %.4f”表示小数点后显示4位,因为.162不足4位,所以小数部分末尾会添加零占位。
(d) 1e-006                                                        %-6.2g”表示左对齐、最小6个字段宽,.2表示可以显示最大2个(去掉小数点后)有效数字。之所以显示1e是因为数字9979只能显示99这两个有效数字,所有后面的7会四舍五入向前进位,这样实际要显示的 数字就从.0000009979变成了.0000010000,所以结果显示为1e,如果将.2变为.3的话就会显示为9.98e-007。在%f%e当中,如果需要舍弃小数点后部分数字,同样会使用这种四舍五入的显示方式。

 

2.编写printf函数调用,以下列格式显示float型变量x:

(a) 指数表示形式,字段宽度8,左对齐,小数点后保留1位数字。

(b) 指数表示形式,字段宽度10,右对齐,小数点后保留6位数字。

(c) 定点十进制表示形式,字段宽度8,左对齐,小数点后保留3位数字。

(d) 定点十进制表示形式,字段宽度6,右对齐,小数点后无数字。

答:

(a)  printf("%-8.1e", x);

(b)  printf("%10.6e", x);

(c)  printf("%-8.3f", x);

(d)  printf("6.0f", x);

 

3.2节

3.说明下列每对scanf格式串是否等价?如果不等价,请指出它们的差异。

(a) "%d"与" %d"

(b)"%d-%d-%d"与"%d -%d -%d"

(c)"f"与"%f "

(d)"%f,%f"与"%f, %f"

答:

(a) 等价,因为scanf在开始寻找数的时候会忽略掉空格,所以即使在前面添加任意个空格均不影响结果。

(b)不等价,虽然在开始是是scanf会忽略掉空格,但是开始读入之后并不会忽略。所以前者%d-%d-%d中不能在“-”之间加入任何空格,否则会异常退出,而后者%d -%d -%d则可以在“-”之间加入或不加入任意个空格

(c)不等价,第二个格式串中以空格作为结尾,虽然不影响录入%f中的数字,但是第二个格式串并不会在回车或空格后结束,它会一直等到读入第一个非空字符时才会结束。而第一个%f会在遇到空格或回车之类的符号后就结束运行。

(d)不等价,与(b)理由相同,第一个格式串中逗号直接不能加入任何空格,而第二个则可以加入0个或n个空格。

 

4.假设scanf函数调用的格式如下:

scanf("%d%f%d", &i, &x, &j);

如果用户录入

10.3 5 6

调用执行后,变量i、x和j的值分别是多少?(假设变量i和变量j都是int型,而变量x是float型。)

答:

最后的结果是i=10,x=0.3,j=5,

首先因为i是int型所以scanf会读入“10.”,但因为后面出现了小数点(“.”),而i中不能有小数点,所以只将10存入一种并将小数点“放回”去。

之后x是float型,但读入.3后因为遇到了非数字空格,所以scanf会将.3存入x中,而将空格“放回”。

最后的变量j在读取时会像跳过空白字符,直到遇到非空白字符5,而5之后又是非数字的空格,所以只会将5存入变量j中。

而因为此时这个scanf函数结束了,所以最后的数字6会被保留到下一次scanf函数调用时再读取。

 

 5.假设scanf函数调用的是格式如下:

scanf("%f%d%f", &x, &i, &y);

如果用户输入

12.3 45.6 789

调用执行后,变量x、i和y的值分别是多少?(假设变量x和变量y都是float型,变量i是int型。)

答:

最后的结果是x=12.3,i=45,y=0.6

与上一道题类似,首先因为x是float型,所以scanf会读入“12.3”,之后遇到空格,此时结束读入并将12.3存入x中。

之后因为i是int型不能有小数点,所以scanf在读入“45.6”时只会将45存入i中,并将“.6”放回。

y是float型可以有小数点,所以scanf会将上次没有读入的“.6”存入y中,并在遇到空格时结束这次读入。

因为此时scanf函数已经执行完毕,所以最后的789会在下次scanf执行时才被读入。

 

6.指出如何修改3.2节中的addfrac.c程序,使用户可以输入在字符/的前后都有空格的分数

答:

 1 /*只需要在原程序中的/前后各加入一个空格即可 */
 2 /* Adds two fractions */
 3 
 4 #include <stdio.h>
 5 
 6 int main(void)
 7 {
 8     int num1, denom1, num2, denom2, result_num, result_denom;
 9 
10     printf("Enter first fraction: ");
11     scanf("%d / %d", &num1, &denom1);     /*至于要在原程序中的/前后各加入一个空格即可 */ 
12 
13     printf("Enter second fraction: ");
14     scanf("%d / %d", &num2, &denom2);
15 
16     result_num = num1 * denom2 + num2 * denom1;
17     result_denom = denom1 * denom2;
18     printf("The sum is %d/%d\n", result_num, result_denom);
19 
20     return 0;
21 }

 

编程题

1.编写一个程序,以月/日/年(即mm/dd/yy)的格式接受用户录入的日期信息,并以年月日(即yy/mm/dd)的格式将其显示出来:

Enter a date (mm/dd/yyyy): 2/17/2011

You entered the date 20110217

答:

 1 /*月日年转成年月日*/
 2 #include <stdio.h>
 3 
 4 int main(void)
 5 {
 6     int day = 0, month = 0, year = 0;
 7 
 8     printf("Enter a date (mm/dd/yyyy): ");
 9     scanf("%d/%d/%d", &month, &day, &year);
10 
11     printf("You entered the date %.2d%.2d%d", year, month, day);   /*月和日用%.2d显示,保证月份和日期会以两位数形式显示 */
12 
13     return 0;
14 }

 

2.编程一个程序,对于用户录入的产品信息进行格式化,程序会话应类似下面这样:

Enter item number: 583
Enter unit price: 13.5
Enter purchase date (mm/dd/yyyy): 10/24/2010
Item  Unit       Purchase
    price     Date
583   $   13.50    10/24/2010

其中,产品编号和日期项采用左对齐方式,单位价格采用右对齐方式,允许最大取值为9999.99的美元。提示:各个列使用制表符控制。

答:

 1 /*输入信息并显示,产品编号和日期左对齐,价格右对齐*/
 2 
 3 #include <stdio.h>
 4 
 5 int main(void)
 6 {
 7     /* 声明item number变量item_num,unit price变量price,日期变量day、month和year */
 8     int item_num = 0, day = 0, month = 0, year = 0;
 9     /* unit price包含小数点,所以其变量应为float型 */
10     float price = 1.0f;
11 
12     /* 用户输入数据,程序录入对应变量中 */
13     printf("Enter item number: ");
14     scanf("%d", &item_num);
15     printf("Enter unit price: ");
16     scanf("%f", &price);
17     printf("Enter purchase date (mm/dd/yyyy): ");
18     scanf("%d/%d/%d", &month, &day, &year);
19 
20     printf("Item\t\tUnit\t\tPurchase\n");   /* 第一行显示,中间通过两个制表符\t分隔 */
21     printf("\t\tprice\t\tDate\n");          /* 第二行显示,中间通过两个制表符\t分隔 */
22     /* 编号和日期是左对齐,所以要在前面加上负号。价格采用%7.2f显示,是因为最大价格是9999.99共七位,在小于七位时用空格占位,.2则是保证小数点后只显示2位数字。 */
23     /* 日期中的.2是为了让最少以两位数形式显示,年份为四位数,所以采用.4保证最少显示四位数 */
24     printf("%-d\t\t$%7.2f\t%-.2d/%-.2d/%-.4d\n", item_num, price, month, day, year);
25 
26     return 0;
27 }

 

3.图书用国际标准书号(ISBN)进行标识。2007年1月1日之后分配的ISBN包含13位数字(旧的ISBN使用10位数字),分为5组,如978-0-393-97950-3.第一组(GS1)目前为978或979.第二组(组标识)指明语言或者原出版社国(如0和1用于英语的国家)。第三组(出版商编号)便是出版商(393是W.W.Norton出版社的编号)。第四组(产品编号)是由出版商分配的用于识别具体哪一本书的(97950)。ISBN的末尾是一个校验数字,用于验证前面数字的准确性。编写一个程序来分解用户录入的ISBN信息:

Enter ISBN: 978-0-393-97950-3
GS1 prefix: 978
Group identifier: 0
Publish code: 393
Item number: 97950
Check digit: 3

注意:每组中数字的个数是可变的,不能认为每组的长度都与示例一样。用实际的ISBN值(通常放在书的封底和版权页上)测试你编写的程序。

答:

 1 /*ISBN分解*/
 2 
 3 #include <stdio.h>
 4 
 5 int main(void)
 6 {
 7     /* 第一组数字的变量定义为gs1,第二组数字的变量定义为group_id,第三组数字的变量定义为pub_code,第四组数字的变量定义为item_num,校验位定义为check_d */
 8     int gs1 = 0, group_id = 0, pub_code = 0, item_num = 0, check_d = 0;
 9 
10     printf("Enter ISBN: ");
11     /* 每组数字看成一个整体,通过-来识别每组数字,并将其存入对应的变量中,这样每组数字个数即使发生变化也能正确的显示出来 */
12     scanf("%d-%d-%d-%d-%d", &gs1, &group_id, &pub_code, &item_num, &check_d);
13 
14     /* 直接将每组变量分别显示出来即可 */
15     printf("GS1 prefix: %d\nGroup identifier: %d\nPublish code: %d\nItem number: %d\nCheck digit: %d\n", gs1, group_id, pub_code, item_num, check_d);
16 
17     return 0;
18 }

 

4.编写一个程序,提示用户以[(xxx)xxx-xxx]的格式输入电话号码,并以xxx.xxx.xxxx的格式显示该号码:

Enter phone number [(xxx) xxx-xxxx]: (404) 817-6900
You entered: 404.817.6900

答:

 1 /*输入电话号码(xxx) xxx-xxxx并转换格式显示xxx.xxx.xxxx */
 2 
 3 #include <stdio.h>
 4 
 5 int main(void)
 6 {
 7     /* 将电话号码拆分成3组,分别定义成num1、num2和num3 */
 8     int num1 = 0, num2 = 0, num3 = 0;
 9 
10     printf("Enter phone number [(xxx) xxx-xxxx]: ");
11     /* 根据提示的格式分别将3组数字存入变量中 */
12     scanf("(%d) %d-%d", &num1, &num2, &num3);
13 
14     printf("You entered: %d.%d.%d\n", num1, num2, num3);
15 
16     return 0;
17 }

 

5.编写一个程序,要求用户(按任意次序)输入从1到16的所有整数,然后用4×4矩阵的形式将它们显示出来,再计算每行、每列和每条对角线上的和:

Enter the numbers from 1 to 16 in any order: 16 3 2 13 5 10 11 8 9 6 7 12 4 15 14 1
16    3      2    13
5    10    11      8
9      6      7    12
4    15    14      1


Row sums: 34 34 34 34
Column sums: 34 34 34 34
Diagonal sums: 34 34

如果行、列和对角线上的和都一样(如本例所示),则称这些数组成一个幻方(magic square)。这里给出的幻方出现于艺术家和数学家Albrecht Dürer在1514年的一幅画中。(注意,矩阵的最后一行中间的两个数给出了该画的创作年代。)

答:

 1 /*输入1到16所有整数,以4*4显示,并计算每行、每列、和对角线的和 */
 2 
 3 #include <stdio.h>
 4 
 5 int main(void)
 6 {
 7     /* 定义十六个数字的变量,从num1到num16 */
 8     int num1 = 0, num2 = 0, num3 = 0, num4 = 0, num5 = 0, num6 = 0, num7 = 0, num8 = 0;
 9     /* 拆成两行定义是因为写在一行里实在是太长了,不方便阅读 */
10     int num9 = 0, num10 = 0, num11 = 0, num12 = 0, num13 = 0, num14 = 0, num15 = 0, num16 = 0;
11     /* 定义4×4矩阵的每行和的变量,从row1到row4 */
12     int row1 = 0, row2 = 0, row3 = 0, row4 = 0;
13     /* 定义4×4矩阵的每列和的变量,从col1到col4 */
14     int col1 = 0, col2 = 0, col3 = 0, col4 = 0;
15     /* 定义两个对角线和的变量dia1和dia2 */
16     int dia1 = 0, dia2 = 0;
17 
18     printf("Enter the numbers from 1 to 16 in any order: ");
19     /* 将十六个数字分别存入到16个变量里 */
20     scanf("%d%d%d%d%d%d%d%d", &num1, &num2, &num3, &num4, &num5, &num6, &num7, &num8);
21     /* 同样因为太长了,所以拆成两行写 */
22     scanf("%d%d%d%d%d%d%d%d", &num9, &num10, &num11, &num12, &num13, &num14, &num15, &num16);
23 
24     /* 显示出矩阵,根据题目示例,每个数字应该保证两个字符宽,右对齐。通过制表符来使每行和每列对齐 */
25     printf("%2d\t%2d\t%2d\t%2d\t\n%2d\t%2d\t%2d\t%2d\t\n", num1, num2, num3, num4, num5, num6, num7, num8);
26     printf("%2d\t%2d\t%2d\t%2d\t\n%2d\t%2d\t%2d\t%2d\t\n\n\n", num9, num10, num11, num12, num13, num14, num15, num16);
27 
28     /* 计算每行的和 */
29     row1 = num1 + num2 + num3 + num4;
30     row2 = num5 + num6 + num7 + num8;
31     row3 = num9 + num10 + num11 + num12;
32     row4 = num13 + num14 + num15 + num16;
33 
34     /* 计算每列的和 */
35     col1 = num1 + num5 + num9 + num13;
36     col2 = num2 + num6 + num10 + num14;
37     col3 = num3 + num7 + num11 + num15;
38     col4 = num4 + num8 + num12 + num16;
39 
40     /* 计算两个对角线的和 */
41     dia1 = num1 + num6 + num11 + num16;
42     dia2 = num4 + num7 + num10 + num13;
43 
44     /* 显示结果 */
45     printf("Row sums: %d  %d  %d  %d  \nColumn sums: %d  %d  %d  %d  \n", row1, row2, row3, row4, col1, col2, col3, col4);
46     printf("Diagonal sums: %d  %d  \n", dia1, dia2);
47 
48     return 0;
49 }

 

6.修改3.2节的addfrac.c程序,使用户可以同时输入两个分数,中间用加好隔开:

Enter two fractions separated by a plus sign: 5/6+3/4
The sum is: 38/24

答:

 1 /*同时输入两个分数并计算*/
 2 
 3 #include <stdio.h>
 4 
 5 int main(void)
 6 {
 7     /* 定义两个分数的变量,分子分别是x1和x2,分母是y1和y2 */
 8     int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
 9     /* 计算出的分子用result_num变量表示,分母用result_denom变量表示 */
10     int result_num = 0, result_denom = 0;
11 
12     printf("Enter two fractions separated by a plus sign: ");
13     /* 读取两个分数 */
14     scanf("%d/%d+%d/%d", &x1, &y1, &x2, &y2);
15 
16     /* 计算两个分数的和 */
17     result_num = x1 * y2 + x2 * y1;
18     result_denom = y1 * y2;
19     printf("The sum is: %d/%d\n", result_num, result_denom);
20 
21     return 0;
22 }