查验身份证

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

这是我本来写了很久才得到的
#include<stdio.h>//目前只差判断前17位都是数字 
int main()
{
    int N,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,j1=0;
    char r;
    scanf("%d",&N);
    for(int j2=1;j2<=N;j2++)
    {
        scanf("%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%c",&a,&b,&c,&d,&e,&f,&g,&h,&i,&j,&k,&l,&m,&n,&o,&p,&q,&r);//读入各位数字
        int sum,z;
        sum=(a*7+b*9+c*10+d*5+e*8+f*4+g*2+h*1+i*6+j*3+k*7+l*9+m*10+n*5+o*8+p*4+q*2);
        z=sum%11;

        char r1;
        switch(z)
        {
            case 0:r1='1';break;
            case 1:r1='0';break;
            case 2:r1='X';break;
            case 3:r1='9';break;
            case 4:r1='8';break;
            case 5:r1='7';break;
            case 6:r1='6';break;
            case 7:r1='5';break;
            case 8:r1='4';break;
            case 9:r1='3';break;
            case 10:r1='2';break;
        }

        if(r1!=r)
        {
            printf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%c\n",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
        }
        else
        {
            j1++;
        }
    }
    if(j1==N)
    {
        printf("All passed");
    }
    return 0;
}
后来发现没有办法判断前17位输入的是数字,所以这个方案不好。
并且,写得很乱,改都不好改

以上写于三月十几
···························································································
20200322更新

今天重新写一遍,换了一部分思路,用了新知识
经过很长时间(一个半小时),我终于过了。这次收获的更多了。

代码如下

#include<stdio.h>
int main()
{
    int n,sta=0,sum=0,z,per=0;//sta记录状态,用来判断前17位是否都是数字;sum为加权求和得到的值;z是对11取模后所得;per是通过的身份证号码数
    char r1;//r1是正确校验值
    scanf("%d\n",&n);//n组数据
    char a[18];
    int c[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
    for(int i=1;i<=n;i++)
    {
        //输入18位身份证号码
        for(int j=0;j<=18;j++)
        {
            a[j]=getchar();
        }

        //接下来判断前17位是否都是数字
        for(int o=0;o<=16;o++)
        {
            if((a[o]>=48)&&(a[o]<=57))continue;//第o+1位是数字则继续此次循环
            sta=1;//有某一位不是数字则sta=1
        }
        if(sta==1)//sta=1说明有某一位不是数字
        {
            for(int v=0;v<=17;v++)
            {
            printf("%c",a[v]);
            }
            printf("\n");
            sta=0;//复原sta的值 
            continue;
        }
        //就直接把此身份证号输出并结束此次循环

        //前17位都是数字则继续

        //首先加权求和
        for(int q=0;q<=16;q++)
        {
            sum=sum+(a[q]%48)*c[q];
        }
        //再与11取模
        z=sum%11;
        //再一一对应
        switch(z)
        {
            case 0:r1='1';break;
            case 1:r1='0';break;
            case 2:r1='X';break;
            case 3:r1='9';break;
            case 4:r1='8';break;
            case 5:r1='7';break;
            case 6:r1='6';break;
            case 7:r1='5';break;
            case 8:r1='4';break;
            case 9:r1='3';break;
            case 10:r1='2';break;
        }
        //再与所输校验值对比
        if(r1==a[17])
        {
            per++;//记录通过数加一 
        }
        else
        {
            for(int p=0;p<=17;p++)
            {
            printf("%c",a[p]);
            }
            printf("\n");
        }

        sum=0;
		z=0;//复原sum,z的值 
    }
    if(per==n)
    {
        printf("All passed");
    }
    return 0;
}

这次我很注意写注释,就不会像上次一样混乱。

通过做本题也学到不少

  1. 在DEVC++中调试时要想一次性将一个数组添加查看可以这样:

可以通过调试的时候添加查看:比如说有一个长度为3的vector v,如果想要查看v[0]的值,就在添加查看中写 * (&v[0])
如果想要查看整个数组的值,就可以写*(&v[0])@3
@后面的数字表示想要查看的长度,这里vector的长度是3所以可以写3就能看到所有的值~
1

  1. 思路上,将身份证号以字符格式输入才有利于判断前17位是否为数字(由ASCII值判断)
  2. 合理利用数组可以方便许多(比如你可以对比一下我的之前的代码,17个乃至18个%d输得烦人,明显是笨功夫)——我以后见到数组不再头大了。

也遇到许多问题

  1. 第六行之所以有一个\n是因为,原本没有时getchar()会将换行符输入进a[0],造成错误,这个可以加\n解决,也可以不用getchar(),换成scanf
  2. 低级错误,最开始没有在合适的时机将sta, z, sum的值恢复一下,以至于他们的值累积下来造成第一个结果正确,后续全部错误的结果
  3. 第31行处的continue位置最开始错误,错放到了 } 之后,就造成了错误结束本次循环
  4. 格式问题,每个错误身份证号输出后要换行——\n

还要加强的部分

  1. 主要是得再勤奋点,多学些东西,比如这次刚学到continue就用上了。

  1. 原文地址https://blog.csdn.net/liuchuo/article/details/60137651 ↩︎

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值