300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > C语言程序设计 现代设计方法_第4章代码 练习题及编程题答案

C语言程序设计 现代设计方法_第4章代码 练习题及编程题答案

时间:2024-06-09 16:34:11

相关推荐

C语言程序设计 现代设计方法_第4章代码 练习题及编程题答案

代码

4.1 upc.c

程序 计算通用产品代码的校验位

美国和加拿大的货物生产商都会在超市销售的每件商品上放置一个条形码。这种被称为通用产品代码 (Universal Product Code,UPC)的条形码可以识别生产商和产品。每个条形码表示一个12位的数,通常这个数会打印在条形码下面。例如,下的条形码来自Stouffer’s法式面包腊肠比萨的包装:

数字0 13800 15173 5 出现在条形码的下方。第1个数字表示商品的种类(大部分商品用0 或者7 表示,2 表示需要称量的商品,3 表示药品或与健康相关的商品,而5 表示赠品)。第一组5位数字用来标识生产商(13800是雀巢美国的冰冻食品公司的代码)。第二组5位数字用来标识产品(包括包装尺寸)。最后一位数字是“校验位”,它唯一的目的是用来帮助识别前面数字中的错误。如果条形码扫描出现错误,那么前11位数字可能会和最后一位数字不匹配,超市扫描机将拒绝整个条形码。

下面是一种计算校验位的方法:首先把第1位、第3位、第5位、第7位、第9位和第11位数字相加;然后把第2位、第4位、第6位、第8位和第10位数字相加;接着把第一次加法的结果乘以3,再和第二次加法的结果相加;随后再把上述结果减去1;相减后的结果除以10取余数;最后用9减去上一步骤中得到的余数。

还用Stouffer’s的例子,我们由0+3+0+1+1+3得到第一个和8,由1+8+0+5+7得到第二个和21。把第一个和乘以3后再加上第二个和得到45,减1得到44。把这个值除以10取余数为4。再用9减去余数4,结果为5。下面还有两个通用产品代码,试着手工算出各自的校验位(不要去厨房找答案):

Jif牌奶油花生黄油(18盎司): 0 51500 24128 ?

Ocean Spray牌蔓越桔果酱(8盎司):0 31200 01005 ?

要计算的检验位分别为8(Jif)和6(Ocean Spray)。

下面编写一个程序来计算任意通用产品代码的校验位。要求用户录入通用产品代码的前11位数字,然后程序显示出相应的校验位。为了避免混淆,要求用户分3部分录入数字:左边的第一个数字、第一组5位数字以及第二组5位数字。程序会话的形式如下所示:

Enter the first (single) digit: 0

Enter first group of five digits: 13800

Enter second group of five digits: 15173

Check digit: 5

程序不是按一个五位数来读取每组5位数字的,而是将它们读作5个一位数 。把数看成一个个独立的数字进行读取更为方便,而且也无需担心由于五位数过大而无法存储到int 型变量中。(某些编译器限定int 型变量的最大值为32 767。)为了读取单个的数字,我们使用带有%1d 转换说明的scanf 函数,其中%1d 匹配只有一位的整数。

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(void){int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5,first_sum, second_sum, total;printf("Enter the first (single) digit: ");scanf("%1d", &d);printf("Enter first group of five digits: ");scanf("%1d%1d%1d%1d%1d", &i1, &i2, &i3, &i4, &i5);printf("Enter second group of five digits: ");scanf("%1d%1d%1d%1d%1d", &j1, &j2, &j3, &j4, &j5);first_sum = d + i2 + i4 + j1 + j3 + j5;second_sum = i1 + i3 + i5 + j2 + j4;total = first_sum * 3 + second_sum;printf("Check digit: %d\n", 9 - (total - 1) % 10);return 0;}

练习题

4.1节

1. 给出下列程序片段的输出结果。假设i 、j 和k 都是int 型变量。

(a)i = 5; j = 3;printf("%d %d", i / j, i % j);(b)i = 2; j = 3;printf("%d", (i + 10) % j);(c)i = 7; j = 8; k = 9;printf("%d", (i + 10) % k / j);(d)i = 1; j = 2; k = 3;printf("%d", (i + 5) % (j + 2) / k);

Solution(a) 1 2 (b) 0 (c) 1 (d) 0

如果i 和j 都是正整数,(-i) / j 的值和-(i / j) 的值是否总一样?验证你的答案。

Solution

No. The C89 and C99 standards implement division of negative numbers differently:(-9)/7can produce -1 or -2 in C89, while-(9/7)will always produce -1. C99 will always truncate the remainder towards zero, however, so the answers produced by(-i)/jand-(i/j)will be equivalent.

下列表达式在C89中的值是多少?(如果表达式有多个可能的值,都列出来。)

