第二题:身份证号查验程序

第二题:身份证号查验程序

Author : StarsAC

Date : May 16th, 2024

输出结果

1. 题目解析

本题要求编写一个程序来查验身份证号码的有效性并输出有问题的号码。查验的内容包括字符串长度,字符串所含字符以及最后一位的校验码是否正确。其中,位于身份证号最后一位的校验码的计算规则如下:

  1. 前17位数字按照特定的权重进行加权求和,权重分配为如下表所示。

    身份证数字位数1234567891011121314151617
    对应权重7910584216379105842
  2. 将计算的和对11取模,得到值Z。

  3. 根据Z值与校验码M的值的对应关系,如下表所示,确定身份证号码的最后一位是否有效。

    Z012345678910
    M10X98765432

2.关键数据结构

  1. char类型字符串数组id1[][]用于存储输入的身份证号码组。
  2. char类型数组id[]:用于存储待验证的身份证号码。
  3. int类型数组weights:存储身份证号码前17位的加权因子,数组长度为17,元素值为{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
  4. char类型数组check_num:储存身份证号码最后一位的校验码M的映射,字符串长度为11,值为"10X98765432"

3.功能模块设计

  1. **身份证号码的格式检查:**检查身份证号码组成的字符串长度是否为18,且前17位只能是数字09,最后一位只能是数字09或字符‘X’。
  2. **加权求和计算:**计算身份证号码前17位数字的加权和。
  3. **Z值的计算:**将身份证号码前17位数字的加权和对11取模得到Z值。
  4. **校验码M的计算:**根据Z值与校验码M的值的对应关系得到相对应的M值。
  5. **验证身份证号码的有效性:**检查用户输入的身份证号码的校验码值和计算结果是否匹配。
  6. **结果输出:**向控制台打印输出经过校验后发现问题的身份证号码。

4.编写并调试各功能模块

1.身份证号码的格式检查

int validate_format(char* id){      	//身份证号码校验函数
    int i;
    if(strlen(id) != 18){       		//判断身份证号码是否为18位
        return -1;
    }

    for (i = 0; i < 17; i++) {      	//判断前17位是否合法
        if(id[i] < '0' || id[i] > '9'){
            return -1;
        }
    }

    if(!((id[17] >= '0' && id[17] <= '9' ) || id[17] == 'x' || id[17] == 'X' )){    											//判断第18位是否合法
        return -1;
    }
    return 0;       					//如果合法, 返回正常值0
}

2.加权求和计算

int weights[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};//权重
int sum_weights,i,j,n;          		//初始化变量
for (i= 0; i < 17; i++) {				//计算加权和
        sum_weights += (id[i] - '0') * weights[i];
}

3.Z值的计算

int z = sum_weights % 11;       		//计算Z

4.校验码M的计算

char check_num[] = {"10X98765432"};     //Z和M之间的映射关系
char m = check_num[z];          		//得到相应的M值

5.验证身份证号码的有效性,输出判断结果

char id1[n][18];                        //创建字符串数组
for (j = 0;j < n; j++){                 //遍历字符串数组
    printf("请输入身份证号,以回车键结束:\n");
    scanf("%s", &id1[j]);
    char* id = id1[j];
    if(validate_format(id) != 0){       //若身份证号格式错误
        printf("身份证号格式错误:%s\n",id);
    }else{
        for (i= 0; i < 17; i++) {       //计算加权和
            sum_weights += (id[i] - '0') * weights[i];
        }
        int z = sum_weights % 11;       //计算Z
        char m = check_num[z];          //得到相应的M值
        if(id[17] != m) {               //若身份证号校验码错误
            printf("身份证号校验码错误:%s\n", id);
        }
    }
}

5.测试样例及对应输出

请输入要验证的身份证号码的数量,以回车键结束:
4
请输入身份证号,以回车键结束:
101
身份证号格式错误:101
请输入身份证号,以回车键结束:
11111111111111111A
身份证号格式错误:11111111111111111A
请输入身份证号,以回车键结束:
111111111111111111
身份证号校验码错误:111111111111111111
请输入身份证号,以回车键结束:
111111111111111110

进程已结束,退出代码为 0

6.完整程序

#include <stdio.h>
#include <string.h>
int validate_format(char* id);

int main(void) {
    int weights[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};    //权重
    char check_num[] = {"10X98765432"};     //Z和M之间的映射关系
    int sum_weights,i,j,n;          		//初始化变量
    printf("请输入要验证的身份证号码的数量,以回车键结束:\n");
    scanf("%d",&n);
    char id1[n][18];                        //创建字符串数组
    for (j = 0;j < n; j++){                 //遍历字符串数组
        sum_weights = 0;
        printf("请输入身份证号,以回车键结束:\n");
        scanf("%s", &id1[j]);
        char* id = id1[j];
        if(validate_format(id) != 0){       //若身份证号格式错误
            printf("身份证号格式错误:%s\n",id);
        }else{
            for (i= 0; i < 17; i++) {       //计算加权和
                sum_weights += (id[i] - '0') * weights[i];
            }
            int z = sum_weights % 11;       //计算Z
            char m = check_num[z];          //得到相应的M值
            if(id[17] != m) {               //若身份证号校验码错误
                printf("身份证号校验码错误:%s\n", id);
            }
        }
    }
    return 0;
}

int validate_format(char* id){      		//身份证号码校验函数
    int i;
    if(strlen(id) != 18){       			//判断身份证号码是否为18位
        return -1;
    }

    for (i = 0; i < 17; i++) {      		//判断前17位是否合法
        if(id[i] < '0' || id[i] > '9'){
            return -1;
        }
    }

    if(!((id[17] >= '0' && id[17] <= '9' ) || id[17] == 'x' || id[17] == 'X' )){    												//判断第18位是否合法
        return -1;
    }
    return 0;       						//如果合法, 返回正常值0
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值