原题链接
Crontab原题链接
解题思路
题目意思就是输出每一时刻能被执行的命令
那么如果时间允许的话,可以直接把时间枚举一遍,每个时间判断一下该任务能否执行即可
其实时间1970010100,结束时间209912312359
算下来是六千万多分钟,10s时间足够,因此暴力枚举
写一个时钟结构体,模拟时间的递增,并且能将时间进行格式化输出
写一个任务结构体,存储该任务能执行的时间,当minute,hour, day, month, week都满足时,将时间和命令输出
解题技巧
时间结构体的写法应记住,可以看作是一个模板
掌握如何快速将多个int合并成一个字符串(sprintf)
如何将字符串分割存储在多个int中(sscanf)
判断时间点是否可执行时,可以采用结构体加时间数组的存储格式
代码实现
#include
#include
#include
#include
using namespace std;
int months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
struct Timer
{
int minute, hour, dayofmonth, month, dayofweek, year;
//构造函数要同名
Timer(string t)
{//能自动去除前缀零,将字符串内容写入数字中
sscanf(t.c_str(), "%04d%02d%02d%02d%02d", &year, &month, &dayofmonth, &hour, &minute);
}
int is_leap()
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100)) return 1;
else return 0;
}
int getdays()
{
if (month == 2) return months[2] + is_leap();
else return months[month];
}
void next()
{
if ( ++ minute == 60)
{
minute = 0;
if ( ++ hour == 24)
{
hour = 0;
dayofweek = (dayofweek + 1) % 7; //位置不要写错
if ( ++ dayofmonth > getdays())
{
dayofmonth = 1;
if ( ++ month == 13)
{
month = 1;
year ++;
}
}
}
}
}
//重载小于符号,是指自己小于对方,不要写反
bool operator< (const Timer & t)const
{
if (t.year != year) return year < t.year;
if (t.month != month) return month < t.month;
if (t.dayofmonth != dayofmonth) return dayofmonth < t.dayofmonth;
if (t.hour != hour) return hour < t.hour;
return minute < t.minute;
}
string to_string()
{
char str[20];
//把一串整数打印到字符串中,而不是显示在终端屏幕上,所以需要返回字符串
sprintf(str, "%04d%02d%02d%02d%02d", year, month, dayofmonth, hour, minute);
return str;
}
};
struct Text
{
//判断某刻时间能否做某事,时间允许遍历时,可以采用这样的数组存法
bool minute[60], hour[24], dayofmonth[32], month[13], dayofweek[7];
string command;
bool check(Timer & t)
{
return minute[t.minute] && hour[t.hour] && dayofmonth[t.dayofmonth] &&
month[t.month] && dayofweek[t.dayofweek];
}
}text[20];
unordered_map <string, int> book;
void Init()
{
string a[19] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug",
"sep", "oct", "nov", "dec", "mon", "tue", "wed", "thu", "fri", "sat", "sun"};
int b[19] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 0};
for (int i = 0; i < 19; i ++)
{
book[a[i]] = b[i];
}
}
int getnum(string str)
{
if (str[0] >= '0' && str[0] <= '9') return stoi(str);
else
{
//转换大小写的方法要记住掌握
transform(str.begin(), str.end(), str.begin(), ::tolower);
return book[str];
}
}
void work(string str, bool st[], int len)
{
if (str == "*")
{
for (int i = 0; i < len; i ++) st[i] = true;
return ;
}
for (int i = 0; i < str.size(); i ++)
{
int j = str.find(',', i);
if (j == -1) j = str.size();
string tmp = str.substr(i, j - i);
int k = tmp.find('-');
if (k == -1)
{
st[getnum(tmp)] = true;
}
else
{
int l = getnum(tmp.substr(0, k));
int r = getnum(tmp.substr(k + 1));
for (int u = l; u <= r; u ++) st[u] = true;
}
i = j;
}
}
int main()
{
Init();
int n;
string s, t;
cin >> n;
cin >> s >> t;
for (int i = 0; i < n; i ++)
{
string minute, hour, dayofmonth, month, dayofweek, command;
cin >> minute >> hour >> dayofmonth >> month >> dayofweek >> command;
//传数组名,相当于传首地址了吗,竟然可以直接用函数修改数组
work(minute, text[i].minute, 60);
work(hour, text[i].hour, 24);
work(dayofmonth, text[i].dayofmonth, 32);
work(month, text[i].month, 13);
work(dayofweek, text[i].dayofweek, 7);
text[i].command = command;
}
Timer cur("197001010000"), start(s), end(t);
cur.dayofweek = 4;
while (cur < end)
{
//不能使用大于等于,因为之重载了小于号
if (!(cur < start))
{
for (int i = 0; i < n; i ++)
{
if (text[i].check(cur))
{
cout << cur.to_string() << " " << text[i].command << endl;
}
}
}
cur.next();
}
return 0;
}