火车托运费的计算
设乘坐火车托运行李时按下列式子收费:
0 (0<=x<=20)
应交费用y = (x–20) * 2 (20 (x–40) * 5 + 40 (x>40) 编一个程序用来计算应交金额。 实例解析: 这是第三章中的一个例题(当时是用switch处理的),是一个选择结构的实例,收费情况共分三种。 本题可以采用三种方法来编程: (1) 用三个单独的if语句,每个if语句处理一种情况; (2) 用嵌套的if语句处理,需两个if语句; (3) 用switch语句。 方法一:用单独的if语句 #include int main() { int x, y; scanf(“%d”, &x); if(x <= 20) y = 0; if(x > 20 && x <= 40) y = (x-20)*2; if(x > 40) y = (x–40)*5 + 40; printf(“y = %d\n”, y); getch(); return 0; } 注意: if(x > 40)一行,不能写成else,原因请参看第3章3.13中的if语句常见错误。 方法二:用嵌套的if语句 #include <stdio.h> int main() { int x, y; scanf(“%d”, &x); if(x <= 20) y = 0; else if(x <= 40) //在x>=20不成立的情况下,若x<=40 y = (x-20)*2; else //在前面两个条件都不成立的情况下 y = (x–40)*5 + 40; printf(“y = %d\n”, y); getch(); return 0; } 方法三:用switch语句 #include <stdio.h> int main() { int x, y; scanf(“%d”, &x); switch(x/20) { case 0: y = 0; break; case 1: y = (x-20)*2; break; default: y = (x–40)*5 + 40; } printf(“y=%d\n”, y); getch(); return 0; } 找小偷 警察局抓了a、b、c、d 共4名盗窃嫌疑犯,但只有一人是小偷。审讯中,a不承认自己是小偷,b说c是小偷,c指认d为小偷,d说c冤枉他。已知4人中有3人说的是真话,请问谁是小偷? 实例解析: 本实例的目的是让读者学会把逻辑值当整数来使用。 C中的逻辑值要么为1,要么为0。将几个关系(或逻辑)表达式相加,由结果可以知道其中有几个表达式是成立的。 由题意知,4个人都是嫌疑犯,所以我们定义一个变量x,使之分别取值1、2、3、4,分别代表a、b、c、d是小偷的4种情况。 对于x的每一个取值,我们判断下面的4个表达式有几个成立。 (1) x != 1 //小偷不是a (2) x == 3 //小偷是c (3) x == 4 //小偷是d (4) x != 4 //小偷不是d 判断的方法是:将4个表达式的值相加,若等于3,表示三个人说的是真话,符合题意,输出结果,否则,不符合题意,跳过。 下面是程序代码: #include <stdio.h> int main() { int x; for(x = 1; x <= 4; x++) if((x!=1) + (x==3) + (x==4) + (x!=4) == 3) printf(“%c是小偷!\n”, x+64); getch(); return 0; } 判断整数能被3、5、7中的哪些数整除 键盘输入一个整数,判断能被3、5、7中的几个数整数,并且指出这几个数。 实例解析: 这个题目可以用3个if语句分别检查能否被3、5、7整除,但这种最普通的算法效率较低。 这里我们介绍一种简单的方法,利用实例3所介绍的技巧:将几个关系表达式相加,可以知道有几个表达式是成立的。 求解:s = (x%3==0) + (x%5 == 0) + (x%7 == 0) (1)若s 值为3,则x可同时被3个数整除 (2)若s为2,则只能同时被其中2个数整除。 (3)若s为1,则只能被其中1个数整除。 (4)若s为0,则不能被其中任何数整除。 但是,这样设计有一个问题,当s = 2或s = 1时,我们只知道x可以被几个数整数,但能被哪些数整除却不能确定。 为此,我们这样设计:用一个字节的后三位分别表示能否被3、5、7整除。若x能被3整除,我们让最后一位为1,若能被5整除,让倒数第2位为1,若能被7整除,让倒数第3位为1。共有8种可能: (1)00000000 (2)00000001 (3)00000010 (4)00000011 (5)00000100 (6)00000101 (7)00000110 (8)00000111 通过检查该字节的值,可以得到本实例所要的结论。 程序代码如下: #include <stdio.h> int main() { int x; char s; scanf(“%d”, &x); s = (x%3==0) + (x%5==0)*2 + (x%7==0)*4; switch(s) { case 0: printf(“none\n”); break; case 1: printf(“3\n”); break; case 2: printf(“5\n”); break; case 3: printf(“3,5\n”); break; case 4: printf(“7\n”); break; case 5: printf(“3,7\n”); break; case 6: printf(“5,7\n”); break; case 7: printf(“3,5,7\n”); break; default: printf(“error!\n”); } return 0; } 找假货 有5箱产品,每箱20件,但其中有几箱里全是假货。已知正品每件100克,假货比正品轻10克,问能否用天平只称一次,找出所有装假货的箱子? 实例解析: 本题可以先这样考虑:每箱取出一件产品,共取5件,一起放在天平上称一次,如果总重490克,说明比正常情况少了10克,其中必定有一件是假货,推断出只有一箱假货。如果比正常少20克,则有两箱假货,如果少30克,有三箱假货…… 但是,这样只能知道有几箱假货,不知道哪箱是假货。为此,我们给每个箱子加上权重:即每个箱子取出的产品数目不同。 我们想到,可以在5个箱子中分别取1、2、3、4、5件产品,但这样的算法依然存在问题:当总重470克时,有可能1、2号箱是假货,还有可能3号箱是假货,还是不能确定哪些箱是假货。 正确的取法应该是:分别在5个箱子中取1、2、4、8、16件产品,这样就不会出现分辨不清的情况了。例如若总重430克,少了70克,则一定是前三箱是假货。 下面是程序代码: #include int main() { int w[5] = {100,90,100,90,90}; //分别是5个箱子里一件产品的重量 int sum = 0, i, k = 1, m; for(i = 0; i < 5; i++ ) { sum += w[i]*k; k *= 2; } m = (100*31 – sum)/10 ; // 计算其中有多少件假货 k = 16; // k先取第5箱的权重 for(i = 5; i >= 1; i--) { if(m >= k) { printf(“第%d箱是假货\n”, i); m -= k; } k /= 2; // k变为下一个要处理箱的权重 } getch(); return 0; } 上面代码的最后一段也可以采用位操作来完成: m = (100*31 – sum)/10 ; // 计算其中有多少件假货 for(i = 1; i <= 5; i++) { if(m & 1) printf(“第%d箱是假货\n”, i); m >>= 1; } 计算某天是一年中的第几天 键盘输入一个年月日,计算该日期在该年中是第几天。 实例解析: 这也是第三章中的一个例题(参看例3.3),在例3.3中是用switch语句来编程的,这里我们用循环的方法。 程序设计思路是:用一个数组存放12个月份的天数(实际上第12月的数据无用),假设month=5,则需要先把前4个月的天数(即下面数组的第1~4个元素)加起来,再加上5月份的日期(即day),若是闰年,再加1。 #include int main( ) { int year, month, day; int m[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i, n = 0; scanf(“%d%d%d”, &year, &month, &day); for(i = 1; i < month; i++) n += m[i]; n += day; if((year%4==0 && year%100 != 0 || year%400 == 0 ) && month>=3 ) n++; printf(“%d\n”, n); getch(); return 0; }