读取一个字符窜,该字符窜表示出生年月日,例如19880521表示1988年5月21日,判断这个日期是否合法,看起来似乎十分简单,但是具体做起来却很麻烦,因为一个字符窜中可能未必都是数字,即使都是数字可能月份和日期不正确,例如19861330显然有问题,不应该有13月份,再如19870230,2月份不应该有30天。其实我们只需要实现这样一个功能函数练练练字符窜处理就是了。它表示的范围在1900年1月1日至2099年12月31日之间,当然在这个区间内应该是个理论上合法的日期。
基本上可以这样分步来做,先检查字符窜长度是否合法,然后检查是否都是数字,然后检查年份是否合法,然后检查月份和天数是否合法。当然也可以在一起一并检查,只是逻辑上很乱。由于是终端字符窜读取检查,不要求速度一定多快。如果您很久没有写过字符窜处理的C程序了,不妨练练手回忆一下过去学习的知识。
下面的C代码(不用C++)有些臃肿,欢迎提出建议和意见。
#include // strlen, strncpy
#include // isdigit
#include // atoi
int isValidDate(const char* str)
{
// 检查长度
const int LEN = 8;
int len = strlen(str);
if(LEN != len)
return 0;
// 检查所有字符是否均为数字
int idx = 0;
while(idx < LEN && isdigit(str[idx])) ++idx;
if(idx < LEN)
return 0;
// 检查年份是否在[1900, 2099]
char year_str[5] = { 0 };
strncpy(year_str, str, 4);
int year = atoi(year_str); // to extract year
if(year < 1900 || 2099 < year)
return 0;
// 检查月份和日期是否合乎逻辑
char month_str[3] = { 0 }, day_str[3] = { 0 };
strncpy(month_str, str + 4, 2); // 抽取月份字符窜
strncpy(day_str, str + 6, 2); // 抽取日期字符窜
int day = atoi(day_str);
int month = atoi(month_str);
switch(month)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12: /* 31天 */
return 0 < day && day < 32;
case 4: case 6: case 9: case 11: /* 30天 */
return 0 < day && day < 31;
case 2: /* 2月份比较特殊,闰年: 29天,平年: 28天 */
{
int leap = (0 == year % 4 && 0 != year % 100) || (0 == year % 400);
return (1 == leap && (0 < day && day < 30)) || (0 == leap && (0 < day && day < 29));
}
default: return 0;
}
}
/* 简单输出结果小测一下 */
#include // printf
int main ()
{
const char* str1 = "20552029";
const char* str2 = "18960321";
const char* str3 = "2000a220";
const char* str4 = "20110132";
const char* str5 = "19990138";
const char* str6 = "209905-9";
const char* str7 = "20000229";
printf(isValidDate(str1) ? "valid\n" : "invalid\n");
printf(isValidDate(str2) ? "valid\n" : "invalid\n");
printf(isValidDate(str3) ? "valid\n" : "invalid\n");
printf(isValidDate(str4) ? "valid\n" : "invalid\n");
printf(isValidDate(str5) ? "valid\n" : "invalid\n");
printf(isValidDate(str6) ? "valid\n" : "invalid\n");
printf(isValidDate(str7) ? "valid\n" : "invalid\n");
}