(a) 8 / 5(b) -8 / 5(c) 8 / -5(d) -8 / -5

Solution(a) 1 (b) -1 or -2 (c) -1 or -2 (d) 1 or 2

对C99重复上题。

Solution(a) 1 (b) -1 (c) -1 (d) 1

下列表达式在C89中的值是多少?(如果表达式有多个可能的值,都列出来。)

(a) 8 % 5(b) -8 % 5(c) 8 % -5(d) -8 % -5

Solution(a) 3 (b) -3 or 5 (c) 3 or -5 (d) 3 or 5

对C99重复上题。

Solution(a) 1 (b) -3 (c) 3 (d) -3

本章计算UPC校验位的方法最后几步是:把总的结果减去1,相减后的结果除以10取余数,用9减去余数。换成下面的步骤也可以:总的结果除以10取余数,用10减去余数。这样做为什么可行?

Solution

The second, “simplified” algorithm could produce a check digit of10, which would not be valid.

如果把表达式9 - ((total - 1) % 10) 改成(10 -(total % 10)) % 10 ,upc.c 程序是否仍然正确?

Solution

Yes, both expressions would produce equal answers.

给出下列程序片段的输出结果。假设i 、j 和k 都是int 型变量。

(a)i = 7; j = 8;i *= j + 1;printf("%d %d", i, j);(b)i = j = k = 1;i += j += k;printf("%d %d %d", i, j, k);(c)i = 1; j = 2; k = 3;i -= j -= k;printf("%d %d %d", i, j, k);(d)i = 2; j = 1; k = 0;i *= j *= k;printf("%d %d %d", i, j, k);

Solution(a) 63 8 (b) 3 2 1 (c) 2 -1 3 (d) 0 0 0

给出下列程序片段的输出结果。假设i 和j 都是int 型变量。

