欢迎您来到芯片的主页!

Welcome to Chipset's homepage!

检查出生年月日的字符窜是否合法

读取一个字符窜,该字符窜表示出生年月日,例如19880521表示1988年5月21日,判断这个日期是否合法,看起来似乎十分简单,但是具体做起来却很麻烦,因为一个字符窜中可能未必都是数字,即使都是数字可能月份和日期不正确,例如19861330显然有问题,不应该有13月份,再如19870230,2月份不应该有30天。其实我们只需要实现这样一个功能函数练练练字符窜处理就是了。它表示的范围在1900年1月1日至2099年12月31日之间,当然在这个区间内应该是个理论上合法的日期。

基本上可以这样分步来做,先检查字符窜长度是否合法,然后检查是否都是数字,然后检查年份是否合法,然后检查月份和天数是否合法。当然也可以在一起一并检查,只是逻辑上很乱。由于是终端字符窜读取检查,不要求速度一定多快。如果您很久没有写过字符窜处理的C程序了,不妨练练手回忆一下过去学习的知识。

下面的C代码(不用C++)有些臃肿,欢迎提出建议和意见。

#include <string.h>   // strlen, strncpy
#include <ctype.h>   // isdigit
#include <stdlib.h>   // 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 <stdio.h>  // 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");
}

posted on 2011-08-23 14:07 Chipset 阅读(1846) 评论(6)  编辑 收藏 引用 所属分类: 算法和数据结构消遣

Feedback

# re: 检查出生年月日的字符窜是否合法 2011-08-23 16:03 他她女鞋

还在迷糊中。  回复  更多评论   

# re: 检查出生年月日的字符窜是否合法[未登录] 2011-08-23 17:20 Chipset

@他她女鞋
原理很简单的。  回复  更多评论   

# re: 检查出生年月日的字符窜是否合法[未登录] 2011-08-24 12:06 杨粼波

原理很简单:广告。AD。  回复  更多评论   

# re: 检查出生年月日的字符窜是否合法 2011-08-24 21:58 匿名

month为2的分支中,没有判断day是否大于0  回复  更多评论   

# re: 检查出生年月日的字符窜是否合法[未登录] 2011-08-25 09:06 Chipset

@匿名
谢谢,这是一个bug,我马上改过来。  回复  更多评论   

# re: 检查出生年月日的字符窜是否合法[未登录] 2011-10-30 11:19 cppx

爷,正则表达式啊,都像你这么玩,程序员全累死完了。  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理