日期问题
分析
格式化输入输出
用scanf读入
使用scanf("%d/%d/%d", &a, &b, &c); 在02/03/03这样的输入中提取到02
03 04这几个值
scanf("%04d%02d%02d", &year, &month, &day); 将8位数自动处理到年月日
用printf输出
printf("%d-%02d-%02d\n", year, month, day); 可以将9月输出为09 原理是输出占两位
不足用0填补
sprintf(s,"%04d%02d%02d",y,m,d); 将年月日读入到字符串里面去 直接可以对字符串进行处理
筛日期
一个很常用的技巧 要什么日期 首先先把这段时间的合法的日期全都找出来 然后再对他们进行操作 类似于筛素数 先筛再操作
筛选也很简单 将日期用八位数表示 从起始到结束循环就行了 不用考虑多少进位的问题 多枚举那点不算什么
for (int date = Start; date <= End; date ++ ){
int year = date / 10000, month = date % 10000 / 100, day = date % 100;
if (check_valid(year, month, day))
……
}
}
如何判断是否是合法日期呢
首先年份没什么可看的 基本没什么限制
月份要是0~12
天数就比较复杂 用一个数组记录每个月应该有的天数
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
然后首先就是要在0~31的范围内
其次就是与某月应该有的天数进行比较 这里二月比较特殊 还要另外判断一个闰年
四年一闰:年份是4的倍数是闰年;
百年不闰:是100的倍数不是闰年;
四百年又闰:是400的倍数却又是闰年。
if(year % 100 && year % 4 <mark> 0 || year % 400 </mark> 0)
bool check_date(int year, int month, int day){
if (month == 0 || month > 12)
return false;
if (day == 0 || day > 31)
return false;
int curdays=days[month];
if(month==2)
if(year % 100 && year % 4 <mark> 0 || year % 400 </mark> 0)
curdays+=1;
if(day>curdays)
return false;
return true;
}
这种方式 泛用性也更强了
#include<bits/stdc++.h>
using namespace std;
int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check_date(int year,int month,int day){
if(month==0 || month>12)
return false;
if(day==0 || day>31)
return false;
int curdays=days[month];
if(month==2)
if(year%100 && year%4==0 && year%400==0)
curdays++;
if(day>curdays)
return false;
return true;
}
int main()
{
int one,two,three;
scanf("%d/%d/%d",&one,&two,&three);
cin>>Start>>End;
for(int date=Start;date<=End;date++){
int year=date/10000; //取前4位(砍掉后4位) / 4个0
int month=date%10000/100;//取后4位 %4个0 取后4位的前2位 再砍去2个0
int day=date%100; //取后2位 直接 %2个0
if(check_date(year,month,day)){
//具体逻辑
//…………
printf("%d-%02d-%02d\n", year, month, day);
}
}
return 0;
}
算相差天数
类似于前缀和的思想
分别计算两个日期距离一个公元1年1月1日的总天数
然后计算这两个天数之间的差值来得到日期差
注意考虑闰年对2月天数的影响
#include<bits/stdc++.h>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 计算从公元1年1月1日到指定日期的总天数
int daysFromStart(int year, int month, int day) {
int totalDays = 0;
// 添加之前年份的天数
for(int y = 1; y < year; y++) {
totalDays += isLeapYear(y) ? 366 : 365;
}
// 添加当前年份的月份天数
for(int m = 1; m < month; m++) {
totalDays += days[m];
if(m == 2 && isLeapYear(year)) {
totalDays++;
}
}
// 添加当前月份的天数
totalDays += day;
return totalDays;
}
int main() {
int startDate, endDate;
while(cin >> startDate >> endDate) {
if(startDate>endDate)
swap(startDate,endDate);
int startYear=startDate/10000,
startMonth=startDate%10000/100,
startDay=startDate%100;
int endYear=endDate/10000,
endMonth=endDate%10000/100,
endDay=endDate%100;
int dateDiff = daysFromStart(endYear,endMonth,endDay)
- daysFromStart(startYear,startMonth,startDay)
+ 1;
cout << dateDiff << endl;
}
return 0;
}
*组合拳
写日期问题 把这几个函数一默写上 后面就基本不成问题了
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool is_leap(int y){
return y%100 && y%4==0 || y%400==0;
}
int get_days(int y,int m){
return days[m]+(m==2 && is_leap(y));
}
void next_day(int &y,int &m,int &d){//注意 传的是引用
d++;
if(d>get_days(y,m)){
d=1;
m++;
if(m>12){
m=1;
y++;
}
}
}
bool check_date(int y, int m, int d) {
if (m < 1 || m > 12)
return false;
if(d < 1 || d > getdays(y,m))
return false;
return true;
}
while ((curYear < 给定年份) ||
(curYear == 给定年份 && curMonth < 给定月份) ||
(curYear == 给定年份 && curMonth == 给定月份 && curDay < 给定日子)) {
// 执行 next_day 操作
}
题目
https://www.acwing.com/blog/content/24163/
💬 评论