You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Python Week3作业Outdated:区分输入格式与数值范围错误处理

CS50 Python Outdated作业问题修复方案

问题描述

做CS50 Python第三周的Outdated作业时碰到的问题:

  • 作业要求:写个程序接收两种格式的日期——MM/DD/YYYY或者英文月份格式(比如September 8, 1636),转成YYYY-MM-DD格式输出;如果输入无效,就得重新提示用户输入。
  • 当前代码的问题:
    1. 输入完全不符合格式要求时(比如数字格式日期里混了非数字内容)直接报错崩溃,没法正常拒绝并重新提示
    2. 日期、月份数值超出范围时的重新提示逻辑混乱,递归调用导致流程出错

原代码核心问题

  1. 没做异常处理:处理数字格式日期时,直接用int()转分割后的字符串,碰到非数字就会抛出ValueError程序崩了
  2. 格式校验太松:
    • 数字格式没检查是不是刚好分成3部分(比如输入1/2020会直接索引越界)
    • 英文格式没检查分割后的部分数量,也没校验日期后面的逗号是否存在
  3. 错误处理逻辑乱:用递归调用check()来重新获取输入,导致函数栈嵌套,原来的循环逻辑完全失效
  4. 日期合法性校验不全:只检查了日期是否大于31,没考虑不同月份的天数差异(比如2月最多28/29天,4月最多30天)

修复后的代码

MONTHS = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
]

def is_leap_year(year):
    # 判断闰年,用来校验2月的天数
    if year % 4 != 0:
        return False
    elif year % 100 != 0:
        return True
    else:
        return year % 400 == 0

def get_max_days(month, year):
    # 返回对应月份的最大天数
    if month in [4, 6, 9, 11]:
        return 30
    elif month == 2:
        return 29 if is_leap_year(year) else 28
    else:
        return 31

def validate_numeric_date(date_str):
    # 校验并解析数字格式的日期
    parts = date_str.split("/")
    if len(parts) != 3:
        return None
    try:
        month = int(parts[0])
        day = int(parts[1])
        year = int(parts[2])
    except ValueError:
        return None
    # 校验月份范围
    if not (1 <= month <= 12):
        return None
    # 校验日期范围
    max_day = get_max_days(month, year)
    if not (1 <= day <= max_day):
        return None
    return (year, month, day)

def validate_word_date(date_str):
    # 校验并解析英文月份格式的日期
    parts = date_str.split()
    if len(parts) != 3:
        return None
    month_name, day_part, year_str = parts
    # 校验月份名称
    month_name = month_name.title()
    if month_name not in MONTHS:
        return None
    month = MONTHS.index(month_name) + 1
    # 处理日期部分的逗号
    if not day_part.endswith(","):
        return None
    day_str = day_part[:-1]
    try:
        day = int(day_str)
        year = int(year_str)
    except ValueError:
        return None
    # 校验日期范围
    max_day = get_max_days(month, year)
    if not (1 <= day <= max_day):
        return None
    return (year, month, day)

def main():
    while True:
        date_input = input("Date: ").strip()
        # 先尝试解析数字格式
        result = validate_numeric_date(date_input)
        if result:
            year, month, day = result
            print(f"{year}-{month:02d}-{day:02d}")
            break
        # 再尝试解析英文格式
        result = validate_word_date(date_input)
        if result:
            year, month, day = result
            print(f"{year}-{month:02d}-{day:02d}")
            break
        # 格式无效,重新提示输入
        continue

if __name__ == "__main__":
    main()

关键改进点

  • 统一输入循环逻辑:用main()里的while True循环处理输入,代替原来的递归调用,流程清晰可控
  • 完善异常处理:解析数字时用try-except捕获ValueError,避免程序崩溃
  • 严格格式校验:
    • 数字格式检查是否刚好分割为3部分
    • 英文格式检查分割为3部分、日期部分是否带逗号
  • 完整日期合法性校验:
    • 添加闰年判断,准确校验2月的天数
    • 区分不同月份的最大天数(30/31天)
  • 模块化拆分:把日期校验、闰年判断、最大天数计算拆成独立函数,代码更易维护
  • 返回值清晰:校验函数返回None表示输入无效,返回合法的(year, month, day)元组表示有效,逻辑明确

内容的提问来源于stack exchange,提问作者Koh Cw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:53:12