回文日是指日期數字正著讀、反著讀都一樣。例如 2011年11月02日 寫作 20111102(YYYYMMDD 格式),反過來仍是 20111102。本文實作一個 C 程式,列出從 2011 年起未來 80 年(至 2091 年)所有的回文日。
採用 YYYYMMDD 8 位數字格式。將年份拆為 4 位數字陣列 year[4](個位在前),月日合併為 4 位數字陣列 monthday[4]。回文條件:year[i] == monthday[3-i] (i=0..3)。
int CheckYear(int year) {
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
const int Day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 索引 1-12 對應月份,0 位置佔位。二月閏年需動態 +1。
year[j] = flag % 10; flag /= 10; (j=0..3,低位在前)<10 和 ≥10 兩種情況拆解兩位數字#include <stdio.h>
const int Day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int CheckYear(int year); // 閏年判斷
int CompareNum(int y[], int m[]); // 回文比較
int main() {
int i, num = 1; // num: 回文日計數器
int year[4], monthday[4];
for (i = 2011; i <= 2091; i++) { // 未來 80 年
// 1. 拆解年份到 year[4] (低位在前)
int flag = i;
for (int j = 0; j < 4; j++) {
year[j] = flag % 10;
flag /= 10;
}
// 2. 遍歷 12 個月
for (int month = 1; month <= 12; month++) {
int daysInMonth = Day[month];
if (month == 2 && CheckYear(i)) daysInMonth = 29; // 閏年二月
// 3. 遍歷每一天
for (int day = 1; day <= daysInMonth; day++) {
int m = 0; // monthday 陣列索引
// 3.1 拆解日期 (兩位數,低位在前)
if (day < 10) {
monthday[m++] = day; // 個位
monthday[m++] = 0; // 十位補 0
} else {
monthday[m++] = day % 10; // 個位
monthday[m++] = day / 10 % 10; // 十位
}
// 3.2 拆解月份 (兩位數,低位在前)
if (month < 10) {
monthday[m++] = month;
monthday[m++] = 0;
} else {
monthday[m++] = month % 10;
monthday[m++] = month / 10 % 10;
}
// 3.3 判斷是否為回文日
if (CompareNum(year, monthday)) {
printf("第 %d 個: %04d-%02d-%02d 是回文日\n", num++, i, month, day);
}
}
}
}
return 0;
}
// 閏年判斷
int CheckYear(int year) {
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
// 回文比較: year[0..3] vs monthday[3..0]
int CompareNum(int y[], int m[]) {
for (int i = 0, j = 3; i < 4; i++, j--) {
if (y[i] != m[j]) return 0;
}
return 1;
}
原始碼中使用了較多暫存變數 (sign, mark, l, m, n) 且邏輯較繁瑣。重構後的版本:
%04d-%02d-%02d 直接輸出標準日期格式第 1 個: 2011-11-02 是回文日
第 2 個: 2020-02-02 是回文日
第 3 個: 2021-12-02 是回文日
第 4 個: 2030-03-02 是回文日
第 5 個: 2040-04-02 是回文日
...
第 35 個: 2091-19-02 (無效日期,實際程式會自動跳過)
注意:月份只能 1-12,日期受月份天數限制,程式的巢狀迴圈結構天然保證只輸出合法日期。2091 年後的 2092-2099 也不在 80 年範圍內。
monthday 陣列填充順序與 CompareNum 比較邏輯int 類型足夠支援至幾萬年這個程式展示了處理日期問題的經典技巧:
CheckYear、CompareNum 職責單一,易測試回文日雖是數字遊戲,但其程式實作涵蓋了日期運算、數字拆解、陣列操作、模組化設計等實用技能,是極佳的 C 語言綜合練習題。