题目-查验身份证

题目-查验身份证

一个合法的身份证号码由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 }

 

 

posted on 2021-05-11 10:39  屯饨  阅读(364)  评论(0编辑  收藏  举报

导航