题目大意:
输入年、月、日、星期、小时、分钟、秒,以及所处的时区,要求将其转换成UTC+3时区内的时间。
浑身都是坑的模拟题。
①题目没有说是单组还是多组数据(其他OJ上的版本是多组数据),保险起见建议处理到EOF。
②"Year: Set by two or four decimal digits. If a year is set by two decimals it is assumed that this is a number of the year of the XX century."
我查了谷歌翻译才反应过来那个XX是罗马数字20……输入年份时不能直接"%d",得先读成字符串,再判断长度,如果长度为2则在转成整数时需要加上1900。
③"First two digits set the hours and the last two the minutes of offset value."
在求该时区与UTC+3相差的偏移量时,不能简单粗暴地用300减去读入的数。假如输入+0130,那么300-130的结果就是170,该结果显然是错误的。
④"The absolute value of the difference does not exceed 24 hours."
注意-2350这样的极端情形,加的天数有可能是2天!(虽然现实中不存在-2350这样的时区划分,但本题的数据就不好说了)
⑤"Your program should rely on the predefined correctness of the given Day-of-week and Time-zone."
这句话的意思其实是说输入数据保证格式和内容都是正确的,我一开始看到这句还愣了一会儿(没见过这种操作)……
⑥"February, as a rule, has 28 days, save for the case of the leap year (29 days)."
学到了一个新短语:save for(手动笑哭
本题是需要考虑闰年的,闰年的判定法与现实一致:四年一闰,百年不闰,四百年再闰。
⑦"The output string should not include leading and trailing spaces."
注意行末不能有空格。另外输出时一定要注意加前导零。
AC代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <stdexcept> 5 #include <string> 6 7 const char dayOfWeekName[7][4] = { 8 "SUN", 9 "MON", 10 "TUE", 11 "WED", 12 "THU", 13 "FRI", 14 "SAT" 15 }; 16 const char monthName[12][4] = { 17 "JAN", 18 "FEB", 19 "MAR", 20 "APR", 21 "MAY", 22 "JUN", 23 "JUL", 24 "AUG", 25 "SEP", 26 "OCT", 27 "NOV", 28 "DEC" 29 }; 30 const char timeZoneOffsetName[6][4] = { 31 "UT", 32 "GMT", 33 "EDT", 34 "CDT", 35 "MDT", 36 "PDT" 37 }; 38 const int timeZoneOffset[6] = {0, 0, -400, -500, -600, -700}; 39 const int dayNumberOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //non-leap year 40 41 inline bool isLeapYear(int year) 42 { 43 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 44 } 45 46 inline int getMonthId(const char* month) 47 { 48 for (int i = 0; i < 12; i++) 49 if (strcmp(month, monthName[i]) == 0) 50 return i; 51 52 throw std::invalid_argument("invalid month name: " + std::string(month)); 53 } 54 55 inline int getDayOfWeekId(const char* dayOfWeek) 56 { 57 for (int i = 0; i < 7; i++) 58 if (strcmp(dayOfWeek, dayOfWeekName[i]) == 0) 59 return i; 60 61 throw std::invalid_argument("invalid day of week: " + std::string(dayOfWeek)); 62 } 63 64 int getOffset(const char* timeZone) 65 { 66 if (timeZone[0] == '+' || timeZone[0] == '-') //in digit form 67 //return 300 - atoi(timeZone); //WRONG!!! 68 { 69 int tz = atoi(timeZone); //example: +0235 70 if (tz > 0 && tz < 300) 71 tz += 40; //+0235 -> 275 72 return 300 - tz; //+0235 -> 275 -> +0025 73 } 74 else 75 for (int i = 0; i < 6; i++) 76 if (strcmp(timeZone, timeZoneOffsetName[i]) == 0) 77 return 300 - timeZoneOffset[i]; 78 79 throw std::invalid_argument("invalid time zone: " + std::string(timeZone)); 80 } 81 82 int advanceClock(int& hour, int& minute, int offset) 83 { 84 if (offset >= 0) 85 { 86 minute += offset % 100; 87 if (minute >= 60) 88 { 89 minute -= 60; 90 hour += 1; 91 } 92 hour += offset / 100; 93 if (hour >= 24) 94 { 95 int temp = hour / 24; 96 hour %= 24; 97 return temp; 98 } 99 } 100 else //offset < 0 101 { 102 minute -= (-offset % 100); 103 if (minute < 0) 104 { 105 minute += 60; 106 hour -= 1; 107 } 108 hour -= (-offset / 100); 109 if (hour < 0) 110 { 111 hour += 24; 112 return -1; 113 } 114 } 115 return 0; 116 } 117 118 void forwardDate(int& year, char* month, int& dayOfMonth, char* dayOfWeek, int offset) 119 { 120 int monthId = getMonthId(month); //0-based 121 int curDayNumber = dayNumberOfMonth[monthId] + (monthId == 1 && isLeapYear(year)); 122 123 int dayOfWeekId = getDayOfWeekId(dayOfWeek); 124 strcpy(dayOfWeek, dayOfWeekName[(dayOfWeekId + 1) % 7]); 125 126 if ((dayOfMonth += offset) > curDayNumber) 127 { 128 dayOfMonth = 1; 129 if ((monthId += 1) >= 12) 130 { 131 monthId = 0; 132 year += 1; 133 } 134 } 135 strcpy(month, monthName[monthId]); //maybe advanced before 136 } 137 138 void backwardDate(int& year, char* month, int& dayOfMonth, char* dayOfWeek) 139 { 140 int monthId = getMonthId(month); //0-based 141 142 int dayOfWeekId = getDayOfWeekId(dayOfWeek); 143 strcpy(dayOfWeek, dayOfWeekName[(dayOfWeekId + 6) % 7]); 144 145 if ((dayOfMonth -= 1) <= 0) 146 { 147 if ((monthId -= 1) < 0) 148 { 149 monthId = 11; 150 year -= 1; 151 } 152 dayOfMonth = dayNumberOfMonth[monthId] + (monthId == 1 && isLeapYear(year)); 153 //update dayOfMonth before monthId 154 } 155 strcpy(month, monthName[monthId]); 156 } 157 158 bool solve() 159 { 160 char dayOfWeek[5]; 161 char month[4]; 162 char timeZone[8]; 163 char yearStr[5]; 164 int dayOfMonth; 165 int year; 166 int hour, minute, second; 167 int offset; 168 169 if (scanf("%s%d%s%s%d:%d:%d%s", dayOfWeek, &dayOfMonth, month, yearStr, 170 &hour, &minute, &second, timeZone) == EOF) 171 return false; 172 173 dayOfWeek[3] = '