当前位置: 代码迷 >> 综合 >> 身份证号码转换(15-->18 or 18-->15)
  详细解决方案

身份证号码转换(15-->18 or 18-->15)

热度:97   发布时间:2024-01-28 18:55:41.0

要用身份证号码,但是不记得第18位是啥了,于是在网上查了一下,有计算方法,兴起,就按照算法写下了下面的代码。

经过VS2019编译,运行,结果没有问题。

功能:

1.自动判断输入的是15位还是18位,15则转18,18则转15 输出

2.如果输入的是15位,因为年代不明确(19 or 20),给出提示,进一步确认

3.对输入的号码,从年、月、日三方面判断输入合理性

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<ctime>
using namespace std;
//第18位校验码计算对应的前17位参数
int wi[17] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 };
//存放18位身份证号
int ai[18] = { 0 };
//计算出的最后一位数字对应(%11)余数数组 
int checknum[11] = { 1,0,10,9,8,7,6,5,4,3,2 };
//用于校验月份输入正确性
int monthday[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
//计算前17位数字和校验参数乘积再求和
int sum = 0;
//用于确定出生年代,默认19**--20世纪
int Year = 1900;
//用于存放输入的需要转换的身份证号码
string id;
//15位转18位
void id15_id18()
{cout << ">>>>>>>>转换后号码为:";//获取前17位,并为计算校验码求和,在第7、8位加上年代(19 / 20)for (int i = 0, j = 0; i < 17; ++i){if (i < 8)j = i;elsej = i - 2;if (i == 6)ai[i] = Year / 1000;else if (i == 7)ai[i] = Year / 100 % 10;elseai[i] = (id[j] - '0');sum += wi[i] * ai[i];//为校验码求和}int i_18 = sum % 11;//计算出校验码%11的余数,获得对应校验码下标//输出18位身份证号码的前17位for (int i = 0; i < 17; ++i)cout << ai[i];//第18位如果校验码余数为10,则用 'X' 替换if (i_18 == 2)cout << "X";elsecout << checknum[i_18];//余数 0-9 按对应数组位置输出cout << endl;
}
//18位直接输出15位
void id18_id15()
{cout << endl << ">>>>>>>>>>转换后号码为:";//输出15位身份证号码for (int i = 0; i < 17; ++i)// i<17 ,直接舍弃第18位{if (i == 6)i += 2;//跳过年代数字19 / 20 向后继续输出cout << id[i];}cout << endl;
}//校验输入号码 月 日的正确性
int chekymd(int len)
{//获取当前年份time_t tt = time(NULL);tm* t = localtime(&tt);int Ynow = t->tm_year+1900;//计算身份证号码中的年月日int year, month, day;if (len == 15){cout << endl;cout << "2000年之前,输入【1】" << endl;cout << "2000年之后,输入【2】" << endl;cout << endl << "请确认:";int ye;//确定年代cin >> ye;cout << endl;if (ye == 2)Year = 2000;year = (id[6] - '0') * 10 + (id[7] - '0') + Year;month = (id[8] - '0') * 10 + (id[9] - '0');day = (id[10] - '0') * 10 + (id[11] - '0');}if (len == 18){year = (id[6] - '0') * 1000 + (id[7] - '0') * 100 + (id[8] - '0') * 10 + (id[9] - '0');month = (id[10] - '0') * 10 + (id[11] - '0');day = (id[12] - '0') * 10 + (id[13] - '0');}//判断年月日输入正确性if (year<1900 || year>Ynow){cout << "输入年份超范围 error..." << endl;return -1;}if (month < 1 || month>12){cout << "输入月份超范围 error..." << endl;return -1;}if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)monthday[1] = 29;if (day<1 || day>monthday[month - 1]){cout << "输入日期超范围 error..." << endl;return -1;}return 0;}int main()
{cout << "========身份证号码:15->18 or 18->15========" << endl;cout << endl << endl <<"===== 退出【exit/EXIT】 =====" << endl << endl;cout << endl << "******************************************** " << endl;cout << "输入要转换的身份证号码: ";cin >> id;while (id != "exit"&&id!="EXIT"){int len = id.length();cout << endl << "输入的号码为:" << len << "位. " << endl;if (len != 15 && len != 18){cout << endl << "输入错误..." << endl;}else{int ck = chekymd(len);//校验 月份 和 日期if (ck == -1)len = -1;//15位转18位输出if (len == 15)id15_id18();//18位转15位输出if (len == 18)id18_id15();}//重置数组和求和memset(ai,0,18);sum = 0;Year = 1900;//循环cout << endl << endl << "******************************************** " << endl;cout << "输入要转换的身份证号码: " ;cin >> id;}//system("pause");cout << endl << "程序结束,按任意键退出!" << endl;cin.get();cin.get();return 0;
}

此外,

1.如果希望更严谨,还可以对18位输入时的最后一位进行校验。(如果需要请自行修改代码)

2.如果能够获得前6位号码数据库,则可以对输入信息的前6位做校验

OK 就先记录这些吧。