火车托运费的计算
设乘坐火车托运行李时按下列式子收费:
0 (0<=x<=20)
应交费用y = (x�C20) * 2 (20<x<=40)
(x�C40) * 5 + 40 (x>40)
编一个程序用来计算应交金额。
实例解析:
这是第三章中的一个例题(当时是用switch处理的),是一个选择结构的实例,收费情况共分三种。
本题可以采用三种方法来编程:
(1) 用三个单独的if语句,每个if语句处理一种情况;
(2) 用嵌套的if语句处理,需两个if语句;
(3) 用switch语句。
方法一:用单独的if语句
#include <stdio.h>
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�C40)*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�C40)*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�C40)*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 <stdio.h>
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 �C 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 �C 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<stdio.h>
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;
}