Problem Description
身份证号码共18位,最后一位是校验位。
A[18]:aaaaaabbbbbbbbcccd
校验的规则如下:
身份证的前十七位数字和对应的权值相乘后相加后所得的和对11取余的余数与校验位(身份证最后一位)相同则身份证合法。
前十七位的权值分别是:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
余数x和校验位y的对应规则如下:
x:0 1 2 3 4 5 6 7 8 9 10
y:1 0 X 9 8 7 6 5 4 3 2
Input
输入身份证号码。
Output
如果所输入身份证号码合法,则输出ID Correct,否则输出ID Wrong。
Sample Input
1222222222
11111111111111111111
341181198809150011
11010119900307387X
150102199003075131
150102200003075131
Sample Output
ID Wrong
ID Wrong
ID Correct
ID Correct
ID Correct
ID Wrong
解题思路
- 用数组id保存输入的身份证号码,数组y保存余数所对应的校验码,数组weight保存身份证前十七位对应的权值。
- 遍历数组id的前十七位,将其对应权值相乘通过sum累加。
- 对累加结果sum取余后与校验位比较。
经验总结
- 数组id为字符型数组,其中的数字直接运算用的是ASCII码,需转换为对应的数值后再参与计算。
- 可能某些字母数字组合碰巧能检验通过(不确定),故在检验最后一位之前,需先检验输入数据是否符合身份证的格式。
代码实现(C)
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
// 对输入数据是否符合身份证格式的检验
bool isIDString(const char *str) {
// 位数检验
if (strlen(str) != 18)
return false;
// 前十七位检验
for (int i = 0; i < 17; ++i)
if (str[i] < '0' || str[i] > '9')
return false;
// 最后一位检验
if ((str[17] < '0' || str[17] > '9') && str[17] != 'X')
return false;
return true;
}
bool isValidID(const char *id) {
// 数组y保存余数所对应的校验码
char y[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
// 数组weight保存身份证前十七位对应的权值
int weight[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
// 权值相乘累加
int sum = 0;
for (int i = 0; i < 17; ++i)
sum += (id[i] - '0') * weight[i];
return (y[sum % 11] == id[17]);
}
int main() {
// 数组id保存输入的身份证号码
char id[18];
while (~scanf("%s", id)) {
if (!isIDString(id))
printf("ID Wrong\n");
else if (isValidID(id))
printf("ID Correct\n");
else
printf("ID Wrong\n");
}
return 0;
}