从“HDU 2005 第几天?”谈起
在程序设计中,日期时间的处理经常会遇到。在C语言程序设计的一些教材中会出现如下例子或习题。
【例1】第几天? (HDU 2005)
给定一个日期,输出这个日期是该年的第几天。
Input
输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,另外,可以向你确保所有的输入数据是合法的。
Output
对于每组输入数据,输出一行,表示该日期是该年的第几天。
Sample Input
1985/1/20
2006/3/12
Sample Output
20
71
(1)编程思路1。
对于month月,需要累计1~month-1月的各个月份的天数。例如,month等于8,需要累计1~7月的天数,即d=0+31(1月)+28(或29、2月天数)+31(3月)+30(4月)+31(5月)+30(6月)+31(7月),这个操作可以写成循环,如:
d=0;
for( i=1; i<=month-1; i++)
d=d+第i月的天数;
但也可以不写成循环,用switch…case结构来解决。因为,大的月份一定包含小的月份的累计,因此,在case常量表达式的安排时,可以从大到小,并且每个入口进入后,不用break语句退出switch结构,这样可以完成累计,具体描述为:
d=0;
switch(month-1)
{
case 11:d+=30;
case 10:d+=31;
case 9:d+=30;
case 8:d+=31;
case 7:d+=31;
case 6:d+=30;
case 5:d+=31;
case 4:d+=30;
case 3:d+=31;
case 2:d+=28(或d+=29);
case 1:d+=31;
}
另外,在程序中,需要判断某一年是否闰年,因为闰年的2月份为29天,而非闰年的2月份为28天。
闰年的判定条件是:①能被4整除,但不能被100整除的年份都是闰年,如1996年,2004年是闰年;②能被100整除,又能被400整除的年份也是闰年。如2000年是闰年。可以用一个逻辑表达式来表示:
(year%4==0&&year%100! =0) | | year%400==0
当year为某一整数值时,如果上述表达式值为true(1),则year为闰年;否则year为非闰年。
(2)源程序1。
#include <stdio.h>
int main()
{
int year,month,day,d;
while (scanf("%d/%d/%d",&year,&month,&day)!=EOF)
{
d=0;
switch(month-1)
{
case 11:d+=30;
case 10:d+=31;
case 9:d+=30;
case 8:d+=31;
case 7:d+=31;
case 6:d+=30;
case 5:d+=31;
case 4:d+=30;
case 3:d+=31;
case 2:d+=28;
if (year%4==0 && year%100!=0 || year%400==0) d++;
case 1:d+=31;
}
d=d+day;
printf("%d\n",d);
}
return 0;
}
(3)编程思路2。
学习过数组后,我们可以将每个月的天数保存在数组table[13]中,其中table[i]的值为第i月的天数。这样用一个循环完成累加即可。2月先保存默认天数28,对闰年进行特别处理。
这样写出的程序更简洁。在我们学习的过程中,应将写出简洁高效的程序作为自己程序设计的风格和目标。
(4)源程序2。
#include <stdio.h>
int main()
{
int table[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int year,month,day,d,i;
while (scanf("%d/%d/%d",&year,&month,&day)!=EOF)
{
d=0;
for (i=1;i<=month-1;i++)
d+=table[i];
if (month>2 && (year%4==0 && year%100!=0 || year%400==0))
d++;
d=d+day;
printf("%d\n",d);
}
return 0;
}
【例2】几月几日。
输入一个年份year和一个整数d,求year年的第d天是几月几日? 例如,输入2006 71,输出应为3 12,即2006年的第71天是3月12日。
(1)编程思路。
执行例1中程序的逆过程。为简化计,程序中采用二维数组来分别保存非闰年和闰年各月的天数。用循环先确定第d天前有多少月,减去各月的天数后,剩余的就是几日。
(2)源程序。
#include <stdio.h>
int main()
{
int table[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31}
,{0,31,29,31,30,31,30,31,31,30,31,30,31}};
int year,month,day,d,leap;
while (scanf("%d %d",&year,&d)!=EOF)
{
month=1;
if (year%4==0 && year%100!=0 || year%400==0)
leap=1;
else
leap=0;
while (d>table[leap][month])
{
d-=table[leap][month];
month++;
}
day=d;
printf("%d %d\n",month,day);
}
return 0;
}
【例3】今天星期几。
输入一个日期的年、月、日后,输出该日期是星期几。
(1)编程思路。
设变量year、month和day分别表示输入的年、月和日。在例1中我们求了一个日期是当年的第几天(设为d),由于一个星期有7天,因此,如果我们知道该年的元旦是星期几(设为week),那么该日期是星期几就可以确定了,计算公式为:(week+d-1)%7。0代表星期日。
怎样求年号为year这年的元旦是星期几呢?用一个简单公式即可计算出来。
已知 公元 1 年 1月 1日 为星期一。别问为什么,日历编撰的起点,就是这么规定了。
我们知道一年有365天(当然闰年会有366天,先不管了),每7天1周,365%7=1。即若不考虑闰年,则每年的元旦是星期几应该是上一年元旦星期几的后一天。
由于 1 年元旦是星期一,因此 2年元旦星期二,3年元旦星期三,4年元旦星期四,…即
week =(year)%7。
由于闰年的存在会在2月多一天,因此,闰年的下一年元旦星期几应再加1,即 5年为星期六(不是星期五,因为 4年是闰年),因此需要知道前year-1年中有多少个闰年。闰年的规则简述就是每4年一个闰年,每100年不是闰年,每400年又是闰年。按集合包含与容斥规则,闰年个数有 (year-1)/4 - (year-1)/100 + (year-1)/400。
因此,已知年号year,就可以根据year计算出该年元旦是星期几。计算公式如下:
week=[ year+(year-1)/4-(year-1)/100+(year-1)/400]%7;
(2)源程序。
#include <stdio.h>
int main()
{
int table[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
char str[7][3]={"日","一","二","三","四","五","六"};
int year,month,day,d,i,week;
while (scanf("%d/%d/%d",&year,&month,&day)!=EOF)
{
week=(year+(year-1)/4-(year-1)/100+(year-1)/400)%7;
d=0;
for (i=1;i<=month-1;i++)
d+=table[i];
if (month>2 && (year%4==0 && year%100!=0 || year%400==0))
d++;
d=d+day;
week=(week+d-1)%7;
printf("%d 年 %d 月 %d日 星期%s\n",year,month,day,str[week]);
}
return 0;
}
从“HDU 2005 第几天?”谈起的更多相关文章
- hdu 2005 求第几天(水题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2005 转载于:https://blog.csdn.net/tigerisland45/article/ ...
- HDU 2005 第几天?(闰年判断)
传送门: acm.hdu.edu.cn/showproblem.php?pid=2005 第几天? Time Limit: 2000/1000 MS (Java/Others) Memory L ...
- HDU 2005 (水)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2005题目大意:给定年份,计算是第几天 解题思路: 很水,判定下是否为闰年,方法:四年一闰,百年不闰,四 ...
- hdu 2005 - 第几天?
题意:判断是否为闰年 解法:这题需要注意一下用scanf能直接读入year,month,day 附上代码: 1: #include<stdlib.h> 2: #include<str ...
- hdu 2005 java
题意: 输入数据格式为YYYY/MM/DD,对于每组输入数据,输出一行,表示该日期是该年的第几天. 思路: 使用Calendar.DAY_OF_YEAR import java.text.ParseE ...
- [翻译]初识SQL Server 2005 Reporting Services Part 1
原文:[翻译]初识SQL Server 2005 Reporting Services Part 1 构建和部署基本报表 如果曾经存在一项工作使得“真正的”开发者给他的上司泡蘑菇,那就是构建报表.毕竟 ...
- 致初学者(一): HDU 2000~ 2013题解
对于开始学习C语言程序设计或C++程序设计面向过程部分的同学来说,利用在线OJ网站进行实践训练,对提高自己的编程能力很有好处.国内外OJ网站很多,每个都去看看,去刷个题,是不现实的,也没必要.即使一个 ...
- HDU 1234 (浙大计算机研究生复试上机考试-2005年) 开门人和关门人 (水)
开门人和关门人 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- hdu 2732 Leapin' Lizards(最大流)Mid-Central USA 2005
废话: 这道题不难,稍微构造一下图就可以套最大流的模板了.但是我还是花了好久才解决.一方面是最近确实非常没状态(托词,其实就是最近特别颓废,整天玩游戏看小说,没法静下心来学习),另一方面是不够细心,输 ...
随机推荐
- 【Java例题】1.4圆类
4.定义一个圆类,包括半径.构造方法.计算周长方法, 计算面积方法和显示半径方法. 然后编写一个主类,在其主方法中通过定义一个圆对象来 显示圆的半径.周长和面积. package study; imp ...
- SVG和canvas渲染的性能比较
1.什么是SVG? 描述: 一种使用XML描述的2D图形的语言 SVG基于XML意味着,SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器. 在 SVG 中,每个被 ...
- 暴风雨中的 online :.net core 版博客站点遭遇的高并发问题进展
今天暴风雨袭击了杭州,而昨天暴风雨(高并发问题)席卷了园子,留下一片狼藉. 在前天傍晚,我们进行了 .net core 版博客站点的第二次发布尝试,在发布后通过 kestrel 直接监听取代 ngin ...
- Netty学习(七)-Netty编解码技术以及ProtoBuf和Thrift的介绍
在前几节我们学习过处理粘包和拆包的问题,用到了Netty提供的几个解码器对不同情况的问题进行处理.功能很是强大.我们有没有去想这么强大的功能是如何实现的呢?背后又用到了什么技术?这一节我们就来处理这个 ...
- 【C/C++】随机数的生成
C/C++:rand()函数 rand()函数的头文件:#include<stdlib.h> 该函数产生的随机数随机性差,速度慢,周期小(0-32767) 用法如下所示: #include ...
- HTML/CSS:display:flex 布局教程
网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂 ...
- 2月9日 《Java 8实战》读后感
第一部分 基础知识 第3章 Lambda表达式 使用函数式接口 Predicate Consumer Function 第二部分 函数式数据处理 第4章 引入流 第5章 使用流 第6章 用流收集数据 ...
- Spring 集成Kafka(完整版)
前面的文章我们已经完成了Kafka基于Zookeeper的集群的搭建了.Kafka集群搭建请点我.记过几天的研究已经实现Spring的集成了.本文重点 jar包准备 集成是基于spring-integ ...
- 用代码说话:synchronized关键字和多线程访问同步方法的7种情况
synchronized关键字在多线程并发编程中一直是元老级角色的存在,是学习并发编程中必须面对的坎,也是走向Java高级开发的必经之路. 一.synchronized性质 synchronized是 ...
- Mybatis框架(9)---Mybatis自定义插件生成雪花ID做为表主键项目
Mybatis自定义插件生成雪花ID做为主键项目 先附上项目项目GitHub地址 spring-boot-mybatis-interceptor 有关Mybatis雪花ID主键插件前面写了两篇博客作为 ...