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;
}

执行结果如下:

执行结果

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

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语言代码训练营(第七天)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,069评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,212评论 1 287
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,912评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,424评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,741评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,194评论 1 206
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,553评论 2 307
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,289评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,923评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,251评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,775评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,144评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,698评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,936评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,658评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,214评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,159评论 2 258

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,534评论 25 707
  • 继续我们之前的项目,上一篇中我们完成了自己的String类型设计,封装了相关的功能。有朋友留言中提到C语言中有相应...
    天花板阅读 3,961评论 8 52
  • 上一篇中我们用项目思维把我们的程序做了大的调整,收到的大部分反馈邮件都说基本能看懂。今天我们来实现最后一部分功能。...
    天花板阅读 3,818评论 17 49
  • 顺着你的方向是斟满酒的杯盏是要离岸的船只是即将倒塌的鼓楼 于一千零一夜你檠着通明的月亮来寻这满山的坡石来寻这喧嚣的...
    买金矿阅读 485评论 8 27
  • 菠萝大叔寻找小菠萝的故事在村子里都传开了,人们看着一个爱子情深的父亲守望的眼神,每个人都在心里默念着,如果看到了大...
    汪八万阅读 1,153评论 0 1