那在这一节的最后呢,我们再举一个小的例子来看一下函数的一个 基本的作用。当然作为C程序的基本组成单位, 函数的作用非常的巨大。那么再这儿我们只给出了一个简单的例子,来展示一下函数的最基本的一个作用, 就是来组织程序。噢,也就是说啊, 利用函数,我们可以把一个挺大的程序啊, 切成一块一块的小程序。那么同时在这个 例子里头呢,我们也展示一下全局变量对整个程序的影响。 Okay,我们来看一个例子。这个题目是这样的。给定从公元 2000年1月1日开始逝去的天数, 啊,就是过去的天数。给你一个。然后呢,请你编写程序给出 当前的这一天,比方说,当时你已经过去多少多少天了,那么过去了这些天之后的那一天, 是哪年哪月哪日星期几。假设说我告诉你,从 2000年1月1号开始,过了3000天,那么3000天过去以后的那天, 是哪年哪月哪日星期几呢?那么这个题如果放 在理想状况下,它就非常的好解。比方说我们认为每年都有365天,然后每个月都有30天。 那这个题就特别好办了。 但是现在不同,这个题目给了两点提示。第一,你要注意闰年。 第二,注意每个月的天数 也不一样!而且闰年里的4月份跟平年的4月份的天数又不同。 那这就跟实际的情况完全一样了,对不对?那现在让你来解决一下这个问题,你想应该怎么 办呢?那有些同学可能觉得,哎哟,那是如果是按实际的算,那这个算法就复杂咯! 哦,也不复杂。哦,无非就是让我们体会一般现实和理想的差距而已。 好,我们再来看一下它对输入输出数据的要求。要求啊, 输入多组数据,每一组呢,一个正整数。 这个正整数呢,表示从2000年1月1号开始已经过去的天数。 对于输入的每个天数呢,要求你都 数出一行,这一行里头包含了对应的 日期和星期几。它的格式呢,是年-月-日, 然后星期几。啊,星期几呢,用英文来 表示。输入的最后一行是-1,那表示输入结束,不须要再特殊处理。 而且呢,你可以假设年数一定不会超过9999。 那大家思考一下,对于这样一个问题我们应该怎么去解它呢? 首先啊,有了我们前面关于输入输出的讨论, 那么虽然这个程序呢,是输入多组的数据,并且输出多组的数据。那我相信这个输入输出啊, 应该不是什么太大的困难了。 呵,所以说呢,我们可以集中力量来考虑如何来计算这个日期。 在这个程序里头啊,实际上须要我们计算出来的信息啊,有4个。 一个是年,一个是月,一个是日, 一个是星期几。那在这4个信息中呢, 有一个信息是最容易计算的。它不受其他信息的影响, 那就是星期几。 所以说,计算这个程序的一个基本的思路,我们,我们可不可以这样? 首先呢,我们定义一个变量,用来存放这个输入的天数。 然后呢,基于这样一个天数啊,我就开始一路的计算。 因为关于星期几的计算,不牵扯任何其他的问题。所以说呢, 我先基于这个日期啊,算出来。哦,那么当前这一天应该是星期几?那当然呢,需要我们查一下, 2000的1月1日,啊,它应该是个星期六。那么基于这个星期呢,我们就可以算出来 星期几。那么有了星期几以后啊,接下来我再计算年。 计算年的办法也不难。 我们就从总的天数里面减掉2000年的天数, 再减掉2001年的天数,再减掉2002年的天数,一直减下去。 也就是说要减掉每年的天数。那么, 直到减到剩下的天数不够一年, 噢,我们就得到了关于年的信息了。那么在这计数上呢,我们在减掉 每个月的天数,直到减到剩下的天数,不够一个月,余数我们就得出来 月的信息。那么最后剩下的那个天数就应该是日的信息。Okay, 这就是我们 解决这个问题的思路。那么当然在这个过程中,要减掉每年的 天数也不是一个特别简单的事情。这须要我们去计算要减掉的那一年 是不是闰年。啊,我们先要计算一下它是不是闰年,然后再减掉相应的天数。那减掉每 月的天数呢,也不是一个容易的事情。因为每个月的天数不同。噢,我们怎么样去减掉 每个月的天数呢?那么在这个地方啊,我们可以利用一个数组, 来枚举出每个月的天数。那无论如何,这个 题啊,我们可以分成这三步去解决。第一步,计算出星期几。 第二步,计算出年的信息。第三步,计算出月 的信息。最后呢,得到day的信息。啊,这是整个的这个程序。 哎呀,看上去还真的挺罗嗦的。啊,如果写到一个程序里头,这个程序毕竟是比较长的。 那么在这儿呢,我们就可以用一个函数来做一个组织。比方说我们先来看它的主程序。 这个主程序可以长成这样子。在这个主程序里头呢,首先我定义了 一个全局的变量,days。但是因为啊, 这个days在所有的函数里头啊,可能都要用到。然后呢,我定义了三个函数。 第一个函数呢,是get_dayofweek(), 啊,用来计算星期几。第二个函数就是get_year(), 我获得年的信息。 第三个函数是get_month(), 我获得月的信息。 那么整个程序的架构呢,也非常简单。看这儿! 对于输入的每一天,那么只要这一天不等于-1。当然等于-1的话整个程序就结束了。 呵,我先求出星期几,然后呢,再求出 年的信息。然后呢,我计算一下最后的 那一年是不是一个闰年。 然后把这个信息呢,告诉接下来的这个函数去获得月的信息。 这leap_year做一个输入参数,输入给get_month()。哦,然后呢,求出月的信息。 啊,这是整个程序的组织。从这个主程序我们就可以看出来,由于 使用了这一些函数,它使主程序变得特别的简明。 好,我们看到这个主程序我们就可以知道它每一部在做什么。 不仅如此,通过使用这些函数, 我们还把一个大的程序拆分成了好多小的程序。这将有利于啊,我们 把一个程序分给多个人去协同 完成。比方说我们现在把写这个程序的任务 交给了一个小组。那这个小组里头呢,一共有 4个人。那这4个人就可以做一个分工。 有一个人呢,来写main函数。然后呢,把这三个函数get_dayofweek(), get_year(), get_month(), 分别分给另外三个不同的同学。这样的话,这4个人呢, 就可以协同完成这一个大的程序了。这是函数的另一个作用。 所以说利用函数啊,我们可以把一个大的程序拆分成多个小的。 我们可以把一个总的任务分给多个人去完成。 其实呢,有种倒分本身就是一个结构化程序设计的重要思想之一。 那么有了这个思路之后啊,我们再去组织这个程序,就会变得简单了。 那么关于这个程序的细节呢,我们在这儿就不详细的去讨论了。 那么大家呢,可以参考PPT中给出来的程序。哦,自己呢,试着去写一下。 那么同时呢,在这个程序里头啊,还有一点事情想跟大家分享。 在这个程序里头啊,我们定义了一个全局变量,就是days。 这个全局变量呢,根据刚才我们的思路,在get_dayofweek()这个函数中, 我们会用了它。在get_year()这个函数里头, 我们也会用到它。并且在这个里头还会改变它。 因为我们要从这个days里面减掉每年的天数。那么在get_month()的这个函数里头呢,也 会用到这个days。也就是说啊,这个全局变量在 接下来的三个函数以及主函数里头都要用到这个 全局变量。那么这样做会不会有什么问题呢? 的确会带来一些问题。 第一个问题,因为days在三个函数里面都会用到, 而且呢,有的函数还会改变它。所以万一在get_year()里面, 啊,你不要说程序我没写好,写错了,这个错误就会直接的传递到 get_month()这个函数中去。比如说,无论get_month() 这个函数做得对不对,它的计算基础都是错误的。 也就是说因为days是一个贯穿三个函数的一个全局变量从而使得 围绕着days所番的错误都会在这些函数里面有所体现, 这是第一个麻烦。第二个麻烦,就如刚才我们所设想的那个场景。 假设说我们把整个的那个程序分给4个同学去完成。然后呢,这4个同学必须都 记得有一个days这样的全局变量。 而且呢,关于这个全局变量的使用我们必须严格的 限定下来,来联合开发这个程序的4位同学之间多了很多交流上的麻烦。 也就增加了犯错误的概率。这就是这个全局变量带给我们的 麻烦。在这儿呢,关于全局变量和函数的关系,我们做一个总结。 通过这个题目,我们就可以看到,全局变量 的使用啊,有的时候确实会给我们提供一定的便利。 但是呢, 因为引入了全局变量,往往就破坏了函数的相对独立性。 哦,像刚才我们的这个程序,那么几个函数呢,就被串在了一起。那像羊肉串一样把它给串在一起了。 每个函数都没办法独立的发挥作用。 而且呢,它增加了函数之间的耦合性。也就是说当 某一个函数里头,对这个全局变量进行了一些操作以后,很有可能 会通过这个全局变量而影响到其他的函数,这也是一个非常不好的一点。 同时呢,函数之间的这种交互啊,也变得不够清晰了。 也比方说关于年的计算。哦,其实在年的计算这个函数里面有两个返回的结果。 一个呢,是返回了当前的年数。另一个呢,实际上是体现在全局变量上面。在全局变量中 减掉了以往年的天数。但是呢,由于这个全局变量的存在使得 这两个结果并没有明显的体现在函数的返回值上。 所以说啊,由于这些问题的存在就提醒我们必须要谨慎的 使用全局变量。所以说呢,我们给出的建议是不在非常必要的情况下, 请你不要使用全局变量。 噢,我们要尽量保持函数的相对 独立性,降低函数之间的耦合性。并且呢, 要尽可能的提高函数之间进行交互的清晰度。 Okay,那么关于这样一个例子讨论呢,我们就进行到这里。 当然关于函数更多的内容我们会在后续的 课程里头啊,做更多的介绍。Okay, 那么今天的课呢,我们就进行到这里。 谢谢大家!