閒來無事,想不想秀翻身邊隊友呢?
閒來無事昨天在逛B站的時候,突然看到有個同樣在深究C語言的朋友發了一個關於身份證檢驗系統的視頻,因此就靜下來看了一下,從學習到分析,將其構成一定的思路自己補充完全前前後後花費了將近3個小時,可能也是因爲自己還是不夠熟練的原因的,但是好歹算是將其整體的完成了,看到成果的時候還是挺讓人高興的。
開發一個程序之前,最爲重要的是它所涉及到的每個步驟
所說到的每個步驟,籠統一些的說法其實就是所構建的它所要滿足的條件,比如對於身份證檢驗系統來說,不僅要滿足年月日,還應該滿足最後一位的ISO校驗,也就是因爲這一系列的問題纔會導致很多的朋友難以快速的完成對於程序的需求,因此很難快速的完成對一個程序的補充和完善。
程序段
主函數段
如果大家讀懂了主函數,或者說是知道要檢驗一個身份證所需要檢驗那些東西,那麼編寫一個身份證檢驗系統絕對是分分鐘就可以完成的了。
//**核心主函數**
int main()
{
char id[20] = { 0 };//定義所需要輸入身份證的長度
char choose;//爲之後查詢結束一個之後是否結束程序做準備
int year, month, day;
printf("※Luckily原創小程序※\n身份證號校驗or查詢系統\n");
start:
printf("————————————\n");
printf("請輸入需要查詢的身份證號:\n");
scanf("%18s", id);
if (CheckFormat(id) == 0) goto start;//基礎格式的檢查,是用來檢查身份證是否爲18位
year = Trans(id[6]) * 1000 + Trans(id[7]) * 100 + Trans(id[8]) * 10 + Trans(id[9]);
month = Trans(id[10]) * 10 + Trans(id[11]);//進行年月日的轉換,從身份證之中轉換出來我們所需要計算的年月日
day = Trans(id[12]) * 10 + Trans(id[13]);
if (CheckData(year, month, day) == 0)goto start;//檢查年月日是否符合正規的日期
if (CheckCode(id) == 0) goto start;//身份證最後一位ISO的校驗
printf("該身份證號是合法的身份證號!\n");
printf("————————————\n");
printf("信息如下:\n");
FindAddress(id);//輸出身份證前六位所對應的地理位置
FindSex(id);//輸出性別
FindBirthday(year, month, day);//出生日期
FindCode(id);//所在當地是同年同月裏第多少個孩子
printf("————————————\n");
printf("是否要再次查詢?按Y繼續,按其他鍵退出。\n");
choose = _getch();
if (choose == 'Y' || choose == 'y')goto start;
system("pause");
return 0;
}
子函數段
- ------字符轉數字的函數-------
int Trans(char c)
{
return (c - 48);
}
//因爲我們所輸入進去的都是ASCII值,而要完成查需轉換爲具體的數字
//數字字符值減去48才能夠得到所對應的整型數值
- ------基礎格式檢查函數-------
int CheckFormat(char *id) //用來檢查所輸入的身份證號的長度是否爲18
{
if (strlen(id) != 18)
{
printf("輸入錯誤,長度不正確,請檢查後重試!\n");
return 0;
}
for (i = 0; i < 17; i++)//檢查所輸入的第1-17位是否爲數組
{
if (id[i]>'9' || id[i] < '0')
{
printf("輸入錯誤,第1-17位出現非數字,請檢查後重試!\n");
return 0;
}
}
if ((id[17]>'9' || id[17] < '0')&&id[17] != 'X')//檢查所輸入的第十八位是否爲數字或者是X
{
printf("輸入錯誤,第18位不是數字或X,請檢查後重試!\n");
return 0;
}
return 1;
}
- ------出生日期檢查函數-------
int CheckData(int year, int month, int day)//用來檢查輸入的身份證號第7-14位出生日期的格式是否正確
{
int sign = 1;
if (month > 12 || month < 1) sign = 0;//檢查所輸入的月份是否正確
if (month == 2)//如果2月的話,則判斷此年份是否是閏年
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
if (day>29 || day < 1)sign = 0;
}
else if (day>28 || day < 1)sign = 0;
}
switch (month)//根據月份來判斷月份天數是否合格
{//此都歸爲大月
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day > 31 || day < 1)sign = 0; break;
case 4://此類歸爲小月
case 6:
case 9:
case 11:
if (day > 30 || day < 1)sign = 0; break;
}
if (sign == 0)
{
printf("該身份證號出生日期格式不正確,請檢查後重試!\n");
return 0;
}
return 1;
}
- ------ISO效驗碼檢查函數-------
int CheckCode(char *id)
{//對於這一個子函數的定義,很多人可能會不懂,我們可以進行百度搜索關於身份證校驗的規則就可以明白
int r[17] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
int check;
char code[11] = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3','2'};
int sum = 0;
for (i = 0; i < 17; i++)
{
sum += (Trans(id[i]))*r[i];
}
check = sum % 11;
if (id[17] != code[check])
{
printf("該身份證號未通過ISO校驗,請檢查最後一位後重試\n");
return 0;
}
return 1;
}
- ------常住戶口所在地輸出函數-------
void FindAddress(char *id)//根據身份證前六位輸出所對應的地址
{
int address;
address = Trans(id[0]) * 100000 + Trans(id[1]) * 10000
+ Trans(id[2]) * 1000 + Trans(id[3]) * 100
+ Trans(id[4]) * 10 + Trans(id[5]);
printf("常住戶口所在地:");
DataBase(address);//調用基礎數據檢測前六位所對應的地址
printf("\n");
}
- ------性別輸出函數-------
//身份證的第17位,奇數爲男,偶數爲女,通過除2得餘數來判斷
void FindSex(char *id)
{
int sex = Trans(id[16]);
printf("性別:");
if (sex % 2 == 1)printf("男\n");
if (sex % 2 == 0)printf("女\n");
}
- ------年齡和出生日期輸出函數-------
void FindBirthday(int year,int month,int day)//用來計算身份證所對應的出生年月日來計算對應的年齡
{
time_t timep;
struct tm *p;
time(&timep);
p = gmtime(&timep);//獲取系統時間中的年份
printf("年齡:%d歲\n", (1900 + p->tm_year) - year);
printf("出生日期:%4d年%2d月%2d日\n",year,month,day);
}
- ------順序碼輸出函數-------
void FindCode(char *id)//表示給同地同日出生的人進行編號第15-17位原樣輸出即可
{
printf("當地同年同月同日出生的第%c%c%c個孩子\n", id[14], id[15], id[16]);
}
- ------行政區劃代碼數據庫-------
void DataBase(int address)
{
switch (address)
{
case 110000:printf("北京市"); break;
case 110100:printf("北京市市轄區"); break;
case 110101:printf("北京市市轄區東城區"); break;
case 110102:printf("北京市市轄區西城區"); break;
...
...
...
case 710000:printf("臺灣省"); break;
case 810000:printf("香港特別行政區"); break;
case 820000:printf("澳門特別行政區"); break;
default:
printf("數據庫中無此行政代碼"); break;
}
}
因爲所對應的地點太多,因此我完整的程序大家可以在我的GitHub上取,我會將鏈接附在後面,並且將行政區劃代碼數據文件也粘貼在後面,可以供大家使用,代碼就這些, 快做出來自己過過癮吧。
身份證校驗系統GitHub鏈接
我所整理出來的數據是excel格式的,但是博客上所需要上傳都是擴展名必須包含.md,所以我將其以壓縮包的形式放在了資源之中了,大家可以下載免費使用了。