C语⾔趣味程序设计编程百例精解
1.绘制余弦曲线
在屏幕上⽤“*”显⽰0~360度的余弦函数cos(x)曲线
*问题分析与设计
如果在程序中使⽤数组,这个问题⼗分简单。但若规定不能使⽤数组,问题就变得不容易了。
关键在于余弦曲线在0~360度的区间内,⼀⾏中要显⽰两个点,⽽对⼀般的显⽰器来说,只能按⾏输出,即:输出第⼀⾏信息后,只能向下⼀⾏输出,不能再返回到上⼀⾏。为了获得本⽂要求的图形就必须在⼀⾏中⼀次输出两个“*”。
为了同时得到余弦函数cos(x)图形在⼀⾏上的两个点,考虑利⽤cos(x)的左右对称性。将屏幕的⾏⽅向定义为x,列⽅向定义为y,则
0~180度的图形与180~360度的图形是左右对称的,若定义图形的总宽度为62列,计算出x⾏0~180度时y点的坐标m,那么在同⼀⾏与之对称的180~360度的y点的坐标就 应为62-m。程序中利⽤反余弦函数acos计算坐标(x,y)的对应关系。
使⽤这种⽅法编出的程序短⼩精炼,体现了⼀定的技巧。
*程序说明与注释
#include<stdio.h>
#include<math.h>
int main()
{
double y;
int x,m;
for(y=1;y>=-1;y-=0.1) /*y为列⽅向,值从1到-1,步长为0.1*/
{
m=acos(y)*10; /*计算出y对应的弧度m,乘以10为图形放⼤倍数*/
for(x=1;x<m;x++) printf(” “);
printf(“*”); /*控制打印左侧的 * 号*/
for(;x<62-m;x++)printf(” “);
printf(“*\n”); /*控制打印同⼀⾏中对称的右侧*号*/
}
return 0;
}
*思考题
如何实现⽤“*”显⽰0~360度的sin(x)曲线。
在屏幕上显⽰0~360度的cos(x)曲线与直线f(x)=45*(y-1)+31的迭加图形。其中cos(x)图形⽤“*”表⽰,f(x)⽤“+”表⽰,在两个图形相交的点上则⽤f(x)图形的符号。
2.绘制余弦曲线和直线
*问题分析与算法设计
本题可以在上题的基础上进⾏修改。图形迭加的关键是要在分别计算出同⼀⾏中两个图形的列⽅向点坐标后,正确判断相互的位置关系。为此,可以先判断图形的交点,再分别控制打印两个不同的图形。
*程序注释与说明
#include<stdio.h>
#include<math.h>
int main()
{
double y;
int x,m,n,yy;
for(yy=0;yy<=20;yy++) /*对于第⼀个y坐标进⾏计算并在⼀⾏中打印图形*/
{
y=0.1*yy; /*y:屏幕⾏⽅向坐标*/
m=acos(1-y)*10; /*m: cos(x)曲线上y点对应的屏幕列坐标*/
n=45*(y-1)+31; /*n: 直线上y点对应的列坐标*/
for(x=0;x<=62;x++) /*x: 屏幕列⽅向坐标*/
if(x==m&&x==n) printf(“+”); /*直线与cos(x)相交时打印“+”*/
else if(x==n) printf(“+”); /*打印不相交时的直线图形*/
else if(x==m||x==62-m) printf(“*”); /*打印不相交时的cos(x)图形*/
else printf(” “); /*其它情况打印空格*/
printf(“\n”);
}
return 0;
}
*思考题
如何实现sin(x)曲线与cos(x)曲线图形的同时显⽰。
在屏幕上⽤“*”画⼀个空⼼的圆
*问题分析与算法设计
打印圆可利⽤图形的左右对称性。根据圆的⽅程:
R*R=X*X+Y*Y
可以算出圆上每⼀点⾏和列的对应关系。
*程序说明与注释
#include<stdio.h>
#include<math.h>
int main()
{
double y;
int x,m;
for(y=10;y>=-10;y–)
{
m=2.5*sqrt(100-y*y); /*计算⾏y对应的列坐标m,2.5是屏幕纵横⽐调节系数因为屏幕的
⾏距⼤于列距,不进⾏调节显⽰出来的将是椭圆*/
for(x=1;x<30-m;x++) printf(” “); /*图形左侧空⽩控制*/
printf(“*”); /*圆的左侧*/
for(;x<30+m;x++) printf(” “); /*图形的空⼼部分控制*/
printf(“*\n”); /*圆的右侧*/
}
return 0;
}
*思考题
实现函数y=x2的图形与圆的图形叠加显⽰
在歌星⼤奖赛中,有10个评委为参赛的选⼿打分,分数为1~100分。选⼿最后得分为:去掉⼀个最⾼分和⼀个最低分后其余8个分数的平均值。请编写⼀个程序实现。
*问题分析与算法设计
这个问题的算法⼗分简单,但是要注意在程序中判断最⼤、最⼩值的变量是如何赋值的。
*程序说明与注释
#include<stdio.h>
int main()
{
int integer,i,max,min,sum;
max=-32768; /*先假设当前的最⼤值max为 整型数的最⼩值*/
min=32767; /*先假设当前的最⼩值min为C语⾔整型数的最⼤值*/
sum=0; /*将求累加和变量的初值置为0*/
for(i=1;i<=10;i++)
{
printf(“Input number %d=”,i);
scanf(“%d”,&integer); /*输⼊评委的评分*/
sum+=integer; /*计算总分*/
if(integer>max)max=integer; /*通过⽐较筛选出其中的最⾼分*/
if(integer<min)min=integer; /*通过⽐较筛选出其中的最低分*/
}
printf(“Canceled max score:%d\nCanceled min score:%d\n”,max,min);
printf(“Average score:%d\n”,(sum-max-min)/8); /*输出结果*/
}
*运⾏结果
Input number1=90
Input number2=91
Input number3=93
Input number4=94
Input number5=90
Input number6=99
Input number7=97
Input number8=92
Input number9=91
Input number10=95
Canceled max score:99
Canceled min score:90
Average score:92
*思考题
题⽬条件不变,但考虑同时对评委评分进⾏裁判,即在10个评委中出最公平(即评分最接返平均分)和最不公平(即与平均分的差距最⼤)的评委,程序应该怎样实现?
问555555的约数中最⼤的三位数是多少?
*问题分析与算法设计
根据约数的定义,对于⼀个整数N,除去1和它⾃⾝外,凡能整除N的数即为N的约数。因此,最简单的⽅法是⽤2到N-1之间的所有数去除N,即可求出N的全部约数。本题只要求取约数中最⼤的三位数,则其取值范围可限制在100到999之间。
*程序说明与注释
#include<stdio.h>
int main()
{
long i;
int j;
printf(“Please input number:”);
scanf(“%ld”,&i);
for(j=999;j>=100;j–)
if(i%j==0)
{
printf(“The max factor with 3 digits in %ld is:%d,\n”,i,j);
break;
}
}
*运⾏结果
输⼊:555555
输出:The max factor with 3 digits in555555 is:777
求13的13次⽅的最后三位数
*问题分析与算法设计
解本题最直接的⽅法是:将13累乘13次⽅截取最后三位即可。
但是由于计算机所能表⽰的整数范围有限,⽤这种“正确”的算法不可能得到正确的结果。事实上,题⽬仅要求最后三位的值,完全没有必要求13的13次⽅的完整结果。
研究乘法的规律发现:乘积的最后三位的值只与乘数和被乘数的后三位有关,与乘数和被乘数的⾼位⽆关。利⽤这⼀规律,可以⼤⼤简化程序。
*程序说明与注释
#include<stdio.h>
int main()
{
int i,x,y,last=1; /*变量last保存求X的Y次⽅过程中的部分乘积的后三位*/
printf(“Input X and Y(X**Y):”);
scanf(“%d**%d”,&x,&y);
for(i=1;i<=y;i++) /*X⾃乘Y次*/
last=last*x%1000; /*将last乘X后对1000取模,即求积的后三位*/
printf(“The last 3 digits of %d**%d is:%d\n”,x,y,last%1000); /*打印结果*/
}
*运⾏结果
Input X and Y(X**Y):13**13
The last 3 digits of 13**13 is:253
Input X and Y(X**Y):13**20
The last 3 digits of 13**20 is:801
100!的尾数有多少个零?
*问题分析与算法设计
可以设想:先求出100!的值,然后数⼀下末尾有多少个零。事实上,与上题⼀样,由于计算机所能表⽰的整数范围有限,这是不可能的。
为了解决这个问题,必须⾸先从数学上分析在100!结果值的末尾产⽣零的条件。不难看出:⼀个整数若含有⼀个因⼦5,则必然会在求100!时产⽣⼀个零。因此问题转化为求1到100这100个整数中包含了多少个因⼦5。若整数N能被25整除,则N包含2个因⼦5;若整数N能被5整除,则N包含1个因⼦5。
*程序说明与注释
#include<stdio.h>
int main()
{
int a,count =0;
for(a=5;a<=100;a+=5) //循环从5开始,以5的倍数为步长,考察整数
{
++count; //若为5的倍数,计数器加1
if(!(a%25)) ++count; //若为25的倍数,计数器再加1
}
最容易上手的编程语言printf(“The number of 0 inthe end of 100! is: %d.\n”,count); //打印结果
return 0;
}
*运⾏结果
The number of 0 in the endof 100! is: 24.
*问题进⼀步讨论
本题的求解程序是正确的,但是存在明显的缺点。程序中判断整数N包含多少个因⼦5的⽅法是与程序中的100有关的,若题⽬中的100改为1000,则就要修改程序中求因⼦5的数⽬的算法了。
*思考题
修改程序中求因⼦5的数⽬的算法,使程序可以求出任意N!的末尾有多少个零。
⼩明有五本新书,要借给A,B,C三位⼩朋友,若每⼈每次只能借⼀本,则可以有多少种不同的借法?
*问题分析与算法设计
本问题实际上是⼀个排列问题,即求从5个中取3个进⾏排列的⽅法的总数。⾸先对五本书从1⾄5进⾏编号,然后使⽤穷举的⽅法。假设三个⼈分别借这五本书中的⼀本,当三个⼈所借的书的编号都不相同时,就是满⾜题意的⼀种借阅⽅法。
*程序说明与注释
int main()
{
int a,b,c,count=0;
printf(“There are diffrent methods for XM to distribute books to 3readers:\n”);
for(a=1;a<=5;a++) /*穷举第⼀个⼈借5本书中的1本的全部情况*/
for(b=1;b<=5;b++) /*穷举第⼆个⼈借5本书中的⼀本的全部情况*/
for(c=1;a!=b&&c<=5;c++) /*当前两个⼈借不同的书时,穷举第三个⼈借5本书
中的1本的全部情况*/
if(c!=a&&c!=b) /*判断第三⼈与前两个⼈借的书是否不同*/
printf(count%8?”%2d:%d,%d,%d “:”%2d:%d,%d,%d\n “,++count,a,b,c);
/*打印可能的借阅⽅法*/
}
*运⾏结果
There are diffrent methods for XM to distribute books to 3 readers:
1: 1,2,3 2: 1,2,4 3: 1,2,5 4: 1,3,2 5: 1,3,4
6: 1,3,5 7: 1,4,2 8: 1,4,3 9: 1,4,5 10:1,5,2
11:1,5,3 12:1,5,4 13:2,1,3 14:2,1,4 15:2,1,5
16:2,3,1 17:2,3,4 18:2,3,5 19:2,4,1 20:2,4,3
21:2,4,5 22:2,5,1 23:2,5,3 24:2,5,4 25:3,1,2
26:3,1,4 27:3,1,5 28:3,2,1 29:3,2,4 30:3,2,5
31:3,4,1 32:3,4,2 33:3,4,5 34:3,5,1 35:3,5,2
36:3,5,4 37:4,1,2 38:4,1,3 39:4,1,5 40:4,2,1
41:4,2,3 42:4,2,5 43:4,3,1 44:4,3,2 45:4,3,5
46:4,5,1 47:4,5,2 48:4,5,3 49:5,1,2 50:5,1,3
51:5,1,4 52:5,2,1 53:5,2,3 54:5,2,4 55:5,3,1
56:5,3,2 57:5,3,4 58:5,4,1 59:5,4,2 60:5,4,3
在屏幕上显⽰杨辉三⾓形
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
…
……………………………..
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论