(a)i = 6;j = i += i;printf("%d %d", i, j);(bi = 5;j = (i -= 2) + 1;printf("%d %d", i, j);(c)i = 7;j = 6 + (i = 2.5);printf("%d %d", i, j);(d)i = 2; j = 8;j = (i = 6) + (j = 3);printf("%d %d", i, j);

Solution(a) 12 12 (b) 3 4 (c) 2 8 (d) 6 9

给出下列程序片段的输出结果。假设i 、j 和k 都是int 型变量。

(a)i = 1;printf("%d ", i++ - 1);printf("%d", i);(b)i = 10; j = 5;printf("%d ", i++ - ++j);printf("%d %d", i, j);(c)i = 7; j = 8;printf("%d ", i++ - --j);printf("%d %d", i, j);(d)i = 3; j = 4; k = 5;printf("%d ", i++ - j++ + --k);printf("%d %d %d", i, j, k);

Solution(a) 0 2 (b) 4 11 6 (c) 0 8 7 (d) 3 4 5 4

给出下列程序片段的输出结果。假设i 和j 都是int 型变量。

(a)i = 5;j = ++i * 3 - 2;printf("%d %d", i, j);(b)i = 5;j = 3 - 2 * i++;printf("%d %d", i, j);(c)i = 7;j = 3 * i-- + 2;printf("%d %d", i, j);(d)i = 7;j = 3 + --i * 2;printf("%d %d", i, j);

Solution(a) 6 16 (b) 6 -7 (c) 6 23 (d) 6 15

表达式++i 和i++ 中只有一个是与表达式(i += 1) 完全相同的,是哪一个呢?验证你的答案。

SolutionThe prefix increment operator `++i` is equivalent to `(i += 1)` because thevalue is immediately read as `i + 1`, unlike the postfix operator, which appliesthe assignment but does not read the value immediately as `i + 1` but as `i`.

添加圆括号,说明C语言编译器如何解释下列表达式。

(a) a * b - c * d + e(b) a / b % c / d(c) - a - b + c - + d(d) a * - b / c - d

Solution(a) (((a * b) - (c * d)) + e)(b) (((a / b) % c) / d)(c) ((((- a) - b) + c) - (+ d))(d) (((a * (- b)) / c) - d)

给出下列每条表达式语句执行以后i 和j 的值。(假设i 的初始值为1,j 的初始值为2。)

(a) i += j;(b) i--;(c) i * j / i;(d) i % ++j;

Solution(a) 3, 2 (b) 0, 2 (c) 1, 2 (d) 1, 3

编程题

编写一个程序,要求用户输入一个两位数,然后按数位的逆序打印出这个数。程序会话应类似下面这样:

Enter a two-digit number: 28

The reversal is: 82

用%d 读入两位数,然后分解成两个数字。提示 :如果n 是整数,那么n % 10 是个位数,而n / 10 则是移除个位数后剩下的数。

#include <stdio.h>int main(void) {int number;printf("Enter a two-digit number: ");scanf("%d", &number);printf("The reversel is %d\n", 10 * (number % 10) + number / 10);return 0;}

存在问题:

变量命名问题

#include <stdio.h>int main(void) {int n = 0;printf("Enter a two-digit number: ");scanf("%d", &n);printf("The reversal is: %d%d\n", n % 10, n / 10);return 0;}

扩展上题中的程序使其可以处理3位数。

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(void){int num, gewei, shiwei, baiwei;printf("Enter a three-digit number: ");scanf("%d", &num);baiwei = num / 100;shiwei = num % 100 / 10;gewei = num % 10;printf("The reversal is: %d\n", gewei * 100 + shiwei * 10 + baiwei);return 0;}

存在问题:

变量命名问题

#include <stdio.h>int main(void) {int n = 0;printf("Enter a three-digit number: ");scanf("%d", &n);printf("The reversal is: %d%d%d\n", n % 10, n / 10 % 10, n / 100);return 0;}

重新编写编程题2中的程序,使新程序不需要利用算术分割就可以显示出3位数的逆序。提示 :参考4.1节的upc.c 程序。

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(void){int num1, num2, num3;printf("Enter a three-digit number: ");scanf("%1d%1d%1d", &num1, &num2, &num3);printf("The reversal is: %d%d%d\n", num3, num2, num1);return 0;}

#include <stdio.h>int main(void) {int n1, n2, n3;printf("Enter a three-digit number: ");scanf("%1d%1d%1d", &n1, &n2, &n3);printf("The reversal is: %d%d%d\n", n3, n2, n1);return 0;}

编写一个程序,读入用户输入的整数并按八进制(基数为8)显示出来:

Enter a number between 0 and 32767: 1953

In octal, your number is: 03641

输出应为5位数,即便不需要这么多数位也要如此。提示 :要把一个数转换成八进制,首先将其除以8,所得的余数是八进制数的最后一位(本例中为1);然后把原始的数除以8,对除法结果重复上述过程,得到倒数第二位。(如第7章所示,printf 可以显示八进制的数,所以这个程序实际上有更简单的写法。)

#include <stdio.h>int main(void) {int n;printf("Enter a number between 0 and 32767: "); scanf("%d", &n);printf("In octal, your number is: %d%d%d%d%d\n", (n/4096)%8, (n/512)%8, (n/64)%8, (n/8)%8, n%8);return 0;}

重写4.1节的upc.c 程序,使用户可以一次输入11位数字,而不用先录入1位,再录入5位,最后再录入5位。

Enter the first 11 digits of a UPC: 01380015173

Check digit: 5

/* Computes a Universal Product Code check digit */#include <stdio.h>int main(void) {int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5,first_sum, second_sum, total;printf("Enter the first 11 digits of a UPC: ");scanf("%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d",&d, &i1, &i2, &i3, &i4, &i5, &j1, &j2, &j3, &j4, &j5);first_sum = d + i2 + i4 + j1 + j3 + j5;second_sum = i1 + i3 + i5 + j2 + j4;total = 3 * first_sum + second_sum;printf("Check digit: %d\n", 9 - ((total - 1) % 10));return 0;}

欧洲国家不使用北美的12位通用产品代码(UPC),而使用13位的欧洲商品编码(European Article Number, EAN)。跟UPC一样,每个EAN码的最后也有一个校验位。计算校验位的方法也类似:首先把第2位、第4位、第6位、第8位、第10位和第12位数字相加;然后把第1位、第3位、第5位、第7位、第9位和第11位数字相加;接着把第一次加法的结果乘以3,再和第二次加法的结果相加;随后,再把上述结果减去1;相减后的结果除以10取余数;最后用9减去上一步骤中得到的余数。

以Güllüoglu Turkish Delight Pistachio & Coconut为例,其EAN码为8691484260008。第一个和为6+1+8+2+0+0=17,第二个和为8+9+4+4+6+0=31。第一个和乘以3再加上第二个和得到82,减1得到81。这个结果除以10的余数是1,再用9减去余数得到8,与原始编码的最后一位一致。请修改4.1节的upc.c 程序以计算EAN的校验位。用户把EAN的前12位当作一个数输入:

Enter the first 12 digits of an EAN: 869148426000

Check digit: 8

#include <stdio.h>int main(void) {int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, sum1, sum2, total;printf("Enter the first 12 digits of an EAN: ");scanf("%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d",&n1, &n2, &n3, &n4, &n5, &n6, &n7, &n8, &n9, &n10, &n11, &n12);sum1 = n2 + n4 + n6 + n8 + n10 + n12;sum2 = n1 + n3 + n5 + n7 + n9 + n11;total = 3 * sum1 + sum2;printf("Check digit: %d\n", 9 - ((total - 1) % 10));return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。