尝试验证输入时,“IndexError:字符串索引超出范围”

问题描述 投票:0回答:3

我正在尝试为学校模拟评估创建公牛和奶牛游戏,并且我遇到了这行代码的问题

def BullsAndCows():
Guess= input("Please enter a 4 digit number, remember no duplicates!")
Guess = str(Guess)
while len(Guess) != 4:
    Guess = input("IT has to be FOUR digits!")
    Guess = str(Guess)

while Guess[0] == Guess[1] or Guess[0] == Guess[2] or Guess[0] == Guess[3] or Guess[1] == Guess[2] or Guess[1] == Guess[3] or Guess[2] == Guess[3]:
    Guess = input("You can't use duplicates silly! Try another number!")
    Guess = str(Guess)`

问题是如果我输入一个带有重复的4位数字,我就不能再输入非4位数而不输出此错误

回溯(最近调用最后一次):文件“python”,第64行,在文件“python”,第57行,在BullsAndCows中IndexError:字符串索引超出范围

第57行是while Guess[0] == ......

第64行只是用于调用函数的BullsandCows()。有谁知道这个问题?

python exception input
3个回答
2
投票

当用户输入长度小于4的字符串时,会生成错误。在这种情况下,guess[3]将超出范围。


如果你想检查你的输入是否符合条件,我会推荐一个由条件终止的while

import re

guess = ''
while not (guess.isdigit() \
           and len(guess) == 4 \
           and not re.search(r'(\d).*\1', guess)):
    guess = input(...)

只要while条件仍然是False,循环继续运行。

  • guess.isdigit()是一个字符串函数,用于检查字符串是否为数字。例如: In [889]: '1234'.isdigit() Out[889]: True In [890]: '1234abc'.isdigit() Out[890]: False
  • 如果第一个条件是len(guess) == 44将检查字符串是否长度为True
  • 另外,为了防止重复,我强烈建议使用正则表达式。如果第一个和第二个条件是True,则re.search函数将应用正则表达式模式(如下所述)来搜索字符串中的重复项。如果存在重复,则返回匹配,评估为True。否则,返回None,这是False

只要这三个条件中的任何一个都是False,整个表达式就是False(由于or布尔逻辑如何工作)并且循环继续执行。


正则表达式细节

(\d)  # digit (capture group) 
.*    # match 0 or more chars
\1    # reference 1st capture group 

2
投票

你的错误的原因是,一旦你通过了4位数的测试,即使输入发生变化,你也不会再这样做了。因此,如果您先输入1111,它会通过第一次测试(while len(Guess) != 4),但不会通过第二次测试。如果你然后输入123,你会得到一个错误,因为输入只有3位数,而Guess[3]提出了一个IndexError

您应该重构代码以在同一位置包含输入的所有测试,并且只有一个while循环。像这样:

def BullsAndCows():
    Guess= input("Please enter a 4 digit number, remember no duplicates!")
    Guess = str(Guess)
    (correct, message) = check_input(Guess)
    while not correct:
        Guess = input(message)
        (correst, message) = check_input(Guess)

def check_input(guess):
    if not guess.isdigit():
        return (False, "Input a number")
    if len(guess) != 4:
        return (False, "The number should have 4 digits")
    if guess[0] == guess[1] or ...
        return (False, "No duplicates")
    #other tests if necessary
    return (True, "ok")

编辑:正如其他人所指出的那样,guess[0] == guess[1] or ...既麻烦又容易出错。最好用更通用的东西替换它,如果你在输入中有4个,5个...... n个数字,它们同样有效。 AK47的解决方案(len(set(guess)) != len(guess))适用于此。由于首次使用的用户的语法有点模糊,以下是它的工作原理:

  • set(guess)将输入转换为一组字符。一组只能有不同的元素,所以set('123') = set('1233212') = {'1', '2', '3'}
  • 如果len(set(guess)) == len(guess),这意味着guess中的所有角色也在集合中;因此所有字符都是不同的。

1
投票

您可以通过删除while循环并使用1来简化您的方法,这将使程序保持运行直到方法中断

您可以使用len()函数检查输入的值是否与4位数相匹配

您可以使用set()构造函数构建输出的集合,这将删除重复项,然后将集合的len()与原始输入的len()进行比较

def BullsAndCows():
    while True:
        guess = str(input("Please enter a 4 digit number, remember no duplicates:"))

        if len(guess) != 4:
            print("It has to be FOUR digits")
            continue

        if len(set(guess)) != len(guess):
            print("You cant enter duplicates silly! Try another number")
            continue

        print("No duplicates in number: {}".format(guess))
        break

BullsAndCows()

>> Please enter a 4 digit number, remember no duplicates:
> 123
>> It has to be FOUR digits
>> Please enter a 4 digit number, remember no duplicates:
> 1111
>> You cant enter duplicates silly! Try another number
>> Please enter a 4 digit number, remember no duplicates:
> 1234
>> No duplicates in number: 1234
© www.soinside.com 2019 - 2024. All rights reserved.