提交记录 #151
提交时间:2024-11-10 13:52:08
语言:c
状态:Unaccepted
编译情况:编译成功
固定测试点#1:
额外测试点#9:
38【日期】身份证的奥秘
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_LENGTH 20 // 身份证号码的最大长度
int weight[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
char checkCode[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
// 判断是否为有效日期
int isValidDate(int year, int month, int day) {
if (month < 1 || month > 12) return 0;
int days_in_month = 31; // 默认一个月31天
if (month == 2) {
// 闰年判断
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
days_in_month = 29; // 二月闰年29天
} else {
days_in_month = 28; // 二月平年28天
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
days_in_month = 30; // 4, 6, 9, 11 这些月30天
}
return day > 0 && day <= days_in_month;
}
// 判断身份证是否合法的函数
int isValidID18(const char *id18) {
int sum = 0;
// 计算加权和
for (int i = 0; i < 17; i++) {
if (!isdigit(id18[i])) {
return 0; // 非数字字符无效
}
sum += (id18[i] - '0') * weight[i];
}
// 计算校验码
int mod = sum % 11;
if (id18[17] != checkCode[mod]) {
return 0; // 校验码错误
}
// 检查出生日期的有效性
int year = (id18[6] - '0') * 1000 + (id18[7] - '0') * 100 +
(id18[8] - '0') * 10 + (id18[9] - '0');
int month = (id18[10] - '0') * 10 + (id18[11] - '0');
int day = (id18[12] - '0') * 10 + (id18[13] - '0');
if (!isValidDate(year, month, day)) {
return 0; // 如果出生日期无效,则身份证无效
}
return 1; // 身份证合法
}
// 将15位身份证号码升级到18位的函数
void upgradeTo18(const char *id15, char *id18) {
// 复制前6位地址码
strncpy(id18, id15, 6);
// 设置年份部分
id18[6] = '1'; // 年份前缀
id18[7] = '9'; // 默认设置为19yy
// 处理顺序码以决定年份前缀
const char *sequence_code = id15 + 12; // 取顺序码部分
if (strcmp(sequence_code, "996") == 0 || strcmp(sequence_code, "997") == 0 ||
strcmp(sequence_code, "998") == 0 || strcmp(sequence_code, "999") == 0) {
id18[7] = '8'; // 设置为18yy,因为是百岁以上的老人
}
// 复制出生日期部分
strncpy(id18 + 8, id15 + 6, 6); // 复制出生日期 (yyMMdd)
// 复制顺序码
strncpy(id18 + 14, id15 + 12, 3);
// 计算校验码
int sum = 0;
for (int i = 0; i < 17; i++) {
sum += (id18[i] - '0') * weight[i];
}
// 设置校验码
int mod = sum % 11;
id18[17] = checkCode[mod]; // 最后1位为校验码
// 设置结束符
id18[18] = '\0'; // 确保字符串结束
}
// 主函数
int main() {
int N;
scanf("%d", &N);
getchar(); // 读取换行符以避免影响后续 fgets 的读取
for (int i = 0; i < N; i++) {
char identity[MAX_LENGTH];
fgets(identity, sizeof(identity), stdin);
// 去掉可能的换行符
identity[strcspn(identity, "\n")] = '\0';
int length = strlen(identity);
if (length == 18) {
// 检查18位身份证号码的有效性
if (isValidID18(identity)) {
printf("Valid\n");
} else {
printf("Invalid\n");
}
} else if (length == 15) {
char id18[MAX_LENGTH];
upgradeTo18(identity, id18);
printf("%s\n", id18);
} else {
printf("Invalid\n");
}
}
return 0;
}