21天C语言代码训练营(第六天)

上一篇中打印2015年日历的程序不知道大家是否写出了,今天我们来用标准程序设计的思想来解决这个问题。

1. 功能分析

在程序设计过程中,我们需要把最基本的功能分析出来,之后封装成功能函数。这样,在最后主程序中只需要通过各种函数调用像搭积木一样把这些功能组合起来就OK了。下面我们具体看看这道题。

1.1 月份打印

打印月份是个比较麻烦的工作,我们需要写一个函数,输入int型的月份,在屏幕中打印出相应的月份名称。

首先,我们编程实现打印一年12个月份的程序。程序如下:

int main()
{
    int i;
    char month[12][10]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

    for (i = 0; i < 12; i++)
    {
        printf("%s\n", month[i]);
    }

    return 0;
}

执行结果如下:

21天C语言代码训练营(第六天)_第1张图片
执行结果

这个程序中,我们通过一个二维数组保存每个月的字母名称,之后通过数组下标完成相应的月份打印。现在我们把核心功能进行函数封装。代码如下:

char g_month[12][10] = {"January", "February", "March", "April", "May", "June",
                    "July", "August", "September", "October", "November", "December"};

// 通过月份数字打印月份名称
void PrintMonth(int month)
{
    printf("%s", g_month[month - 1]);
}

int main()
{
   int i;
   for (i = 0; i < 12; i++)
   {
       PrintMonth(i + 1);
       printf("\n");
   }

   return 0;
}

这段代码中的PrintMonth函数和全局变量g_month就是我们封装的打印月份的功能。

1.2 判断闰年

知道了平年还是闰年才能知道2月份究竟是几天。因此这个函数必不可少。

// 判断闰年,是闰年返回1,是平年返回0
int IsLeapYear(int year)
{
    if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        return 1;
    else
        return 0;
}

1.3 判断一年的第一天是周几

代码如下:

// 返回输入年份的1月1日是周几
int GetWeek(int year)
{
    return (35 + year + year / 4 - year / 100 + year / 400) % 7;
}

1.4 判断每个月的天数

这里需要一个通过年份和月份判断天数的函数。代码如下:

int g_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// 返回输入的年份中输入的月份天数
int GetDays(int year, int month)
{
    if (month == 2 && IsLeapYear(year))
    {
        return g_days[month - 1] + 1;
    }
    else
    {
        return g_days[month - 1];
    }
}

又是一个全局变量和一个函数的组合,这种形式其实是数据结构的思想,通过一个或一些函数来管理一段空间的操作。

2. 功能函数组合

正题流程如下:

  • 判断当年1月1日是周几
  • 循环12个月,每个循环单元中执行下面的工作:
    • 打印月份名
    • 打印星期表头
    • 通过打印空格找到本月1日的具体位置
    • 计算出当月有多少天
    • 依次打印出每一天,每7个数字一次折行

代码实现中,尽量使用前面封装好的函数。代码如下:

#include 

char g_month[12][10] = {"January", "February", "March", "April", "May", "June",
                    "July", "August", "September", "October", "November", "December"};

int g_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// 通过月份数字打印月份名称
void PrintMonth(int month)
{
    printf("%s", g_month[month - 1]);
}

// 判断闰年,是闰年返回1,是平年返回0
int IsLeapYear(int year)
{
    if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        return 1;
    else
        return 0;
}

// 返回输入年份的1月1日是周几
int GetWeek(int year)
{
    return (35 + year + year / 4 - year / 100 + year / 400) % 7;
}

// 返回输入的年份中输入的月份天数
int GetDays(int year, int month)
{
    if (month == 2 && IsLeapYear(year))
    {
        return g_days[month - 1] + 1;
    }
    else
    {
        return g_days[month - 1];
    }
}

int main()
{
    int i, j, k;
    int week;
    int days;
    int year = 2015;

    // 计算当年的1月1日是周几的公式
    week = GetWeek(year);

   for(i = 0; i < 12; i++)
   {
       printf("\n");

       PrintMonth(i + 1);

       printf("\n");

       printf("---------------------------\n");
       printf("Sun Mon Tue Wed Thu Fri Sat\n");

       for(k = 0; k < week; k++)
           printf("    "); // 每月一号对齐它的星期数

       // 这个月的每一天和星期对齐输出
       days = GetDays(year, i + 1);
       for(j = 1; j <= days; j++)
       {
            printf("%3d ", j);
            if(++week >= 7)
            {
                printf("\n");
                week = week % 7;
            }
        }
        printf("\n");
    }
    return 0;
}

执行结果如下:

21天C语言代码训练营(第六天)_第2张图片
Part-1.png
21天C语言代码训练营(第六天)_第3张图片
Part-2.png
21天C语言代码训练营(第六天)_第4张图片
Part-3.png

今天的讲解主要以代码进行展示,如果有问题欢迎探讨。

3. 课后练习题

今天这个题目可以继续追加功能,请自己完成输入任意年份打印当年的日历。同时,把12个月的日历打印成6行2列。请仔细思考一下。

我是天花板,让我们一起在软件开发中自我迭代。
如有任何问题,欢迎与我联系。


上一篇:21天C语言代码训练营(第五天)
下一篇:21天C语言代码训练营(第七天)

你可能感兴趣的:(21天C语言代码训练营(第六天))