万年历
本帖最后由 sdnyzjzx 于 2010-12-17 11:43 编辑C语言学习视频到了第十一个了,收获越来越多,再次感谢Nisy老师,完成了万年历代码编写要求,很高兴,分享一下快乐!并恳请批评指正,谢谢!
代码在Tc2中编译,后来在记事本里加了部分中文注释,带有中文注释语句应该编译不过。
/* yi 2010-12-13 (xing qi 1) wei ji zhun */
int year,m,d,w;/* year month date week */
int sum=0; /* di ji tian */
int tt=0; /* ju li ji zhun zhong tian shu */
int a = {0,31,28,31,30,31,30,31,31,30,31,30,31}; /* mei ge yue tian shu */
int b = {0,7,1,2 ,3,4,5,6};
int k; /* biao ji shi fou run nian */
void sfrn(year)/* 判断是否闰年 */
{
if((year%4==0 && year%100 !=0) || year%400 == 0)
{
k=1;
}
else
{
k=0;
}
}
void djt (year,m,d)/* 输入日期是本年第几天 */
{
int i=0;
sfrn(year);
for(i=0;i<m;i++)
{
sum = sum + *(a+i);
}
sum=sum+d;
if(m>2)
{
sum = sum + k;
}
}
void week(year,m,d)/* 判断星期几 */
{
int i=0;
int j=0;
if(year<=2010)
{
djt(year,m,d);
if(year==2010)
{
if(sum<=347)
{
tt=347-sum;
}
else
{
tt=sum-347;
}
}
else
{ tt=tt-sum;
for(i=year;i<=2010;i++)
{
sfrn(i);
tt=tt+365+k;
}
tt=tt-18;
}
j=tt%7;
if(j==0)
{
w=1;
}
else
{
if(year <2010 || (year==2010 && sum<=347))
{
w=8-j;
}
else
{
w=1+j;
}
}
}
else
{
djt(year,m,d);
for(i=2010;i<year;i++)
{
sfrn(i);
tt=tt+365+k;
}
tt=tt-347+sum;
j=tt%7;
w=1+j;
}
}
void show(year,m,d) /* 显示 */
{
int n=0;
int i=0;
int j=0; /* 当前月数有几天*/
int x,y;
int x0,y0;/* 记录当前输入月数与天数位置 */
int w1=31;
int d1=0;/* 星期几 */
x0=y0=1;
week(year,m,d);
w1=d;
while(w1>7)
{
w1=d-7*n;
n++;
}
d1=w-w1+1;
if(d1<=0)
{
d1=d1+7;
}
clrscr();
if(m==2)
{
sfrn(year);
j = *(a+2)+k;
}
else
{
j = *(a+m);
}
x=10;
y=5;
gotoxy(15,2);
printf("== %d nian %d yue ==",year,m);
for (i=1;i<8;i++)
{
gotoxy(x,y);
printf("%d",*(b+i));
x=x+5;
}
if(d1==7)
{
x=10;
}
else if(d1==1)
{
x=15;
}
else if(d1==2)
{
x=20;
}
else if(d1==3)
{
x=25;
}
else if(d1==4)
{
x=30;
}
else if(d1==5)
{
x=35;
}
else if(d1==6)
{
x=40;
}
y=7;
for (i=1;i<=j;i++)
{
gotoxy(x,y);
if(i==d) /* 记录当前输入月数与天数位置 */
{
x0=x;
y0=y;
}
printf("%d",i);
x=x+5;
if(x>40)
{
printf("\n");
x=10;
y=y+2;
}
}
gotoxy(1,15);
printf("\n\nNin de shu ru %d-%d-%d shi ",year,m,d);
printf(" No.%d day",sum);
printf("xing qi ( %d )\n",w);
printf("\nEsc to exit.");
printf(" row chang time .");
gotoxy(x0,y0);
}
int rqhfx(year,m,d)/* 日期合法性检测 */
{
sfrn(year);
if(year<0||m<0||m>12||d<0||d>31)
{
return 0;
}
else if((m==2 && d>(28+k)) || (m==4 && d>30)||
(m==6 && d>30) ||(m==9 && d>30)||(m==11 && d>30))
{
return 0;
}
else
{
return 1;
}
}
int shuru(c) /* 显示后,判断输入什么键。 */
{
if(c==0x48) /*up 年 + 1 */
{
year++;
sum=0;
tt=0;
return 0;
}
else if(c==0x50 && year>1) /*down 年 - 1 */
{
year--;
sum=0;
tt=0;
return 0;
}
else if(c==0x4b && m>1) /*left 月 - 1 */
{
m--;
sum=0;
tt=0;
return 0;
}
else if(c==0x4b && m==1) /* 处理到了 1月再减 1 的问题 */
{
sum=0;
m=12;
year--;
return 0;
}
else if(c==0x4d && m<12) /*right 月 + 1 */
{
m++;
sum=0;
tt=0;
return 0;
}
else if(c==0x4d && m==12)/*处理到了12月再加1的问题 */
{
sum=0;
m=1;
year++;
return 0;
}
else if(c==0x1b) /*Esc*/
{
return 1;
}
else /* 有点小问题没解决好,任意键都会显示,跟 getch()取到的光标键有关系 ; 问题得到了解决,详细情况见2楼,这里修改一下: 改为 else if( c != 0) */
{
return 2;
}
}
main()
{
char c=0;
intq=0;
inti=0;
start:
clrscr();
printf("Please input year month day :");
scanf("%d %d %d",&year,&m,&d);
q=rqhfx(year,m,d);
if(q==0)
{
printf("\n\nYour input is error !!! Try again .\n");
getch();
goto start;
}
work:
show(year,m,d);
work2:
c=getch();
i=shuru(c);
if (i==0)
{
goto work;
}
else if(i==1)
{
goto end;
}
else if(i==2)
{
gotoxy(3,20);
/* printf("%c %c",0x1,0x7); */
printf("\n Iput error ! Try again ...");
goto work2;
}
end:
clrscr();
gotoxy(10,2);
printf("\n\n======Thank you ! Good bye !======");
getch();
clrscr();
} 总体上不错
模块化设计的也不错
show函数有待改进
PS: 尽量不要在程序中出现goto指令 今天想到一个每次都会打印输入出错提示的办法,如果键盘输入的不是四个方向键或Esc键的话,就返回值2,提示键盘输入错误,问题是当键盘输入四个方向键时,会先得到一个 0 ,再得到 0x48 0x 50 0x 4B 0x 4D,主要就是要解决第一个得到的0的问题,我这样来修改
else --------> 改为 else if( c != 0)
{
return 2;
}
这样就可以解决每次因为输入方向键得到 0 与 0x48 0x 50 0x 4B 0x 4D 的问题了。
不过经测试,现在程序还没解决一个问题:在检测日期合法性时,没有过滤掉非数字键,要继续完善一下。
页:
[1]