1.回文日
2011年11月02日是一个回文日:2011 1102,请列出本世纪还有多少个回文日?
当年份确定后,如2015年,就看20155102能否构成一个合法的日期,其中51部分是月,02部分是日。显然,由2015就不能得出一个回文日。
再如,当年份取2090年时,20900902,由2090可以构造出一个回文日来。
用年份循环并判断,而不是罗列所有的日期,显然效率上更好。
#include <stdio.h>
#include <stdlib.h>int main()
{int year,month,day,date,y;int is_cycle;//用于标识判断结果int count=0;for(year=2015;year<2100;year++){is_cycle=0;month=year%100;//若原月份前两位是回文日,原年份后两位对应月month=month/10+month%10*10;//把月倒过来为真正月份day=year/100;//若是回文日,原年份前两位对应日day=day/10+day%10*10;//把日倒过来为真正日switch(month){case 1:case 3:case 5:case 7:case 8:case 10:case 12:if(day<=31){is_cycle=1;}break;case 4:case 6:case 9:case 11:if(day<=30){is_cycle=1;}break;case 2:if((year%4==0&&year%100!=0)||year%400==0){//闰年if(day<=29){is_cycle=1;}}else{if(day<=28){is_cycle=1;}}break;default:continue;}y=year;if(is_cycle){date=y;while(y>0){date=date*10+y%10;y/=10;}printf("%d\n",date);count++;}}printf("共有%d个回文日.\n",count);return 0;
}
2.确定等式
有等式[※×(※3+※)]^2=8※※9,其中※处为1个数字,滴上了墨水无法辨认。请编程找出※表示哪个数字。
代码:【遍历】
#include <stdio.h>
#include <math.h>int main()
{int a,b,c,temp,left;for(a=1;a<=9;a++){for(b=1;b<=9;b++){for(c=0;c<=9;c++){temp=a*((b*10+3)+c);left=pow(temp,2);if(left/1000==8&&left%10==9){printf("%d %d %d %d %d\n",a,b,c,left/100-left/1000*10,left/10-left/100*10);}}}}return 0;
}
需要注意的是在调用pow函数时,要求参数类型为float,返回值类型也为float,因此容易造成精度损失。
单步执行时当temp=13,15,20,21,22,23..时(起始13)对应的left都少1,而其他数(14,16,17,18,...)都正常。
所以应将
left=pow(temp,2);
改为 :
left=temp*temp;
//或者
left=(int)(0.1+pow(temp,2));
错误的运行:
正确运行:
3.fflush(stdin):清除键盘缓存区
(缓存区:在输入输出时,系统分配一段内存区域,将输入输出的内容放在这片区域)
fflush:函数名;stdin代表标准输入(键盘)
有如下程序常用于重复性工作:
#include<stdio.h>
void dosomething(int *p);
int main( )
{char choice='y';int n=0;while(choice!='N' && choice!='n'){dosomething(&n);printf("按 N 退出,其他键继续....");scanf("%c", &choice); //用choice=getchar();也一样}return 0;
}void dosomething(int *p) //完成特定的业务
{*p+=1; //本例中传地址, *p即nprintf("第%d次完成业务!\n", *p);
}
输入:666<回车>
发现运行异常。这是因为缓存区中保存了666'\n'[回车字符],所以第三次时直接的choice用缓存区中的第二个6,第四次choice用缓存区中的第三个6,第五次choice用缓存区中的'\n',以至于多出来了:
正确的源代码应该在输入前先清除缓存区:
#include<stdio.h>
void dosomething(int *p);
int main( )
{char choice='y';int n=0;while(choice!='N' && choice!='n'){dosomething(&n);printf("按 N 退出,其他键继续....");fflush(stdin);//读入字符前,常要清空“输入缓存区”scanf("%c", &choice); //用choice=getchar();也一样}return 0;
}void dosomething(int *p) //完成特定的业务
{*p+=1; //本例中传地址, *p即nprintf("第%d次完成业务!\n", *p);
}
4.将十进制数转换成n进制数
#include <stdio.h>
#include <stdlib.h>
//除以n取余数保存在数组中,然后将数组从后往前输出,因为后面是高位
int main()
{int n,b,i=0,j,a[20];scanf("%d",&n);scanf("%d",&b);while(b){a[i++]=b%n;b/=n;}i--;for(j=i;j>=0;j--){printf("%d",a[j]);}printf("\n");return 0;
}
运行结果:
5.二分法解方程
二分法是在计算机科学中很重要的一种方法,用于查找产生二分查找算法,还可以用在很多场合。
可以用二分法解方程。
对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。
假设要求方程f(x)=0的解,给定精确度ξ。其算法是:
- 1 确定区间[a,b],验证f(a)·f(b)<0
- 2 求区间(a,b)的中点c
- 3 判断
(2) 若f(c)·f(b)<0,则令a=c.
- 4 判断f(c)是否达到精确度ξ:即若┃f(c)┃<ξ,则x=c就是使f(x)接近零点的近似值,否则重复2-4.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double f(double x);
int main()
{double a,b,c;do{printf("请输入一个范围:");scanf("%lf %lf",&a,&b);}while(f(a)*f(b)>0);printf("该方程在%lf-%lf之间有一解为",a,b);do{c=(a+b)/2;if(f(a)*f(c)<0)b=c;elsea=c;}while(fabs(f(c))>1e-5);printf("%lf\n",c);return 0;
}double f(double x)
{return (3*x*x*x-5*x*x+3*x-6);
}
运行: