学以致用——Java验证身份证号码是否正确(带校验算法)

需求:

验证身份证号码是否正确(带校验算法)

源码:

package javaCoreTech1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 * 
 * @author PDH
 * 华师大中国大学Mooc Java核心技术编程作业,部分代码参考:https://blog.csdn.net/qq_38971856/article/details/94415178
 *
 */
/*验证身份证号码是否正确(带校验算法)
题目内容:
输入一个字符串,请判断是否满足身份证基本要求,并返回具体的生日yyyy-mm-dd。
如果输入数据有误,请输出0000-00-00。
基本要求是:a)必须是18位;b) 前面位数必须是数字,最后一位可以是数字或小写字母;c) 日期是存在的;d)最后一位校验码检查。

校验码规则如下:
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11,看余数是多少?
4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2。
5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是10,身份证的最后一位号码就是罗马数字x。

输入格式:
一个身份证号,18位

输出格式:
yyyy-mm-dd

输入样例:
53010219200508011x

输出样例:
1920-05-08
时间限制:500ms内存限制:32000kb
*/

public class P9_IDChecker {

        public static void main(String[] args)
        {
            String id;    
            int checkResult = 0;
            
            //创建一个IDChecker类
            IDChecker2 idc = new IDChecker2();
               do {
            //输入身份证号
            id = idc.enterID();
            //验证身份证号
            checkResult = idc.checkID(id);
            switch (checkResult) {
                case -1, -2, -3, -4:
                    System.out.println("0000-00-00");
                    System.out.println("请重新输入!");
                    break;
                case 1:
                    System.out.println("身份证号符合当前所有校验规则!");
                    System.out.println("出生日期:"+id.substring(6, 10)+"-"+id.substring(10, 12)+"-"+id.substring(12, 14));
                    break;
                default:
                    break;
                }
               }
               while (checkResult!=1);
            
        }
        
}

class IDChecker2{
    private String id; 
    public IDChecker2() {
        
    }
    public String enterID() {
        System.out.println("请输入身份证号:");
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        try {
            id = input.readLine();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return id;
    }
    
    
    public int checkID(String id) {
        //a)必须是18位
        int lc = lengthCheck(id);
        if (lc < 0)  return lc;

        //b) 前面位数必须是数字,最后一位可以是数字或小写字母;
        int dic = digitCheck(id);
        if (dic < 0)  return dic;
        
        //c) 日期是存在的。
        int dac = dateCheck(id);
        if (dac <0) return dac;
            
        //d)最后一位校验码检查。
        int ldc = lastDigitCheck(id);
        if (ldc < 0) return ldc;

        //所有校验通过后,返回1
        return 1;
        
        }
    
    public int lengthCheck(String id) {
        //a)必须是18位
        if (id.length()!=18) {
            System.out.println("输入错误:位数不是18位!");
            return -1;
        }
        return 0;
    }
    
    public int digitCheck(String id) {
        //b) 前面位数必须是数字,最后一位可以是数字或小写字母;
        int i,n=0;
        for( i=0;i<17;i++)
        {
            if(id.charAt(i)>='0'&&id.charAt(i)<='9')
            {
                n++;
            }
            else
                break;
        }
    
        if(n<=16||!((id.charAt(17)>='0'&& id.charAt(17)<='9')||(id.charAt(17)>='a'&& id.charAt(17)<='z'))) {
            System.out.println("输入错误:前面位数必须是数字,最后一位可以是数字或小写字母!");
            return -2;
        }
        return 0;
    }
    
    public int dateCheck(String id) {
        //c) 日期是存在的。
        int year,month,day;
        year=Integer.valueOf(id.substring(6, 10));
        month=Integer.valueOf(id.substring(10, 12));
        day=Integer.valueOf(id.substring(12, 14));
    
        String strDate = id.substring(6, 14); 
        // 准备第一个模板,从字符串中提取出日期数字  
        String pat1 = "yyyyMMdd" ;  
        // 准备第二个模板,将提取后的日期数字变为指定的格式  
        String pat2 = "yyyy-MM-dd" ;  
        SimpleDateFormat sdf1 = new SimpleDateFormat(pat1) ;        // 实例化模板对象  
        SimpleDateFormat sdf2 = new SimpleDateFormat(pat2) ;        // 实例化模板对象  
        Date d = null ;  
        try{  
            d = sdf1.parse(strDate) ;   // 将给定的字符串中的日期提取出来  
        }catch(Exception e){            // 如果提供的字符串格式有错误,则进行异常处理  
            e.printStackTrace() ;       // 打印异常信息  
        }  
        String r=sdf1.format(d);
        if(!r.equals(strDate)) {
            System.out.println("输入错误:无效的出生日期!");
            return -3;
        }
//        else
//            System.out.println(sdf2.format(d)) ;    // 将日期变为新的格式
//        
        return 0;
    }
    
    public int lastDigitCheck(String id) {
        //d)最后一位校验码检查。
            /*
             * 校验码规则如下:
             * 1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
             * 2、将这17位数字和系数相乘的结果相加。 
             * 3、用加出来和除以11,看余数是多少?
             * 4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2。
             * 5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是10,身份证的最后一位号码就是罗马数字x。
             */
        
        //1.系数数组定义
        int[] factors = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
        //2.求和
        int sum = 0;
        for (int i =0;i<17;i++) {
            sum += (id.charAt(i)-'0')*factors[i];
        }
        //3.取余
        int remainder = sum % 11;
        //4.余数映射数组定义
        char[] mappedDigits = {'1','0','X','9','8','7','6','5','4','3','2'};
        //5.生成最后一位(校验位)
        char lastDigit = mappedDigits[remainder];
//        System.out.println("校验位:"+lastDigit);
        //判断输入的最后一位是否符合校验规则
        if (id.charAt(17)!=lastDigit) {
            System.out.println("输入错误:最后一位不符合校验规则");
            return -4;
        }
        return 0;
    }
}

运行结果:

请输入身份证号:
64222420230217661
输入错误:位数不是18位!
0000-00-00
请重新输入!
请输入身份证号:
64222420230217661X
输入错误:前面位数必须是数字,最后一位可以是数字或小写字母!
0000-00-00
请重新输入!
请输入身份证号:
642224202302296616
输入错误:无效的出生日期!
0000-00-00
请重新输入!
请输入身份证号:
642224202302176616
输入错误:最后一位不符合校验规则
0000-00-00
请重新输入!
请输入身份证号:
642224202302176617
身份证号符合当前所有校验规则!
出生日期:2023-02-17

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值