一個合法的身份證號碼由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
題目思路:本題與其他身份證號驗證的題目類似,但不同的是:
1.本題目中給定的身份證號不一定全爲數字還可能有字母X;
2.而且是加權求和得到sum;
3.最後他還要進行替換來實現對應比較。
經歷元氣滿滿的寫bug的過程之後的到以下代碼:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
//getchar();
int id[n];
for(int i=0;i<n;i++){
id[i]=0;//初始化爲0,若爲1則輸出(有問題),0不輸出 (沒問題)
}
getchar();
char a[n][19];
for(int i=0;i<n;i++){
scanf("%s",a[i]);
a[i][18]='\0';
getchar();
}
char z;
int sum=0;
int t[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
for(int i=0;i<n;i++){//檢查是否前十七位數字不爲字母
for(int k=0;k<17;k++){
if(a[i][k]=='X'){
id[i]=1; //如果不符合,直接標記並跳出。
break;
}
}
if(id[i]==0){//配合上面的跳出
for(int l=0;l<17;l++){////使用一個數組來儲存 權重。
sum+=t[l]*(a[i][l]-'0');//注意sum應該減去'0'!!!
}
z=sum%11+'0';
// printf("z is %c ",z);
if(z=='9'+1)z='2';
else if(z=='2')z='X';
else if(z=='1')z='0';
else if(z=='0')z='1';
else if(z=='3')z='9';
else {
z=12-(z-'0')+'0';//注意呀,找規律。。(不累的話也可以全部都寫一下替換2333333)
}
if(z!=a[i][17])id[i]=1;
// cout<<"id["<<i<<"]="<<id[i]<<" "<<"a["<<i<<"][17]="<<a[i][17]<<" "; ////檢測用的,因爲寫了好多bugbug
// printf("after z==%c\n",z);
sum=0;
}
}
//判斷輸出
int flag=0;
for(int i=0;i<n;i++){
if(id[i]==1){
printf("%s\n",a[i]);
flag=1;
}
}
if(!flag)cout<<"All passed";
return 0;
}
希望能對你做題有所幫助,對於標準輸入輸出,pta不支持gets,哎。