用C语言写个程序推算出是星期几?(用泰勒公式实现)
在日常生活中,我们常常遇到要知道某一天是星期几的问题。有时候,我们还想知道历史上某一天是星期几。比如:
“你出生的那一天是星期几啊?”
“明年五一是不是星期天?我去找你玩?”
通常,解决这个问题的最简单办法就是看日历,但是我们总不会随时随身带着日历,更不可能随时随身带着几千年的万年历。老师告诉我们,学习C语言,就是为了用它来帮助我们解决实际问题的,那么,既然我们通过《C程序设计伴侣》学了C语言,如何用C语言写个程序来推算出自己出生的那天是星期几呢?
答案当然是肯定的(要不然,我也不会在这里啰嗦)。要计算日期所对应的星期,有一个著名的泰勒公式:
w = [ c/4 ] – 2c + y + [y/4] + [13 * (m+1) / 5] + d – 1
其中,c是年份的前两位,y是年份的后两位,m是月份,d是日期,这里需要注意的是,如果是1月和2月,c和y需要按照上一年来取值。比如,我们要 计算2013年1月28日,那么,c=20,y=12(因为是1月,按照上一年取值),m=1,d=28。将这些按照日期获得的数据带入公式,得到的w除 以7,得到的结果是几就是星期几,如果是0则是星期日。另外还需要说明的是,公式中的中括号[…]表示取其中计算结果的整数部分。
按照上面的公式算法,加上我们从《C程序设计伴侣》中学到的关于函数和日期处理的知识,我们可以将这个公式的算法实现为:
// whatday.c 根据泰勒公式推算日期对应的星期
#include <stdio.h>
#include <string.h>
#include <time.h> // 根据日期推算星期
int whatday(int year,int mon,int day)
{
int m = mon;
int d = day;
// 根据月份对年份和月份进行调整
if(m <= )
{
year -= ;
m += ;
}
int c = year / ; // 取得年份前两位
int y = year % ; // 取得年份后两位 // 根据泰勒公式计算星期
int w = (int)(c/) - *c + y + (int)(y/)
+ (int)(*(m+)/) + d - ; return w%; // 返回星期
} // 将数字转换成字符串
char* convertday(int w,char* str)
{
if(w< || w> || NULL == str)
return NULL; char* days[];
days[] = "Sunday";
days[] = "Monday";
days[] = "Tuesday";
days[] = "Wednesday";
days[] = "Thursday";
days[] = "Friday";
days[] = "Saturday"; // 转换
strcpy(str,days[w]); return str;
}
int main(int argc,char* argv[])
{
// 检查参数
if(argc != && argc != )
{
puts("usage: whatday or whatday 2013 1 28");
return ;
} int year = ;
int mon = ;
int day = ;
// 根据不同参数,获取日期
if( == argc)
{
// 如果只有一个参数,以当前日期作为查询日期
time_t t = time(NULL);
struct tm* cur = localtime(&t); year = cur->tm_year + ; // 年份
mon = cur->tm_mon + ; // 月份
day = cur->tm_mday; // 日期
}
else if( == argc)
{
// 将参数转换成日期
year = atoi(argv[]);
mon = atoi(argv[]);
day = atoi(argv[]);
}
else
{
puts("usage: whatday.exe 1981 9 22");
return ;
} // 根据日期计算星期
int w = whatday(year,mon,day);
// w 有可能是负数,转换为正
if(w < )
{
w += ;
} char daystr[] = ""; // 将数字表示的星期转换为字符串
if(NULL != convertday(w,daystr))
{
// 输出推算结果
printf("%d-%d-%d is %s.",year,mon,day,daystr);
} return ;
}
编译这个程序得到whatday.exe应用程序,使用它,我们就可以方便地推算出自己出生的那一天是星期几了:
F:\code>gcc -o whatday.exe whatday.c
F:\code>whatday 1981 9 22
1981-9-22 is Tuesday.F:\code>
根据程序的推算结果,我现在终于知道了原来我是周二出生的啊。感谢泰勒老师,感谢他发现的泰勒公式(太伟大了),感谢C语言,感谢《C程序设计伴侣》,还有CCTV,MTV,感谢。。。还有人和我一样是周二出生的吗?
最后,虽然这种方法简单是简单,但是正如sw老师在平论中提到的那样,它可能会遇到日期被人为调整的特殊情况,在这些特殊情况下,就可能有问题了。那么,要处理这些特殊情况,又该怎么办呢?
在C语言中,解决问题的办法永远不止一个
我们应当时刻记住这句话。同样,要推算某个特定日期对应的星期,也肯定不止泰勒公式这唯一的一种方法。正如sw老师在评论中提到的那样,我们可以利用C标准库中的时间函数mktime()和localtime()来达到同样的目的。
首先,我们可以用分解时间(struct tm)表示我们要推测的时间点(比如,1981年9月22日),然后mktime()函数可以把用分解时间表示的这个固定的时间点转换为日历时剧(用time_t表示),然后再用localtime()函数将这个日历时间转换为分解时间,我们就可以得到这个日期对应的星期数(分解时间的tm_wday成员)。虽然整个过程稍微麻烦了一点,但是其正确性可以得到保证(即使出了问题,也该标准委员会的那些大佬们负责)。你可以按照这个思路自己实现,也可以参考下面的实现。
// whatday.c 使用C标准库中的mktime()函数推算日期对应的星期
#include <string.h>
#include <time.h>
#include <stdio.h>
// 根据日期的年月日得到星期
int whatday(int year,int mon,int day)
{
struct tm t;
memset(&t,,sizeof(t));
// 用年月日填充分解时间t
t.tm_year = year - ; // 减去起始年份
t.tm_mon = mon - ; // 起始月份
t.tm_mday = day;
// 将分解时间t转换为日历时间ct
time_t ct = mktime(&t);
if(- == ct) // 日期错误
{
return -;
}
else
{
// 用localtime()函数获取日历时间ct对应的
// 分解时间,其tm_wday成员就是我们需要的星期数
struct tm* bt = localtime(&ct);
return bt->tm_wday;
}
}
// 将数字转换成字符串
char* convertday(int w,char* str)
{
if(w< || w> || NULL == str)
return NULL;
char* days[];
days[] = "Sunday";
days[] = "Monday";
days[] = "Tuesday";
days[] = "Wednesday";
days[] = "Thursday";
days[] = "Friday";
days[] = "Saturday";
// 转换
strcpy(str,days[w]);
return str;
}
int main(int argc,char* argv[])
{
// 检查参数
if(argc != && argc != )
{
puts("usage: whatday or whatday 2013 1 28");
return ;
}
int year = ;
int mon = ;
int day = ;
// 根据不同参数,获取日期的年月日
if( == argc)
{
// 如果只有一个参数,以当前日期作为查询日期
time_t t = time(NULL);
struct tm* today = localtime(&t);
year = today->tm_year + ;
mon = today->tm_mon + ;
day = today->tm_mday;
}
else
{
// 将参数转换成日期
year = atoi(argv[]) ;
mon = atoi(argv[]);
day = atoi(argv[]);
}
// 根据年月日查询星期几
int w = whatday(year,mon,day);
char daystr[] = "";
// 将数字表示的星期转换为字符串
convertday(w,daystr);
// 输出推算结果
printf("%d-%d-%d is %s.",year,mon,day,daystr);
return ;
}
对比上次的代码我们会发现,我们只是改变了whatday()函数的实现,其它代码并没有发生太大变化。如果你学过《C程序设计伴侣》中提到的字符串处理函数(strcha()和strcpy()以及ctime()函数),还可以将这个程序进一步简化。到底如何进行,看过书了解这些函数后就知道了,你一定可以的。
当然,利用mktime()和localtime()函数配合使用的应用远远不止这些,比如,接下来我们就会用他们来计算每个月的第一个星期一所对应的日期。
转自:http://www.howzhi.com/course/3387/lesson/43160
用C语言写个程序推算出是星期几?(用泰勒公式实现)的更多相关文章
- 学了C语言,如何写个程序计算出每个月的第一个星期一对应的日期
在前面,我们分别利用泰勒公式和C标准库中的mktime()函数推算了某个特定日期所对应的星期几,刚做完这些,就又遇到了一个与日期相关的新任务: 老板把每个月例会的时间定在了每个月的第一个星期一,他让我 ...
- PIC12F629帮我用C语言写个程序,控制三个LED亮灭
http://power.baidu.com/question/240873584599025684.html?entry=browse_difficult PIC12F629帮我用C语言写个程序,控 ...
- C语言写CGI程序
一.CGI概述 CGI(公用网关接口)规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准.Web服务器通过调用CGI程序实现和Web浏览器的交互, 也就是CGI程序接受Web浏览器发送给 ...
- 用C语言写一个程序,得出当前系统的整形数字长(16位,32位,64位)等,不能使用sizeof()
#include <iostream>#include <cmath>using namespace std; int main(){ int num = -1; unsign ...
- python为什么是高级语言和解释型编程语言?它是如何粘合其它语言写的代码的?
学习python之初,不知道大家对于python有没有疑惑,应当是有的.这里我整理出来了自己的一些疑惑,供大家参考. 为什么python是高级程序设计语言 Java,C,C++这些语言是高级语言, ...
- C语言写的流氓关机程序及破解
记得大二刚开始接触电脑的那个时候,偶尔会弹出一个强制关机的窗口,当时没有办法,如下: 现在看来只是一个小程序而已,用C语言编写的: #include<windows.h> int main ...
- 写一个程序,统计自己C语言共写了多少行代码,Github基本操作
前言 在上一篇博客中,本人提到了自己的文件操作可以说是几乎没用过.现在想想,这也算是只在OJ上做题的一个弊端吧.虽然通过OJ做题是一个学习代码好手段,但其他方面也要多多涉猎才好,而不是说OJ用不到文件 ...
- 用Racket语言写了一个万花筒的程序
用Racket语言写了一个万花筒的程序 来源:https://blog.csdn.net/chinazhangyong/article/details/79362394 https://github. ...
- 出错的方法有可能是JDK,也可能是程序员写的程序,无论谁写的,抛出一定用throw
应对未检查异常就是养成良好的检查习惯. 已检查异常是不可避免的,对于已检查异常必须实现定义好应对的方法. 已检查异常肯定跨越出了虚拟机的范围.(比如“未找到文件”) 如何处理已检查异常(对于所有的已检 ...
随机推荐
- Android编程: Activity生命周期和LogCat使用
学习内容:Activity生命周期和LogCat使用 ====Activity生命周期==== 图示(转载): 创建 onCreate重启 onRestart开始 onStart恢复 ...
- LinqToExcel: LINQ查询Excel电子表格
Linq的强大人所共知,能不能将Linq扩展到读取excel呢? 答案当然是肯定的. LinqToExcel就是一个实现了使用Linq语法查询excel表格的.net开源类库. 在nuget搜索下载安 ...
- Ombrophobic Bovines - POJ 2391
Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the ...
- bzoj 2327 构图暴力判断+独立集个数
首先我们可以处理出10^6以内的所有的勾股数,如果我们有2*i-1和2*j互质, 那么A=(2*i-1)*(2*i-1)+(2*i-1)*(2*j),B=2*j*j+(2*i-1)*(2*j)为互质 ...
- 【BZOJ】【3004】吊灯
思路题 要将整棵树分成大小相等的连通块,那么首先我们可以肯定的是每块大小x一定是n的约数,且恰好分成$\frac{n}{x}$块,所以我有了这样一个思路:向下深搜,如果一个节点的size=x,就把这个 ...
- Oracle 11g安装与使用
作为一个新手,学习Oracle,就连安装oracle都感觉到吃力! 经过不间断的搜罗.学习.尝试,找到一些比较有用的“指导”,罗列如下: 1. http://www.2cto.com/database ...
- ActiveMQ主从配置
这种方式有个问题,activemq1有消息没消费完但是突然宕机,虽然程序会自动连到activemq2.但是activemq1的消息只有等机器恢复后才会被消费. 1.启动:我这里使用的是apache-a ...
- css属性简写集合
作为一个前端攻城狮,CSS那绝对是基础,可是基础也有掌握不牢的时候.今天就来总结一下容易写错的CSS属性简写问题. 1.background 背景颜色:background-color ...
- datepicker,结束时间必须大于开始时间
$('#js-start-time').datepicker({ dateFormat:'yy-mm-dd', onSelect: function( startDate ) { var $start ...
- 利用Jquery实现http长连接(LongPoll) {转}
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JqueryAjaxLongPo ...