CS50 Python第二周作业‘Vanity Plates’代码问题求助
CS50 Python第二周作业:Vanity Plates个性化车牌验证问题求助
今天开始通过CS50课程学Python,第二周作业卡在「Vanity Plates」(个性化车牌验证)问题上,我之前没编程基础,突然变难有点摸不着头脑。
这个问题要求实现程序验证马萨诸塞州个性化车牌是否符合以下规则:
- 必须以至少两个字母开头;
- 字符数在2到6之间;
- 数字只能在末尾,且第一个数字不能为0;
- 不得包含句号、空格或标点符号。
程序需要通过is_valid函数返回布尔值判断输入是否有效,输入字母均为大写。
我写了代码,但运行测试用例时,部分用例(比如CS50、ECTO88等)运行后没输出,得手动终止;部分用例(比如NRVOUS等)能通过。代码没语法错误,但我找不到问题在哪,希望能得到帮助搞懂错误原因。
我的代码如下:
def main(): plate = input("Plate: ").upper() if is_valid(plate): print("Valid") else: print("Invalid") def is_valid(s): n = 0 flag = True # 检查长度 if len(s) < 2 or len(s) > 6: flag = False # 检查是否有标点符号(通过Unicode范围排除字母和数字) for i in s: if (ord(i) < 48) or (57 < ord(i) < 65) or (90 < ord(i)): flag = False # 检查前两个字符是否为字母 for i in s[0:2]: if ord(i) < ord("A"): flag = False # 检查数字后面是否有字母,以及第一个数字是否为0 for i in range(0, len(s)): while (ord(s[i]) < ord("A")) and (i < (len(s)-1)): n = n + 1 if ord(s[i+1]) > 57: flag = False # 检查第一个数字是否为0 if (48 <= ord(s[i]) <= 57) and (n == 1): if s[i] == 0: flag = False return flag main()
测试情况
- 失败用例:CS50、ECTO88、CS05、50、CS50P2、PI3.14
- 通过用例:NRVOUS、H、OUTATIME
问题分析与修正
你的代码核心问题是while循环导致死循环:当遇到数字时,while (ord(s[i]) < ord("A")) and (i < (len(s)-1))这个条件成立,但循环内部没有改变i的值,会一直停在同一个索引位置,无限循环下去,导致程序卡住无输出。
另外还有两个逻辑错误:
- 判断第一个数字是否为0时,
s[i] == 0是把字符和数字0比较,应该改成s[i] == '0'; - 检查数字后是否有字母的逻辑混乱,应该用一个状态标记是否已经出现过数字,一旦出现数字,后续所有字符都必须是数字。
下面是修正后的代码:
def main(): plate = input("Plate: ").upper() print("Valid" if is_valid(plate) else "Invalid") def is_valid(s): # 检查长度 if not (2 <= len(s) <= 6): return False # 检查前两个字符是否为字母 if not (s[0].isalpha() and s[1].isalpha()): return False # 标记是否已经出现数字 has_digit = False for i in range(len(s)): char = s[i] # 检查是否有非法字符(非字母非数字) if not (char.isalpha() or char.isdigit()): return False if char.isdigit(): has_digit = True # 第一个数字不能为0 if char == '0' and not any(c.isdigit() for c in s[:i]): return False else: # 如果已经出现过数字,后面不能再出现字母 if has_digit: return False return True main()
修正说明
- 提前返回:一旦发现不符合规则的情况,直接返回
False,避免不必要的循环,逻辑更清晰; - 使用字符串方法:用
isalpha()、isdigit()代替Unicode编码判断,代码更易读; - 状态标记
has_digit:跟踪是否已经出现过数字,一旦出现数字,后续字符必须全是数字; - 修复第一个数字为0的判断:检查当前数字是否是第一个出现的数字,且是否为'0';
- 移除死循环:去掉了导致无限循环的while逻辑,改用for循环遍历每个字符,结合状态标记实现规则检查。
内容的提问来源于stack exchange,提问作者Koh Cw
相关产品推荐
相关产品推荐

