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

原文地址:https://www.cnblogs.com/cs-whut/p/11511301.html

时间: 2024-10-30 01:38:32

从“HDU 2005 第几天?”谈起的相关文章

(hdu 简单题 128题)hdu 2005 第几天(计算当天是该年的第几天)

题目: 第几天? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 89641    Accepted Submission(s): 33727 Problem Description 给定一个日期,输出这个日期是该年的第几天. Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,

hdu 2005 第几天?

第几天? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 96248    Accepted Submission(s): 36189 Problem Description 给定一个日期,输出这个日期是该年的第几天. Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,另外,

HDU 2005 第几天?

第几天? Problem Description 给定一个日期,输出这个日期是该年的第几天. Input 输入数据有多组,每组占一行,数据格式为YYYY/MM/DD组成,具体参见sample input ,另外,可以向你确保所有的输入数据是合法的. Output 对于每组输入数据,输出一行,表示该日期是该年的第几天. Sample Input 1985/1/20 2006/3/12 Sample Output 20 71 代码: 1 #include<cstdio> 2 using names

hdu 2005 第几天?(java)

问题: java输入真是太麻烦了,求大神指点!!! 此处可以用作一个格式化输入: Scanner cin=new Scanner(System.in); int y,m,d; String s; String yy,mm,dd; while(cin.hasNext()){ yy=mm=dd=""; s=cin.next(); char[] ss=s.toCharArray(); int j = 0; for(int i=0;i<ss.length;i++) { if(ss[i]=

[翻译]初识SQL Server 2005 Reporting Services Part 1

原文:[翻译]初识SQL Server 2005 Reporting Services Part 1 构建和部署基本报表 如果曾经存在一项工作使得“真正的”开发者给他的上司泡蘑菇,那就是构建报表.毕竟那并不是真正的开发,更像是制作美化的格式.而且你所使用的构建报表的工具试图提供一个抽象层,这个经常妨碍你对报表的真正掌控.我以前经常听到这些争论.如果这听上去像你曾经在一个水制冷器旁边的对话,那么我请你仔细关注一下SQL Server 2005 Reporting Services(SSRS). S

hdu2005~2009

hdu 2005 给定一个日期,输出这个日期是该年的第几天. 水……可能主要是分类讨论烦一点吧 1 #include<stdio.h> 2 int main() 3 { 4 int year,month,day,d=0,i; 5 int m[12]={31,28,31,30,31,30,31,31,30,31,30,31}; 6 while (scanf("%d/%d/%d",&year,&month,&day)!=EOF) 7 { 8 for (i

第8章 云计算

8.1云计算是物联网发展的基石 8.1.1云计算是物联网的基石   2011年1月18日,“打造中国云—云计算促进产业转型升级” 研讨会在南京雨花软件园管委会多功能厅举行.中国工程院院士李德毅,南京市副市长.雨花台区委书记李侃桢,南京邮电大学副校长朱洪波,雨花台区副区长薛国安,以及来自赛迪集团.微软中国.中兴通讯.区科技局.区商务局.雨花软件园等企事业单位的领导.专家六十余人参加了本次会议,就云计算产业发展及促进产 业转型升级展开了研讨. 在研讨会上中国工程院院士李德毅的演讲将大家带入了云计算的

hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩)

/* hdu 4842(NOIP 2005 过河)之 动态规划(距离压缩) dp[i] := 到桥上的i位置,最少需要踩到的石子数. dp[i] = min(dp[i], dp[i-j] + isStone[i])    条件: (1) S<=j<=T (2) dp[i-j]是青蛙可以到达的点 独木桥长度L,最大为10^9,直接用转移方程,TLE:由于桥上的石子个数100,所以当石子分布在独木桥上时,是很稀疏的. (1)S!=T 考虑,对于此题关键在于求踩到的石子数,而非跳的次数,对于两个相邻

hdu 2732 Leapin&#39; Lizards(最大流)Mid-Central USA 2005

废话: 这道题不难,稍微构造一下图就可以套最大流的模板了.但是我还是花了好久才解决.一方面是最近确实非常没状态(托词,其实就是最近特别颓废,整天玩游戏看小说,没法静下心来学习),另一方面是不够细心,输出格式错了大意没有发现死一只和死多只之间的区别,卡在那里动不了. 题意: 在一张n*m的地图中,有一群蜥蜴,这群蜥蜴每次可以跳跃曼哈顿距离d(曼哈顿距离——dis(a, b) = |ax-bx|+|ay-by|,之后所有的距离都是曼哈顿距离),这些蜥蜴只能在地图上的一些柱子上跳跃.柱子i最多可以支持