1.描述
警察办案里检索到一批(n个)身份证号码,希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码大小进行排序,如果是错误的身份证号,则从排序列表中删除(仅需判断前两位省级地区编码是否在下面的列表中,以及对出生年月是否在1949.10.1-2022.10.1之间进行判断)。
备注:身份证号码为18位的数字组成,省级地区编码是第1到第2位,出生日期为第7到第14位。
身份证前两位各省对应的编号是:
11 北京市\12 天津市\13 河北省\14 山西省\15 内蒙古自治区
21 辽宁省\22 吉林省\23 黑龙江省
31 上海市\32 江苏省\33 浙江省\34 安徽省\35 福建省\36 江西省\37 山东省
41 河南省\42 湖北省\43 湖南省\44 广东省\45 广西壮族自治区\46 海南省
50 重庆市51 四川省52 贵州省53 云南省54 西藏自治区
61 陕西省62 甘肃省63 青海省64 宁夏回族自治区65 新疆维吾尔自治区
71 台湾省
81 香港特别行政区82 澳门特别行政区
*输入格式
第一行一个整数n,表示有n个身份证号码 (n<100)
余下的n行,每行一个身份证号码。 (已保证输入数字是18位)
*输出格式
按出生时间从大到小排序后的身份证号,每行一条
*样例输入
8
466272199203271156
21585619900709197X
21585620000228197X
234804198701078365
404475727700034980//【注:地区码不对】
710351199203313165
118698189201011234//【注:出生年份不对】
50123419831343135X//【注:出生月日不对】
*样例输出
234804198701078365
21585619900709197X
710351199203313165
466272199203271156
//
2.代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <bitset>
#include <string>
#include <vector>
#include <algorithm>
// 使用脚本make.sh编译
/*
(仅需判断前两位省级地区编码是否在下面的列表中,以及对出生年月是否在1949.10.1-2022.10.1之间进行判断)。
备注:身份证号码为18位的数字组成,省级地区编码是第1到第2位,出生日期为第7到第14位。
身份证前两位各省对应的编号是:
11 北京市\12 天津市\13 河北省\14 山西省\15 内蒙古自治区
21 辽宁省\22 吉林省\23 黑龙江省
31 上海市\32 江苏省\33 浙江省\34 安徽省\35 福建省\36 江西省\37 山东省
41 河南省\42 湖北省\43 湖南省\44 广东省\45 广西壮族自治区\46 海南省
50 重庆市51 四川省52 贵州省53 云南省54 西藏自治区
61 陕西省62 甘肃省63 青海省64 宁夏回族自治区65 新疆维吾尔自治区
71 台湾省
81 香港特别行政区82 澳门特别行政区
*/
/*
描述
C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。
声明
下面是 atoi() 函数的声明。
int atoi(const char *str)
参数
str -- 要转换为整数的字符串。
返回值
该函数返回转换后的长整数,如果没有执行有效的转换,则返回零。
*/
static const int ID_LEN = 18;
static const int YEAR_MIN = 1949;
static const int YEAR_MAX = 2022;
static const std::bitset<83>PROVINCE_CODES("11000000000100000111110000001111100011111100011111110000000111000001111100000000000");
struct id_info {
id_info(const char *str) : id(str) {
}
bool parse_info() {
if (id.size() != 18) {
std::cerr << "error id size:" << id.size() << std::endl;
return false;
}
code = (id[0] - '0') * 10 + id[1] - '0';
if (code >= PROVINCE_CODES.size() || (false == PROVINCE_CODES.test(code))) {
std::cerr << "error id code:" << code << std::endl;
return false;
}
char tmp[8] = { 0 };
memcpy(tmp, id.c_str() + 6, 4);
year = atoi(tmp);
memset(tmp, 0, sizeof(tmp));
if (year < YEAR_MIN || year > YEAR_MAX) {
std::cerr << "error id year:" << year << std::endl;
return false;
}
memcpy(tmp, id.c_str() + 10, 2);
month = atoi(tmp);
memset(tmp, 0, sizeof(tmp));
if (month < 1 || month > 12) {
std::cerr << "error id month:" << month << std::endl;
return false;
}
memcpy(tmp, id.c_str() + 12, 2);
day = atoi(tmp);
if (day < 1 || day > 31) {
std::cerr << "error id day:" << day << std::endl;
return false;
}
if (2 == month) {
if ((0 == year % 4) && ((year % 100 != 0) || (0 == year % 400))) {
if (day != 29) {
std::cerr << "leap year:" << year << " error 2 month days:" << day << std::endl;
return false;
}
}
else {
if (day != 28) {
std::cerr << "non leap year:" << year << " error 2 month days:" << day << std::endl;
return false;
}
}
}
return true;
}
std::string id;
int code = 0;
int year = 0;
int month = 0;
int day = 0;
};
class ids_process {
public:
void add_id(const char *str) {
if (!str) {
return;
}
id_info info(str);
if (true == info.parse_info()) {
infos_.push_back(info);
}
}
void sort_ids() {
constexpr auto compare = [] (const id_info &info_one, const id_info &info_other) {
if ((info_one.year == info_other.year) && (info_one.month == info_other.month) && (info_one.day == info_other.day)) {
return info_one.id >= info_other.id;
}
else {
if (info_one.year > info_other.year) {
return true;
}
else if (info_one.year < info_other.year) {
return false;
}
else if (info_one.month > info_other.month) {
return true;
}
else if (info_one.month < info_other.month) {
return false;
}
else return info_one.day >= info_other.day;
}
};
std::sort(infos_.begin(), infos_.end(), compare);
}
void show_ids() const {
std::cout << "=============show ids==============" << std::endl;
for (auto &info : infos_) {
std::cout << info.id << std::endl;
}
}
private:
std::vector<id_info>infos_;
};
int main()
{
int iCount = 0;
const int MAX_LEN = 100;
char id[MAX_LEN] = { 0 };
printf("请输入身份证个数:");
scanf("%d", &iCount);
printf("\n");
if (iCount > 100) {
std::cerr << "invalid count:" << iCount << std::endl;
return -1;
}
ids_process idsp;
printf("请依次输入身份证:\n");
getchar();
for(int i=0; i<iCount; i++)
{
fgets(id, ID_LEN + 1, stdin); // add \0
idsp.add_id(id);
getchar(); // accept \n
}
idsp.sort_ids();
idsp.show_ids();
return 0;
}
3.编译
Makefile:
src = $(wildcard ./*.cpp) # 获取当前目录下所有.cpp文件
objs = $(patsubst %.cpp, %.o, $(src)) # 字符串替换,将.cpp替换为.o,%表示任意字符串
target = idsort
INCLUDE := -I.
LIBS := -lpthread
CFLAGS := -g -Wall $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -std=c++11 -DHAVE_CONFIG_H
$(target): $(objs)
$(CXX) $^ $(LIBS) -o $@
# $(CXX) 代表g++
# $^ 表示所有的依赖文件
# $@ 表示要生产的目标
idsort.o: idsort.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
.PHONY:clean # clean不是一个要生成的文件,假目标
clean:
rm *.o -f
4.运行测试