首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言尋找回文日:從 2011-11-02 開始未來 80 年有哪些?

     編輯:關於C語言

什麼是回文日?

回文日是指日期數字正著讀、反著讀都一樣。例如 2011年11月02日 寫作 20111102(YYYYMMDD 格式),反過來仍是 20111102。本文實作一個 C 程式,列出從 2011 年起未來 80 年(至 2091 年)所有的回文日。

核心演算法設計

1. 日期表示與回文判斷

採用 YYYYMMDD 8 位數字格式。將年份拆為 4 位數字陣列 year[4](個位在前),月日合併為 4 位數字陣列 monthday[4]。回文條件:year[i] == monthday[3-i] (i=0..3)。

2. 閏年判斷

int CheckYear(int year) {
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

3. 月份天數表

const int Day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 索引 1-12 對應月份,0 位置佔位。二月閏年需動態 +1。

4. 數字拆解技巧

  • 年份:year[j] = flag % 10; flag /= 10; (j=0..3,低位在前)
  • 月份 (1-12):分 <10 和 ≥10 兩種情況拆解兩位數字
  • 日期 (1-31):同理拆解,注意閏年二月 29 日

完整 C 程式碼

#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 年範圍內。

擴展應用

  1. 不同日期格式:若改為 DDMMYYYY 或 MMDDYYYY,只需調整 monthday 陣列填充順序與 CompareNum 比較邏輯
  2. 更大時間範圍:將年份迴圈上限改大,注意 int 類型足夠支援至幾萬年
  3. 效能優化:可預先生成所有回文數字串,再驗證是否為合法日期,減少無效日期的檢查

總結

這個程式展示了處理日期問題的經典技巧:

  • 用陣列儲存各位數字,轉換為「字串比較」問題
  • 閏年判斷與月份天數表的標準處理
  • 巢狀迴圈遍歷年/月/日,邊界條件清晰
  • 模組化設計:CheckYear、CompareNum 職責單一,易測試

回文日雖是數字遊戲,但其程式實作涵蓋了日期運算、數字拆解、陣列操作、模組化設計等實用技能,是極佳的 C 語言綜合練習題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved