题目大意:
输入年、月、日、星期、小时、分钟、秒,以及所处的时区,要求将其转换成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 #include2 #include 3 #include 4 #include 5 #include 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 < 0101 {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-based121 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 before136 }137 138 void backwardDate(int& year, char* month, int& dayOfMonth, char* dayOfWeek)139 {140 int monthId = getMonthId(month); //0-based141 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 monthId154 }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] = '\0'; //erase the comma174 year = (strlen(yearStr) == 4 ? atoi(yearStr) : 1900 + atoi(yearStr));175 176 offset = getOffset(timeZone);177 int advanceClockResult = advanceClock(hour, minute, offset);178 179 if (advanceClockResult >= 1)180 forwardDate(year, month, dayOfMonth, dayOfWeek, advanceClockResult);181 else if (advanceClockResult == -1)182 backwardDate(year, month, dayOfMonth, dayOfWeek);183 184 printf("%s, %02d %s %04d %02d:%02d:%02d +0300",185 dayOfWeek, dayOfMonth, month, year, hour, minute, second);186 187 return true;188 }189 190 int main()191 {192 for (int i = 0; solve(); i++)193 {194 if (i > 0)195 putchar('\n');196 }197 return 0;198 }