CCF計算機軟體能力認證試題練習:201712-3 Crontab
Crontab
來源:
標籤:
參考資料:
相似題目:
題目
輸入
輸出
輸入樣例
3 201711170032 201711222352
0 7 * * 1,3-5 get_up
30 23 * * Sat,Sun go_to_bed
15 12,18 * * * have_dinner
輸出樣例
201711170700 get_up
201711171215 have_dinner
201711171815 have_dinner
201711181215 have_dinner
201711181815 have_dinner
201711182330 go_to_bed
201711191215 have_dinner
201711191815 have_dinner
201711192330 go_to_bed
201711200700 get_up
201711201215 have_dinner
201711201815 have_dinner
201711211215 have_dinner
201711211815 have_dinner
201711220700 get_up
201711221215 have_dinner
201711221815 have_dinner
樣例說明
提示
解題思路
說幾個易錯點吧。1.需要判斷日期的合法性(某一天是否真實存在,需要結合某年某月的天數具體判斷,同時需要判斷這一天是星期幾)。2.排序操作:時間值小的先輸出;時間值相等的,按輸入順序輸出;時間值和名稱都相等的,應只輸出一個。3.包括開始時間,不包括結束時間。4.月份和星期幾可以字母表示,忽略大小寫。5.其它,請認真審題。
參考程式碼
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<algorithm>
#include<set>
using namespace std;
const char *month="janfebmaraprmayjunjulaugsepoctnovdec";
const char *weekday="sunmontuewedthufrisat";
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
struct Command{
int no; //編號
long long time; //時間
char name[105]; //名稱
bool operator < (const Command& rhs) const{
if(time==rhs.time) return no<rhs.no;
return time<rhs.time;
}
bool operator == (const Command& rhs) const{
return strcmp(name,rhs.name)==0 && time==rhs.time;
}
}command[10005];
int tot;//對執行命令計數
int n; //輸入命令個數
long long startTime,finishTime; //開始時間和結束時間
char input[6][105]; //每條命令含有6個引數,type依次是【Minutes】【Hours】【day of month】【month】【day of week】【name】
set<int> timeRange[5];//時間值範圍集合,type依次是【Minutes】【Hours】【day of month】【month】【day of week】
set<int>::iterator M,H,dm,m;//對應上一行的前4個迭代器
void getTimeRange(int type, char *str);//對input[type]獲取時間值範圍
int addTimeRange(int type, int start, int finish);//對timeRange[type]增加時間值範圍
void addCommand();//對獲取到的時間值範圍新增命令
//工具類函式
int getValue(int &i, char *str);//從str[i]起得到一個時間值
long long getToday(int y,int m,int d);//計算今天的日期
int getDayofWeek(int y,int m,int d);//計算今天是星期幾
int main(){
scanf("%d%lld%lld",&n,&startTime,&finishTime);
for(int i=0;i<n;i++){
for(int j=0;j<5;j++) timeRange[j].clear();
for(int j=0;j<6;j++){//讀入每條命令的6個引數,並對前5個引數處理
scanf("%s",input[j]);
if(j!=5) getTimeRange(j,input[j]);
}
addCommand();
}
sort(command,command+tot);
tot=unique(command,command+tot)-command;//忽略重複的
for(int i=0;i<tot;i++) printf("%lld %s\n",command[i].time,command[i].name);
return 0;
}
void getTimeRange(int type, char *str){
int start,finish;
//處理星號表示的時間值範圍
if(str[0]=='*'){
if(type==0) start=0, finish=59;
else if(type==1) start=0, finish=23;
else if(type==2) start=1, finish=31;
else if(type==3) start=1, finish=12;
else if(type==4) start=0, finish=6;
addTimeRange(type,start,finish);
return;
}
//處理橫槓和逗號表示的時間值範圍
int i=0;
int len=strlen(str);
while(i<len){
start=getValue(i,str);//獲取一個值,如果後接'-',繼續獲取下一個值
if(str[i]=='-') finish=getValue(++i,str);
else finish=start;
addTimeRange(type,start,finish);
}
}
void addCommand(){
long long today,time;
int dayofWeek;
int y1=startTime/1e8, y2=finishTime/1e8;
int startDay=startTime/1e4;
for(int y=y1;y<=y2;y++)//year
for(m=timeRange[3].begin();m!=timeRange[3].end();m++)//month
for(dm=timeRange[2].begin();dm!=timeRange[2].end();dm++){//day of month
today=getToday(y,*m,*dm);//得到今天的日期
if(today>=startDay && timeRange[4].count(getDayofWeek(y,*m,*dm))){//今天是星期幾,是否在day of week中
for(H=timeRange[1].begin();H!=timeRange[1].end();H++)//Hours
for(M=timeRange[0].begin();M!=timeRange[0].end();M++){//Minutes
time=today*1e4+(*H)*1e2+(*M);
if(time>=startTime && time<finishTime){
strcpy(command[tot].name,input[5]);
command[tot].time=time;
command[tot].no=tot;
tot++;
}
else if(time>=finishTime) return;
}
}
}
}
int getValue(int &i, char *str){
char value[105];int cnt=0;
int len=strlen(str);
while(i<len){
//如果是數值
if(isdigit(str[i])){
while(i<len && isdigit(str[i])){
value[cnt++]=str[i++];
}
value[cnt]='\0';
return atoi(value);
}
//如果是字母
else if(isalpha(str[i])){
while(i<len && isalpha(str[i])){
value[cnt++]=tolower(str[i++]);
}
value[cnt]='\0';
char *p=strstr(month,value);
if(p) return (p-month)/3+1;
else if(p=strstr(weekday,value)) return (p-weekday)/3;
}
else i++;
}
return -1;
}
int addTimeRange(int type,int start,int finish){
for(int i=start;i<=finish;i++){
timeRange[type].insert(i);
}
}
long long getToday(int y,int m,int d){
if(y%4==0 && y%100!=0 || y%400==0) days[1]=29;
else days[1]=28;
if(d>days[m-1]) return -1;
return y*1e4+m*1e2+d;
}
int getDayofWeek(int y,int m,int d){
if(m==1||m==2){
m+=12;
y--;
}
return (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
}