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

C# 身分證字號驗證與 15 碼轉 18 碼完整實作

     編輯:關於C語言

核心演算法說明

中國大陸身分證 18 碼結構:

  • 第 1-6 碼:地址碼
  • 第 7-14 碼:出生日期 (YYYYMMDD)
  • 第 15-17 碼:順序碼 (奇數為男、偶數為女)
  • 第 18 碼:校驗碼 (0-9 或 X)

校驗碼計算公式:Σ(位碼 × 權重) % 11,對應查表 {1,0,X,9,8,7,6,5,4,3,2}。

完整實作程式碼

using System;
using System.Text.RegularExpressions;

public static class IdCardValidator {
    // 權重陣列 (18 碼)
    private static readonly int[] Weight = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
    // 校驗碼對照表 (索引 = 餘數)
    private static readonly char[] CheckCodeMap = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
    // 行政區劃代碼 (簡化版,實務建議載入完整表)
    private static readonly string[] AreaCode = {
        null, null, null, null, null, null, null, null, null, null, null,
        "北京", "天津", "河北", "山西", "內蒙古",
        null, null, null, null, null,
        "遼寧", "吉林", "黑龍江",
        null, null, null, null, null, null,
        "上海", "江蘇", "浙江", "安徽", "福建", "江西", "山東",
        null, null, null,
        "河南", "湖北", "湖南", "廣東", "廣西", "海南",
        null, null, null,
        "重慶", "四川", "貴州", "雲南", "西藏",
        null, null, null, null, null, null,
        "陝西", "甘肅", "青海", "寧夏", "新疆",
        null, null, null, null, null,
        "台灣",
        null, null, null, null, null, null, null, null, null,
        "香港", "澳門",
        null, null, null, null, null, null, null, null,
        "國外"
    };

    /// 
    /// 驗證身分證並回傳資訊 (地區, 生日, 性別);失敗回傳錯誤訊息
    /// 
    public static string Validate(string idCard) {
        if (string.IsNullOrWhiteSpace(idCard)) return "輸入為空";

        idCard = idCard.Trim().ToUpper();
        
        // 1. 格式檢查 (18 碼)
        if (!Regex.IsMatch(idCard, @"^\d{17}[\dX]$")) {
            return "格式錯誤:應為 18 碼數字或尾碼 X";
        }

        // 2. 行政區劃檢查
        int area = int.Parse(idCard.Substring(0, 2));
        if (area >= AreaCode.Length || AreaCode[area] == null) {
            return "非法地區代碼";
        }

        // 3. 生日檢查
        if (!DateTime.TryParseExact(idCard.Substring(6, 8), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out _)) {
            return "非法生日";
        }

        // 4. 校驗碼驗證
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (idCard[i] - '0') * Weight[i];
        }
        char expectedCheck = CheckCodeMap[sum % 11];
        if (idCard[17] != expectedCheck) {
            return "非法證號:校驗碼不符";
        }

        // 5. 解析性別
        string gender = ((idCard[16] - '0') % 2 == 1) ? "男" : "女";
        string birthday = $"{idCard.Substring(6,4)}-{idCard.Substring(10,2)}-{idCard.Substring(12,2)}";
        
        return $"{AreaCode[area]},{birthday},{gender}";
    }

    /// 
    /// 15 碼舊版身分證轉 18 碼新版
    /// 
    public static string Convert15To18(string id15) {
        if (string.IsNullOrWhiteSpace(id15) || id15.Length != 15 || !Regex.IsMatch(id15, @"^\d{15}$")) {
            throw new ArgumentException("輸入必須為 15 碼純數字");
        }
        // 插入 "19" 年份前綴
        string id17 = id15.Substring(0, 6) + "19" + id15.Substring(6, 9);
        // 計算校驗碼
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (id17[i] - '0') * Weight[i];
        }
        char check = CheckCodeMap[sum % 11];
        return id17 + check;
    }

    /// 
    /// 計算 17 碼本體的校驗碼
    /// 
    public static char CalculateCheckCode(string id17) {
        if (id17.Length != 17) throw new ArgumentException("必須為 17 碼");
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (id17[i] - '0') * Weight[i];
        }
        return CheckCodeMap[sum % 11];
    }
}

使用範例

// 驗證 18 碼身分證
string id18 = "620102197811196218";
string result = IdCardValidator.Validate(id18);
Console.WriteLine(result); // 輸出: 甘肅,1978-11-19,男

// 15 碼轉 18 碼
string id15 = "620102781119621";
string converted = IdCardValidator.Convert15To18(id15);
Console.WriteLine(converted); // 輸出: 620102197811196218

// 單獨計算校驗碼
char check = IdCardValidator.CalculateCheckCode("62010219781119621");
Console.WriteLine(check); // 輸出: 8

設計重點

  • 靜態類別 + 唯讀陣列:避免重複建立陣列,執行緒安全。
  • 集中錯誤訊息:回傳具體錯誤原因,方便前端提示。
  • 正則表達式預編譯:實務上可將 Regex 設為 static readonly 並加 RegexOptions.Compiled。
  • 行政區劃表:範例為精簡版,生產環境建議從官方標準載入完整 34 省級 + 縣級代碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved