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

作者: 天花板 | 来源:发表于2015-11-30 00:00 被阅读2314次

    上一篇中打印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;
    }
    

    执行结果如下:

    执行结果

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

    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 <stdio.h>
    
    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;
    }
    

    执行结果如下:

    Part-1.png Part-2.png Part-3.png

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

    3. 课后练习题

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

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


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

    相关文章

      网友评论

      • Hans941:http://www.jianshu.com/p/1b19d6aac9d0
        这种代码会不会很乱,虽然结果正确,别人应该会很难读把。
        这是属于“封装”不好的问题吗?
        Hans941:@天花板 1.除了主函数外的变量命名是潦草了,以后会注意这个问题。
        2.代码缩进自己没有加空格,采用的是Visual Studio中的默认规则。这样有什么坏处吗?
        3.查了资料不加大括号是有很多隐患,以后会都加上。
        天花板:@Aha_斌 目前和封装没有关系。我主要提三个建议:1.变量命名要规范,2.代码缩进要规范,包括符号两边的空格,3.if和for这种下面只有一行代码的时候把大括号写上。原因之前都提过,有问题我们再讨论
      • 丿Diana:默默问一下一月一日星期几怎么计算?
      • 9bde52cf824f:请问相应年份1月1号对应的是星期几,
        (35 + year + year / 4 - year / 100 + year / 400) % 7
        这个公式怎么得到的?
      • e52bddf8c51c:真是六啊
      • _NULL_PTR:很好,学习了,谢谢大神:pray:
      • 17719360720:int GetDays(int year, int month)
        {
        if (month == 2 && IsLeapYear(year))
        {
        return g_days[month - 1] + 1;
        }
        else
        {
        return g_days[month - 1];
        }
        }
        此处代码好像有点小问题,导致2015年2月有28天,第一个应该是return 应该跟第二个互换
      • 不言说的怦然心动:而且计算每一年一月一号是周几的公式只能用于2015年换一个就不行了
        17719360720:@不言说的怦然心动 你可以加一个scanf 函数呀
      • 不言说的怦然心动:代码有一点问题,敲出来和你的结果不太一样,自己给改好了,提高了不少谢谢大神
      • 一颗不想长肉的仙人掌:想着早点开java,期待哦。

      本文标题:21天C语言代码训练营(第六天)

      本文链接:https://www.haomeiwen.com/subject/tlqjhttx.html