日期问题:大小月,平闰年
2017-7-日期问题
若干混乱的历史文献,日期在1960年1月1日至2059年12月31日
日期采用的格式非常不统一 :年/月/日 月/日/年 日/月/年
年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输入
----
一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)
输入
----
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。
样例输入
----
02/03/04
样例输出
----
2002-03-04
2004-02-03
2004-03-02
1.常规日期运算大小月(30天/31天),平年/闰年,
2.细心
3.字符串处理
思路:逻辑上不复杂,但是要注意细节
1 把输入的字符串切割为三个整数(年月日)
2.日、月合法性检验(大小月,平闰年),不合法返回空字符串
3.月,日如果少零,则补全 ( 首先把整数化为字符串 i2s(),用字符串的长度判断是否少0 )
4.用集合 set<string> 对三种 case( 年/月/日,日/月/年,月/日/年 )进行排序和去掉重复
代码
#include<cstdio>
#include<iostream>
#include<sstream>
#include<set>
using namespace std;
bool isLeapYear(int year)
{
if(year%4==0&&year%100!=0 || year%400==0) return true;
else return false;
}
void i2s(int i, string &s) //&s 传引用
{
stringstream ss;
ss<<i;
ss>>s;
}
string f(int a, int b, int c) //a年 b月 c日
{
//剔除不合法年月日,return ""
if(a>=60 && a<=99) a+=1900;
if(a>=0 && a<=59) a+=2000;
if(b<1 || b>12) return "";
if(c<1 || c>31) return "";
switch(b){
case 2 :
if(isLeapYear(a) && c>29) return "";
if(!isLeapYear(a) && c>28) return "";
break;
case 4 :
if(c>30) return "";
break;
case 6 :
if(c>30) return "";
break;
case 9 :
if(c>30) return "";
break;
case 11 :
if(c>30) return "";
break;
default :
break;
}
//月,日如果少零,则补全(首先把整数化为字符串,用字符串的长度判断是否少0)
string _a, _b, _c;
i2s(a, _a);
i2s(b, _b);
i2s(c, _c);
if(_b.length()==1) _b = "0" + _b;
if(_c.length()==1) _c = "0" + _c;
return _a+"-"+_b+"-"+_c;
}
int main(int argc, const char *argv[])
{
// 输入的字符串切割为三个整数(年月日)
string in;
cin>>in;
int a=0, b=0, c=0;
a = (in[0]-'0')*10 + (in[1]-'0');
b = (in[3]-'0')*10 + (in[4]-'0');
c = (in[6]-'0')*10 + (in[7]-'0');
string case1 = f(a, b, c);
string case2 = f(c, a, b);
string case3 = f(c, b, a);
//对元素排序(日期从小到大),去重——set
set<string> ans;
if(case1!="") ans.insert(case1);
if(case2!="") ans.insert(case2);
if(case3!="") ans.insert(case3);
for(set<string>::iterator iter = ans.begin(); iter != ans.end(); iter++)
{
cout<<*iter<<endl;//* 指针
}
}
(1)字符串处理
1) string in;
cin>>in;
int a = (in[0]-'0')*10 + (in[1]-'0');
2) if(_b.length()==1) _b = "0" + _b;
3)
void i2s(int i, string &s) //&s 传引用
{
stringstream ss; //#include<sstream>
ss<<i;
ss>>s;
}
(2) 集合set
set<string> ans; //#include<set>
//在集合中插入元素
if(case1!="") ans.insert(case1);
if(case2!="") ans.insert(case2);
if(case3!="") ans.insert(case3);
//用迭代器遍历
for(set<string>::iterator iter = ans.begin(); iter != ans.end(); iter++)
{
cout<<*iter<<endl;//* 指针
}
2013-1-高斯日记
枚举法模拟翻日历 (这个题可以用excel做)
记日记不注明年月日,而是用一个整数代替,比如:4210
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113 请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
#include<cstdio>
#include<iostream>
using namespace std;
bool isLeapYear(int year)
{
return (( year%4==0 && year%100!=0 )|| year%400==0 );
}
int main(int argc, const char *argv[])
{
int y = 1777;
int m = 4;
int d = 30;
for(int i=1; i<8113 ;i++)
{
d++;
if( d>31 && ( m==1 || m==3 || m==5 || m==7 || m==8 || m==10 ) )
{
m++;
d = 1;
}
if( d>30 && ( m==4 || m==6 || m==9 || m==11 ) )
{
m++;
d = 1;
}
if( isLeapYear(y) && m==2 && d>29 )
{
m++;
d = 1;
}
if( !isLeapYear(y) && m==2 && d>28 )
{
m++;
d = 1;
}
if( d>31 && m==12 )
{
y++;
m = 1;
d = 1;
}
//cout<<y<<" "<<m<<" "<<d<<" "<<endl;
}
cout<<y<<" "<<m<<" "<<d<<" "<<endl;
}
//1799 7 16