Попытка настроить вложенные циклы while с помощью логического переключателя - PullRequest
1 голос
/ 07 апреля 2010

Я пытаюсь настроить цикл while, который будет запрашивать у пользователя имя сотрудника, отработанные часы и почасовую оплату, пока пользователь не введет «ВЫПОЛНЕНО».Со временем я изменю код для подсчета еженедельной оплаты и запишу его в список, но по одной вещи за раз.Проблема в том, что когда основной цикл while выполняется один раз, он просто останавливается.Не выдает ошибку, а просто останавливается.Я должен убить программу, чтобы остановить ее.Я хочу, чтобы он задавал три вопроса снова и снова, пока пользователь не закончил.Мысли?

Обратите внимание, что это просто упражнение, и оно не предназначено для применения в реальном мире.

def getName(): 
    """Asks for the employee's full name"""
    firstName=raw_input("\nWhat is your first name? ")
    lastName=raw_input("\nWhat is your last name? ")
    fullName=firstName.title() + " " + lastName.title()
    return fullName

def getHours():
    """Asks for the number of hours the employee worked"""
    hoursWorked=0 
    while int(hoursWorked)<1 or int(hoursWorked) > 60: 
        hoursWorked=raw_input("\nHow many hours did the employee work: ")
        if int(hoursWorked)<1 or int(hoursWorked) > 60:
            print "Please enter an integer between 1 and 60."
        else:
            return hoursWorked

def getWage():
    """Asks for the employee's hourly wage"""
    wage=0 
    while float(wage)<6.00 or float(wage)>20.00: 
        wage=raw_input("\nWhat is the employee's hourly wage: ")
        if float(wage)<6.00 or float(wage)>20.00:
            print ("Please enter an hourly wage between $6.00 and $20.00")
        else:
            return wage


##sentry variables
employeeName=""
employeeHours=0
employeeWage=0
booleanDone=False

#Enter employee info
print "Please enter payroll information for an employee or enter 'DONE' to quit."

while booleanDone==False:
    while employeeName=="":
        employeeName=getName() 
        if employeeName.lower()=="done":
            booleanDone=True
            break
        print "The employee's name is", employeeName

    while employeeHours==0:
        employeeHours=getHours() 
        if employeeHours.lower()=="done":
            booleanDone=True
            break
        print employeeName, "worked", employeeHours, "this week."

    while employeeWage==0:
        employeeWage=getWage() 
        if employeeWage.lower()=="done":
            booleanDone=True
            break
        print employeeName + "'s hourly wage is $" + employeeWage

Ответы [ 2 ]

3 голосов
/ 07 апреля 2010

Проблема в том, что после первого цикла, employeeName и другие переменные уже будут иметь значения, поэтому ваши внутренние циклы while будут пропущены. Это приводит к тому, что внешний цикл повторяется бесконечно, ничего не делая.

Я бы просто удалил внутренние циклы while: они вам на самом деле не нужны, потому что вы уже выполняете проверку внутри getHours и других функций. Другой вариант - сбросить значения переменных в начале внешнего цикла while.

Еще некоторые улучшения (не связанные с этой ошибкой):

  • В getHours и getWage вы можете просто использовать while True вместо того состояния, которое у вас есть сейчас. Если условие ложно, вы все равно вернулись бы из функции.

  • Вам нужно поймать ValueError в getHours и getWage, если были введены нечисловые данные.

  • вместо booleanDone==False, используйте not booleanDone. Хотя, если вы удалите внутренние циклы, как я предложил, вам даже не нужен этот логический тип: просто вырвитесь из цикла при необходимости.

1 голос
/ 07 апреля 2010

getHours и getWage предполагают, что входные данные соответственно в формате int и float. Таким образом, проверки для ...lower()=="done" никогда не могут быть выполнены: если бы пользователь ввел done в приглашении в любой из этих функций, программа умерла бы с исключением ValueError. Но это другая ошибка.

В конце первого отрезка внешнего цикла мы знаем, что ни одна из трех строк не пуста (это гарантируют внутренние циклы). Затем эти строки не сбрасываются - поэтому они все еще не пусты - поэтому на каждом последующем участке внешнего цикла ни один из внутренних циклов никогда не будет выполнен снова. Это должно вызывать бесконечное быстрое пустое зацикливание в отличие от чистого выхода (т.е. неясно, почему симптомы очевидной ошибки, которую я только что описал, отличаются от ваших наблюдений), поэтому могут быть и другие ошибки, но когда их легко обнаружить убийственная ошибка в этом маленьком куске кода, я думаю, что разумнее перестать копать (какой смысл замечать еще нескольких? -).

Вы должны скорее реорганизовать структуру, сделав роль функций предельно ясной и точной: что именно возвращают эти функции? Если строки, каковы ограничения на эти строки? Кажется, они примерно возвращают «допустимую строку для этой записи» (за исключением возможности убить всю программу, если у пользователя есть опечатка в заработной плате или часах, чего можно избежать с помощью try / except ) - первый и только этот может вернуть done (но тогда он должен четко указать это в своем запросе и избегать второго бесполезного запроса, если пользователи говорят done первому приглашению). Как только вы документируете их как таковые, становится ясно, что внутренние циклы while неоправданны; внешний цикл может быть просто

while True:
    employeeName=getName() 
    if employeeName.lower()=="done":
        break
    print "The employee's name is", employeeName

    employeeHours=getHours() 
    print employeeName, "worked", employeeHours, "this week."

    employeeWage=getWage() 
    print employeeName + "'s hourly wage is $" + employeeWage
...