实验:查验身份证

实验要求:

一个合法的身份证号码共18位,由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  3  4  5  6  7  8  9  10(删掉了2)

M:1  0  9  8  7  6  5  4  3  2(删掉了2对应的X)

现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入、输出格式:

输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码,18位必须全部是数字。

不检验身份证前17位是否合理,只检查对前17位计算出的校验码是否与身份证第18位一致。如果一致,则输出“身份证号 passed”,否则输出“身份证号 Fail”。

输入、输出样例1

具体思路:

        

在选取数据类型时发现int类型储存不了十八位数字,所以我选用了能储存较大数的long long类型来储存身份证号,在具体实践时关于使用switch语句,个人感觉比较麻烦,于是便思考能否将权重用一个数储存下来,以便节省自己的工作量。我通过观察发现在权重数字中存在10,如果储存在一个数中便不好对权重数字取用,但是权重数字中不存在0,于是我便构思将10转化0储存,在取用时当遇到0时说明这一位的权重是10,这样我们便得到了一个权重数字。

这些都是程序外的工作,程序内我使用for循环对身份证的前17位与权重加权求和用sum储存,再用sum对11取模得到Z的值,也就是说使用Z时就是在使用sum%11,因此我不定义Z了而直接使用sum%11,通过观察Z与M的关系我得到如下关系:

可以看到当sum%11>2时M+sum%11=12;

                                            即M=12-sum%11;

        当sum%11<2时M+sum%11=1;

                                            即M=1-sum%11;

之后让M与身份证最后一位比较若相等则通过,不相等则不通过。

流程图:

代码实现如下:

#include<stdio.h>

int main() {

//将权重经过转化变成一个数字储存在qz中,若输入多组数据qz便需要多次使用qz所以要用一个备份储存权重

//身份证号也要经过数据处理,因此也要用备份保存起来,保证原始数据不丢失。

    long long sfz,qz=79058421637905842,m,beifen,bfqz;

    int sum = 0;

    int n;

    scanf_s("%d", &n);

    for (int i = 1; i <= n; i++) {

         sum = 0;

         bfqz = qz;

         scanf_s("%lld", &sfz);

         beifen = sfz;

         beifen /= 10;

         for (int i = 1; i <= 17; i++) {

             if(bfqz%10==0){

                  sum += (beifen % 10) * 10;

             }

             else {

                  sum += (beifen % 10) * (bfqz % 10);

             }

             bfqz /= 10;

             beifen /= 10;

         }

         sum = sum % 11;

         if (sum <=1 ) {

             m = 1 - sum;

         }

         else if (sum > 2) {

                  m = 12 - sum;

         }

         printf("%lld", sfz);

         if (m == sfz % 10) {

             printf("Passed\n");

         }

         else {

             printf("Fail\n");

         }

    }

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值