第2个回答 2017-11-01
与网友分享
勇于探索 追求简朴
学习《C语言的科学和艺术(中文版)》随记
#include <stdio.h>
#include "genlib.h"
#include "simpil.h"
#define Sunday 0
#define Monday 1
#define Tuesday 2
#define Wednesday 3
#define Thursday 4
#define Friday 5
#define Saturday 6
void GiveInstructions(void);
int GetYearFromUser(void);
......;
bool IsLeapYear(int year);
main()
{
int year;
GiveInstructions();
year = GetYearFromUser();
PrinCalendar(year);
}
void GiveInstructions(void)
{
......;
}
......
......
......
bool IsLeapYear(int year)
{
return (((year%4==0) && (year%100 != 0)) || (year%400==0));
)
以上是美国 Eric S. Roberts 博士编著的《C语言的科学和艺术》一书中第5章的例题程序(由于该程序较长,为使本文篇幅短小,故未全部录下)。能编著这样一本关于计算机知识的书,应该是大师级的水平。该例题是一个输入不小于1900即可打印输入年份月历的程序。由于本人初学C语言,刚开始被该例题程序的函数嵌套调用搞得晕头转向,看了好长时间才终于弄明白该程序的功能。首先要说明的是:TURBO C 2.0 没有该书作者自己编写的函数库,几经周折从网上找到所需源程序,却不能通过编译,只得改用C标准库的函数。改用C标准库的函数,就必须对书中的例题程序作较大改动,也同样费了不少周折才终于通过编译。
在学习过程中,本人发现该例题程序有好多问题。
1. 用 define 定义了在程序中用不到的多余符号常量;
2. 定义的函数过多,令人看得眼花缭乱;
3. 函数的层层嵌套调用使得程序逻辑混乱,将人搞得晕头转向。
4. 函数 int FirstDayOfMonth(int month,int year) 被调用12次,而其中求从2月份到12月份第一天是星期几的 for 循环也是多余的。
于是本人经过思考,决定修改该程序。修改后的程序短小精悍,函数调用无层层嵌套现象,看得清楚明白,也没有多余的函数调用。经过修改后的程序可以通过 GCC10、WINTC、TURBO C 2.0 编译器的编译,但只有 GCC10 编译器编译的该程序才能正常显示中文。修改后的程序附在本文的最后。
学而后思,获益不菲;学而不思,难得真谛。我们应当敬重大师,向大师虚心学习。但不能迷信大师,大师写出的东西不可能都是经典范例,更不是改不得的金科玉律,要用自己的头脑思考,去发现问题并解决问题,从而提高自己的认识水平及解决问题的能力。而这正是我们学习的最终目的。
附经过修改后的例题程序如下:
#include <stdio.h>
#define MOND 1
#define SATU 6
void prim(int month,int year,int ndays,int weekday);
int firs(int year);
int main(void)
{
int year=0,month,weekday,ndays[12]={31,28,31,30,31,31,30,31,30,31,30,31};
printf(" 这是一个输入年份数即可打印该年份年历的程序\n");
while(year<1900)
{
printf(" 请输入一个不小于1900的年份数: ");
scanf("%d",&year);
}
printf("\n");
if(((year%4==0) && (year%100 != 0)) || (year%400==0))
ndays[1]=29;
weekday=firs(year);
for(month=1;month<13;month++)
{
prim(month,year,ndays[month-1],weekday);
weekday=(weekday+ndays[month-1])%7;
printf("\n");
}
printf(" %d 年历已打印完毕, 再见!",year);
return 0;
}
void prim(int month,int year,int ndays,int weekday)
{
const char yue[12][10]={"1月","2月","3月","4月","5月","6月","7月",
"8月","9月","10月","11月","12月",};
int i,day;
printf(" %d年 %s\n",year,yue[month-1]);
printf(" 日 一 二 三 四 五 六\n");
for(i=0;i<weekday;i++)
printf(" ");
for(day=1;day<=ndays;day++)
{
printf(" %2d",day);
if(weekday==SATU)
printf("\n");
weekday=(weekday+1)%7;
}
if(weekday+6 != SATU)
printf("\n");
}
int firs(int year)
{
int weekday=MOND,i;
for(i=1900;i<year;i++)
{
weekday=(weekday+365)%7;
if(((i%4==0) && (i%100 != 0)) || (i%400==0))
weekday=(weekday+1)%7;
}
return weekday;
}
写于17:41 2017/11/1