/*特别鸣谢——猫猫学姐*/
小明特别想知道自己身份证号码的秘密,那我就告诉你吧!
公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码,可以用字母表示为:
ABCDEFYYYYMMDDXXXR。
1.地址码ABCDEF。表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260标准的规定执行。
2.出生日期码YYYYMMDD。表示编码对象出生的年、月、日,按GB/T7408标准的规定执行,年、月、日代码之间不用分隔符。
3.顺序码XXX。表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
4.校验码R。根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2标准校验码计算出来的检验码。
18位身份证号码的编排规则:
(1)前1、2位数字表示:所在省份的代码;
11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古"
21:"辽宁",22:"吉林",23:"黑龙江"
31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东"
41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南"
50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏"
61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆"
81:"香港",82:"澳门",83:"台湾地区
91:"国外"
(2)第3、4位数字表示:所在城市的代码;
(3)第5、6位数字表示:所在区县的代码;
(4)第7~14位数字表示:出生年、月、日;
(5)第15、16位数字表示:所在地的派出所的代码;
(6)第17位数字表示性别:奇数表示男性,偶数表示女性;
(7)第18位数字是校检码:是由计算产生的,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示。
第十八位数字的计算方法为:
(1)将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:
7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2
(2)将这17位数字和系数相乘的结果相加。
(3)用加出来和除以11,看余数是多少?
(4)余数只可能有0 1 2 3 4 5 6 7 8 9 10 这11个数字。其分别对应的最后一位
身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
(5)通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。
首先:我们得出,前17位数字与相应系数的乘积和是189。
然后:用189除以11得出的结果是17余2,也就是说余数是2。
最后:通过对应规则就可以知道余数2对应的数字是x。所以,这是一个合格的身份证号码。
现在,于老师给你一个身份证号,你能知道它是不是一个合法的号码?如果是合法的你知道这个号码是男是女吗?
输入格式:
一行中一串号码,最多18位,可能不是18位,每位也可能不是数字或X,没空格。
输出格式:
请按如下顺序判断并输出结果
1.不够18位,直接输出(X为实际读到的位数):
No WeiShuBuZu:X
以下情况需要首先一行原样输出身份证号,如果其中有非法字符用括号括上。
2.有非法字符,即前17位不是数字或第18位不是数字和X,先输出号码本身(非法字符用括号括上),再输出(X为非法字符个数):
No FeiFaZiFu:X
3.省份代码不合法,输出(XX为出错的省份码):
No ShengFenDaiMa:XX
4.出生日期不是合法日期,输出(YYYYMMDD为出错的日期):
No ChuShengRiQi:YYYYMMDD
5.第18位校验代码错误,输出(E为错误代码R为计算得到的正确代码):
No JiaoYanHaoMa:E(R is right)
(不合法的号码只需要按以上顺序输出第一个原因)。
合法号码根据性别输出:Yes male(男)或者Yes female(女)
输入样例1:
34052419800101001
输出样例1:
No WeiShuBuZu:17
输入样例2:
3$0524198:010100Rx
输出样例2:
3($)0524198(:)010100(R)x
No FeiFaZiFu:3
输入样例3:
25042120021715082x
输出样例3:
25042120021715082x
No ShengFenDaiMa:25
输入样例4:
23042120021715082x
输出样例4:
23042120021715082x
No ChuShengRiQi:20021715
输入样例5:
340524198001010017
输出样例5:
340524198001010017
No JiaoYanHaoMa:7(X is right)
输入样例6:
34052419800101001X
输出样例6:
34052419800101001X
Yes male
#include <stdio.h>
#include <string.h>
int count = 0;
char jym;
char s[19];
int ch(char s[]) //字符,前17位不是数字或18位不是数字/x
{
char b[19] = {0}; //b为哈希表,记录非法位置
for (int i = 0; i < 18; i++) //判断并记录是否合法
{
if (s[i] < '0' || s[i] > '9')
{
if (i == 17 && (s[i] == 'x' || s[i] == 'X'))
continue;
b[i] = 1;
count++;
}
}
if (count != 0)
{
for (int i = 0; i < 18; i++)
{
if (b[i] == 1)
{
printf("(%c)", s[i]);
}
else
printf("%c", s[i]);
}
printf("\n");
return 1;
}
return 0;
}
int province(char s[]) //省份
{
int pro[10][10] = {{0}, {0, 1, 1, 1, 1, 1}, {0, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1}, {0}, {0, 1, 1, 1}, {0, 1}};
//二维数组哈希表储存合法省份代码,第一位为行第二位为列,合法置1
if (pro[(int)(s[0] - '0')][(int)(s[1] - '0')] != 1)
return 1;
return 0;
}
int birth(char s[]) //生日
{
int mon[15] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //数组储存每个月日期,二月单独算
int y, m, d;
y = 1000 * (s[6] - '0') + 100 * (s[7] - '0') + 10 * (s[8] - '0') + (s[9] - '0');
m = 10 * (s[10] - '0') + (s[11] - '0');
d = 10 * (s[12] - '0') + (s[13] - '0');
if (m < 1 || m > 12)
return 1;
if (m == 2)
{
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
mon[2] = 29;
else
mon[2] = 28;
}
if (d < 1 || d > mon[m])
return 1;
return 0;
}
int ISO(char s[]) //校验码
{
int xi[20] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
char yu[15] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
//哈希表预处理系数和余数
int sum = 0, remainder;
for (int i = 0; i < 17; i++)
sum += xi[i] * (s[i] - '0');
remainder = sum % 11;
jym = yu[remainder];
if (s[17] != jym)
{
if (jym == 'X' && s[17] == 'x')
return 0;
return 1;
}
return 0;
}
int main()
{
scanf("%s", s);
if (strlen(s) < 18)
{
printf("No WeiShuBuZu:%lu\n", strlen(s));
}
else if (ch(s) == 1)
{
printf("No FeiFaZiFu:%d\n", count);
}
else if (province(s) == 1)
{
printf("No ShengFenDaiMa:%c%c\n", s[0], s[1]);
}
else if (birth(s) == 1)
{
printf("No ChuShengRiQi:");
for (int i = 6; i < 14; i++)
printf("%c", s[i]);
printf("\n");
}
else if (ISO(s) == 1)
{
printf("No JiaoYanHaoMa:%c(%c is right)\n", s[17], jym);
}
else
{
if ((s[16] - '0') % 2 == 0)
printf("Yes female\n");
else
printf("Yes male\n");
}
return 0;
}