5.1先查阅标准库函数,然后再回答下列代码完成什么功能?
int c;
while((c = getchar()) != EOF
putchar(isupper(c)?tolower(c):c);
答:将大写字母转换为小写输出,其它字符原样输出。
5.2下面的代码段意欲实现:如果x = =0,则什么也不做,除非y = =0时调用exit(1);否则置x == x+y。你认为这段代码能否完成上述功能?请给出你的一个实现方案。
if(x == 0)
if(y == 0)
exit(1)
else
x = x+y;
答:不能完成这一功能。一个解决方案是:
if(x == 0)
{ if(y == 0)
exit(1);
}
else x = x+y;
5.3下面的代码段是否存在问题?为什么?
int m = 10;
float x = 2.3;
float *p = &x;
x = m/*p; /* *p = = x */
printf("x = %f\n",x);
答:语句行“x = m/*p; /* *p = = x */”存在问题。ANSI C规定:“如果输入字符流到一个给定的字符串为止已经被识别为记号,则应该包含下一个字符以组成能够构成记号的最长的字符串”。因此,如果/是一个记号的第一个字符,并且/后面紧随了一个*,则这两个字符构成了注释的开始,直到*/的出现。换句话说,这条语句变成了
x = m/*p……*/
但x = m又缺少分号,所以导致编译错。解决问题的一个方案是:
x = m/ *p /* *p == x */
或者
x = m/(*p) /* *p == x */
5.4 编程:任给一个三位十进制整数,若该数中有且仅有两个数码相同,则输出该数。
解:下面给出它的两种解决方案。
方案一:
#include <stdio.h>
int main()
{
int a,b,c,d = 100;
while(d <= 999)
{
c = d % 10;
b = d / 10 % 10;
a = d/100;
if(a==b && b!=c||a==c && b!=c||b==c && a!=b)
printf("%d\n",d);
d++;
}
return 0;
}
方案二:该方案巧妙地利用了条件判断表达式的特性。
#include <stdio.h>
int main()
{
int num,hundreds,tens,units;
printf("Input an integer ( form 100 to 999 ),");
scanf("%d",&num);
hundreds = num/100;
tens = num % 100/10;
units = num % 10;
if((hundreds==tens)+(tens==units)+(hundreds==units)==1)
printf(“%d\n,,num);
return 0;
}
5.5 用case语句编程计算y值:
cos(x+3.0) 0≤x<10
y = cos2(x+7.5) 10≤x<20
cos4(x+4.0) 20≤x<30
解:用case语句编程的关键是如何巧妙地设计“选择开关”。根据本题所提供的条件,我们将选择开关设计为表达式(int)x/10。下面给出本题的一种解决方案。
#include <stdio.h>
#include <math.h>
int main()
{
float x;
printf("Input x = ");
scanf("%f",&x);
switch((int)(x/10))
{
case 0,x = cos(x+3.0); break;
case 1,x = cos(x+7.5); x=x*x; break;
case 2:x=cos(x+4.0); x=x*x*x*x; break;
default:printf("Unknown !\n");goto loop;
}
printf("y=%f\n",x);
loop,return 0;
}
5.6 任给一整数,判断该数是奇数还是偶数。若是大于1的奇数,判其是否是素数。
解:本题很简单,主要是判素数的问题。下面它的一种解决方案。
#include <stdio.h>
#include <math.h>
int main()
{
int n,i;
printf("Input an integer,");
scanf("%d",&n);
if(n % 2==0) printf("%d is an even number.\n",n);
else{
printf("%d is an odd number.\n",n);
if(n>1)
{
for(i = 2; i <= sqrt(n); i++)
{
if(n%i==0)
{
printf("%d is not a prime\n",n);
goto loop;
}
}
printf("%d is a prime\n",n);
}
}/* else */
loop,return 0;
}
5.7 三个成等差数列的数,首尾两项之积为中项的5倍,后两项之和为第一项的8倍,求此三数。
解:从数学上不难分析它们之间的关系,可编程序如下:
#include <stdio.h>
#include <math.h>
int main()
{
float b = 4.0,d;
do{
b++; d = sqrt(b * b – 5 * b);
}while(2 * b != 3 * d);
printf("%.2f \t %.2f \t %.2f \n",b-d,b,b+d);
return 0;
}
5.8 给定一字母,要求打印出一个菱形,该菱形中间一行由此字母组成,其相邻的上下两行由它的直接前趋字母组成。按此规律,直到字母A出现在第一行和最后一行为止。例如,给定字母C,输出如下:
A
BBB
CCCCC
BBB
A
解:将其分解为两部分:先打印上三角,再打印下三角。一种实现方案如下。注意,程序中的prinft语句:
printf("%*c",letter-i+10,' ');
该语句通过格式修饰符“*”来动态确定一行中的前导空格数,即第i行前面应该预留letter-i+10个空格位置,其中“+10”相当于将图整个右移10个空格位置。
#include <stdio.h>
#include<ctype.h>
int main()
{
unsigned char letter;
int i,j;
printf("Input a letter (B to Z),");
letter = getchar();
letter = islower(letter)?toupper(letter):letter; /* 小写换大写 */
letter -= 64;
for(i = 1; i <= letter; i++) /* 打印上三角 */
{
printf("%*c",letter-i+10,' '); /* 确定每行的开始打印位置 */
for(j=1;j<=2*i-1;j++)
putchar(64+i); /* 打印第i行 */
putchar('\n'); /* 一行打印完,换一行 */
} /* 上三角打印完 */
for(i=letter-1;i>=1;i--) /* 开始打印下三角 */
{
printf("%*c",letter-i+10,' ');
for(j=1;j<=2*i-1;j++) putchar(64+i);
putchar('\n');
}
return 0;
}
5.9 打印以下由数字组成的金字塔。
1
12 21
123 321
1234 4321
12345 54321
解:本题比5.8题稍复杂。仍然当作一个矩形来考虑:前部用空格组成一个直角三角形,它控制了前面各行数字的开始打印位置;内部用空格组成一个等腰三角形,它控制了后面各行数字的开始打印位置。设欲打印的行数为n,根据分析不难发现:
对直角三角形,第i行应打印2*n-2*i个空格;
对等腰三角形,第1行不留空格,从第i(i≥2)行开始应打印2*i-3个空格。
#include <stdio.h>
int main()
{
int n,i,j;
printf("Input ranks (0 to 9),");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("%*c",2*n-2*i,' '); /* 确定前半部分每行的开始打印位置 */
for(j=1;j<=i;j++)
printf("%d",j); /* 打印前半部分 */
printf("%*c",2*n-2*i,' '); /* 确定后半部分每行的开始打印位置 */
if(i>=2)
{
for(j=i;j>=1;j--)
printf("%d",j); /* 打印后半部分 */
}
putchar('\n');
}
5.10 在屏幕上用“*”画一个空心的圆。
解:本质上讲,这与前面两题的思路是一样的:利用图形的左右对称性打印圆。当然,我们可根据圆的方程:
r2=x2+y2
方便地计算出圆上每一点的行和列坐标。
#include<stdio.h>
#include<math.h>
int main()
{
double row;
int col,coor;
for(row = 10; row >= -10; row--)
{
/* 计算行row对应的列坐标coor,1.25是屏幕纵横比调节系数 */
coor = 1.25*sqrt(100-row*row);
for(col=1;col<20-coor;col++)
printf(" "); /* 图形左侧空白控制 */
printf("*"); /* 圆的左侧 */
for(;col<20+coor;col++)
printf(" "); /* 图形的空心部分控制 */
printf("*\n"); /* 圆的右侧 */
}
}
5.11 在歌星大奖赛中,有10个评委为参赛的选手打分,打分原则是:最低给1分,最高给100分。选手最后得分为:去掉一个最高分和一个最低分后,取其余8个分数的平均值。请编写一个程序实现。
解:这个问题的算法十分简单,但有两点要注意:一是如何判断无效分,再是如何判断最高分和最低分。一种实现方案如下:
#include<stdio.h>
int main()
{
int score,i,max,min,sum;
max = -32768; /* 最高分 */
min = 32767; /* 最低分 */
sum = 0; /* 总分 */
for(i = 1; i <= 10; i++)
{
do{
printf("Input score %d=",i);
scanf("%d",&score); /* 输入评委的评分 */
}while(score<1||score>100);
sum += score; /* 累计总分 */
if(score > max) max = score; /* 筛选出其中的最高分 */
if(score < min) min = score; /* 筛选出其中的最低分 */
}
printf("Canceled max score:%d\nCanceled min score:%d\n",max,min);
printf("Average score:%d\n",(sum-max-min)/8); /* 输出结果 */
} 
5.12 一辆卡车违反交通规则,撞人后逃跑。现场有三人目击事件,但都没有记住车号,只记下车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的,但与前两位不同;丙是数学家,他说:四位的车号刚好是一个整数的平方。请根据以上线索求出车号。
解:按照题目的要求造出一个前两位数相同、后两位数相同且相互间又不同的整数,然后判断该整数是否是另一个整数的平方。下面是它的一个实现方案。
#include<stdio.h>
int main()
{
int i,j,No,k;
for(i = 1; i <= 9; i++) /* i为前二位车号 */
for(j = 0; j <= 9; j++) /* j为后二位车号 */
if(i != j)
{
No = i*1000+i*100+j*10+j; /* 计算出可能的整数 */
for(k = 31; k*k < No; k++); /* 判断是否为另一整数的平方 */
if( k * k == No )
printf("car number-plate is %d.\n",No);
}
}
5.13 求3000以内的全部亲密数。所谓亲密数是指:如果整数A的全部因子(包括1但不包括A本身)之和等于B;且整数B的全部因子(包括1但不包括B本身)之和等于A,则将整数A和B称为亲密数。
解:显然,这里的问题转化为如何求出一个数的全部因子。求a的各因子的算法是:用a依次对i(i=1,2,…,a/2)进行模运算,若模运算结果等于0,则i为a的一个因子;否则i就不是a的因子。于是,可编程序如下:
#include<stdio.h>
int main()
{
int a,i,b,k;
printf("friendly--numbers pair smaller than 3000:\n");
for(a = 1; a < 3000; a++)?
{
for(b = 0,i = 1;i <= a/2; i++) /* 求a的各因子,其和存于b */
if(!(a % i)) b += i;
for(k = 0,i = 1;i <= b/2; i++) /* 求 b的各因子,其和存于k */
if(!( b % i)) k += i;
if( k == a && a < b )
printf("%4d AND %4d\t",a,b);?
}
}
5.14 3025这个数具有一种独特的性质:将它平分为二段,即30和25,使之相加后求平方,即(30+25)2,恰好等于3025本身。请求出具有这样性质的全部四位数。
具有这种性质的四位数没有分布规律,宜采用穷举法,从而筛选出符合这种性质的四位数。
#include<stdio.h>
int main()
{
int n,a,b;
printf("Result = ");
for(n = 1000; n < 10000; n++)
{
a = n / 100; /* 截取前两位数 */
b = n % 100; /* 截取后两位数 */
if((a+b)*(a+b)==n)
printf("%d,",n);
}
printf("\b \n");
}
5.15 数制转换,将任一十进制整数转换为等值的二进制形式。
解:将十进制整数转换为二进制的方法很多,这里介绍利用C语言能够对位进行操作的特点,无须将一个十进制整数转换为二进制形式,而是将整数在内存中的二进制表示直接输出。
#include<stdio.h>
int main()
{
int i,n,dec;printf("Input decimal number,");
scanf("%d",&dec);
printf("number of decimal form,%d\n",dec);
printf(" it's binary form,");
n = sizeof(int) * 8;
for(i = n; n >= 1; n--)
putchar('0'+((unsigned)(dec&(1<<(n-1)))>>(n-1))); /*输出第n位*/
putchar('\n');
}
5.16 马克思手稿中有一道趣味数学问题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭花了50先令;每个男人花3先令,每个女人花2先令,每个小孩花1先令;问男人、女人和小孩各有几人?
解:这是一个简单的问题,因为如果假设x、y,、z分别代表男人、女人和小孩,由题意不难得到如下方程:
x+y+z=30 (1)
3x+2y+z=50 (2)
由题可知其解应为非负整数,且可能存在多解,于是通过(2)-(1)式可得:
2x+y=20(3)
由(3)式显然,x变化范围是1~9。据此可编程如下:
#include<stdio.h>
int main()
{
int x,y,z;
printf("Men\t\bWomen\t\b\bChildren\n");
printf("......................\n");
for(x=1;x<=9;x++)
{
y=20-2*x;
z=30-x-y;
printf(" %d\t%2d\t%2d\n",x,y,z);
}
}