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

C 語言實現 15 位身份證升級為 18 位(含校驗碼計算)

     編輯:關於C語言

背景與規則

中國大陸身份證號從 15 位升級為 18 位,核心變化:

  1. 出生年份從 2 位擴展為 4 位(前綴 19 或 20,歷史數據多為 19)。
  2. 第 18 位為校驗碼,依 ISO 7064:1983.MOD 11-2 算法計算,可能為數字或 X(代表 10)。

核心算法步驟

  1. 前 6 位(地址碼)保持不變。
  2. 插入 19 作為出生年份前兩位。
  3. 接原 15 位的第 7~15 位(出生月日、順序碼),共 9 位,湊成 17 位本體碼。
  4. 加權求和:S = Σ(本體碼[i] × 權重[i]),i=0..16。權重陣列固定:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}。
  5. 計算 mod = S % 11。
  6. 查表得校驗碼:{'1','0','X','9','8','7','6','5','4','3','2'},索引為 mod。
  7. 拼接第 18 位,完成 18 位身份證號。

完整 C 實現(含邊界檢查)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int id15_to_18(char *cert_no) {
    if (!cert_no || strlen(cert_no) != 15) return -1;  // 輸入校驗

    static const int weight[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
    static const char check_code[11] = {'1','0','X','9','8','7','6','5','4','3','2'};

    char id18[19] = {0};
    // 1. 拼接前 17 位
    strncpy(id18, cert_no, 6);      // 地址碼
    strcat(id18, "19");             // 年份前綴
    strncat(id18, cert_no + 6, 9);  // 月日順序碼

    // 2. 加權求和
    int sum = 0;
    for (int i = 0; i < 17; i++) {
        if (id18[i] < '0' || id18[i] > '9') return -2;  // 非數字字符
        sum += (id18[i] - '0') * weight[i];
    }

    // 3. 校驗碼
    id18[17] = check_code[sum % 11];
    id18[18] = '\0';

    // 4. 回寫
    strcpy(cert_no, id18);
    return 0;
}

int main() {
    char id[20] = "320521720807225";  // 15 位測試樣本
    printf("原始: %s\n", id);
    if (id15_to_18(id) == 0) {
        printf("升級: %s\n", id);  // 預期: 320521197208072253
    } else {
        printf("轉換失敗\n");
    }
    return 0;
}

關鍵點說明

  • 緩衝區大小:輸入輸出同一緩衝區需 ≥ 19 字節(18 位 + \0)。
  • 輸入驗證:檢查長度、字符合法性,避免緩衝區溢出與運算錯誤。
  • 年份前綴:歷史數據統一用 19;若涉及 2000 年後出生者,需額外邏輯判斷(如第 7、8 位月份 > 12 則可能為 20xx,但 15 位身份證最晚發放至 1999 年,通常固定 19 即可)。
  • 校驗碼 X:輸出為大寫字母 X,非小寫 x。

擴展:反向驗證 18 位身份證合法性

bool validate_id18(const char *id) {
    if (!id || strlen(id) != 18) return false;
    int sum = 0;
    for (int i = 0; i < 17; i++) {
        if (id[i] < '0' || id[i] > '9') return false;
        sum += (id[i] - '0') * weight[i];
    }
    char expected = check_code[sum % 11];
    char actual = id[17];
    return (expected == actual) || (expected == 'X' && actual == 'x');  // 兼容小寫 x
}

此實現簡潔、標準、無依賴,適合嵌入式、舊系統改造、數據清洗等場景直接嵌入使用。

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