题目-查验身份证
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:
首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:
Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2
现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。
输入格式:
输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。
输出格式:
按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed
。
输入样例1:
4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X
输出样例1:
12010X198901011234
110108196711301866
37070419881216001X
输入样例2:
2
320124198808240056
110108196711301862
输出样例2:
All passed
具体分析
验证一个身份证号码的校验码准确性的步骤是:
①检验前17位是否全为数字:否则判定为有问题的身份证号码,需要输出该号码;是则进行下一步;
②计算:前17位的加权和 Sum → Sum 对11取模得 Z 值 → 按照对应关系得 M值;
③验证 Z值对应的 M值与第18位是否一致:一致则 passed,不一致则判定为有问题的身份证号码进而输出。
本题需要验证 N 个身份证号码,要把上述步骤框进一个循环 N 次的循环体中。
把 M 的值存放进一维字符数组 M[11] 中会发现 Z 的值就是数组的下标,故在表示 Z 和 M 之间的对应关系时可以用一维数组代替二维数组。
身份证中含有字母‘X’,所以18位身份证号码的数据类型为字符型数组,数字在字符数组中存放的是ASCII码,直接用 char 类型的数字计算时实际是其ASCII码值参与计算,因此在计算前需要进行转化:数字数值 = 其ASCII码值 - 48。
输出 "All passed" 的条件是所有号码都正常,即只要没有号码被输出,就输出 "All passed",设置一个 wrong 标志查验有无输出号码。
代码
1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int N, i, j, t, wrong(0); //N为号码个数,i、j、t都是辅助变量,wrong标志有无出错号码 7 cin >> N; 8 9 char ID[N][18]; //输入18位身份证号码,因为有‘X’,为字符型 10 for(i=0; i<N; i++){ 11 for(j=0; j<18; j++){ 12 cin >> ID[i][j]; 13 } 14 } 15 cout << endl; //为了更直观看输出结果 16 17 char M[11]={'1','0','X','9','8','7','6','5','4','3','2'}; //校验码 18 int q[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; //权重 19 20 for(i=0; i<N; i++){ //按输入的顺序逐个检验号码 21 for(j=0; j<17; j++){ 22 if(ID[i][j]>'9' || ID[i][j]<'0') 23 { //前17位中一旦有非数字,便直接判定为有问题的身份证号码,并输出该号码 24 for(t=0; t<18; t++){ 25 cout << ID[i][t]; 26 wrong = 1; //有出错号码 27 } 28 cout << endl; 29 break; //前往检验下一个号码 30 } 31 else{ 32 if(j==16){ //前17位全为数字,设置验算断点 33 int cal[17]; //用于计算数值的一维整型数组,存放前17位数字 34 int Sum=0, Z; //权重之和 Sum, 取模得值 Z 35 for(t=0; t<17; t++){ //1.将 char 转换为 int 36 cal[t] = ID[i][t] - 48; //数字的ASCII码值比数字的数值大48 37 } 38 for(t=0;t<17;t++){ //2.计算加权和 39 Sum = Sum + cal[t]*q[t]; 40 } 41 Z = Sum % 11; //取模得 Z 值 42 if(M[Z] != ID[i][17]){ //3.校验码不准确时输出有问题的身份证号 43 for(t=0; t<18; t++){ 44 cout << ID[i][t]; 45 wrong = 1; 46 } 47 cout << endl; 48 } //校验码准确则 passed 49 } 50 } 51 } 52 } 53 if(wrong == 0){ //没有输出过号码,即所有号码都正常 54 cout << "All passed" << endl; 55 } 56 57 return 0; 58 }