【问题标题】:Unable to break infinite loop无法打破无限循环
【发布时间】:2018-03-06 15:40:21
【问题描述】:

这里有各种与无限循环相关的帖子,但没有一个反映我的特殊困境(它们处理 Java,或者它们与我的代码格式不匹配等)。我使用的代码实际上是针对像我这样的新学生的练习的源代码或“答案代码”,它只提供“没有正确格式的正确代码”,这对于独立的学生来说可能会使事情复杂化,但也提供了更高效挑战。

代码充分利用了“函数”和“从其他函数中调用函数”,因此几乎没有留下“全局代码”,这可能会使事情稍微复杂一些,但希望有经验的程序员不会被这个。

我认为循环是我的“while 循环代码缩进”或“while 循环条件/计数器代码本身”的问题。循环代码从程序代码的其他部分获取并使用数据,不应完全排除,但实际上我怀疑问题是缩进或内部循环代码本身的前两个可能问题之一,我已经尝试了多个“缩进布局”的变体以及快速修复(错误输入的语法等)。

有问题的代码可以在程序代码的末尾找到(程序代码中只有一个“while 循环”)它位于代码的“菜单选项”部分中的“#循环通过引号选择那些引用适当的月份并将数据存储在摘要字典中。

我已经包含了两个单独的代码窗口,一个突出显示可疑的“问题代码”,另一个突出显示“完整程序代码”。任何方面的帮助将不胜感激。

最有可能出错的代码段

def monthlyReport():
    file = open(QUOTES_TO_DATE_FILE, 'r')

    text = file.read()

    file.close()

    quotes = text.split()

    month = input('Enter month: ')

    summary = {'Lawn':{'Quantity' : 0.0, 'Value' : 0.0}, 'Patio' :{'Quantity' : 0.0, 'Value' : 0.0}, 'Water Feature' :{'Quantity' : 0.0, 'Value' : 0.0}}
# Loop through quotes selecting those referencing the appropriate month and
#store the data in summary dictionary
    index = 0

    while True:

    if quotes[index] == month:

            inputQuotesFromFile2(quotes[index+1])    

            summary['Lawn']['Quantity'] = summary['Lawn']['Quantity'] + quote['Lawn']['Width'] * quote['Lawn']['Length']

            summary['Lawn']['Value'] = summary['Lawn']['Value'] + quote ['Lawn']['Cost']

            summary['Patio']['Quantity'] = summary['Patio']['Quantity'] + quote['Patio']['Width'] * quote['Patio']['Length']

            summary['Patio']['Value'] = summary['Patio']['Value'] + quote['Patio']['Cost']

            summary['Water Feature']['Quantity'] = summary['Water Feature']['Quantity'] + quote['Water Feature']['Quantity']

            summary['Water Feature']['Value'] = summary['Water Feature']['Value'] + quote['Water Feature']['Cost']

            index = index + 2

        if (index >= len(quotes)):

            break

        totalValue = summary['Lawn']['Value'] + summary['Patio']['Value'] + summary['Water Feature']['Value']

        outputSummaryDictionary(summary, month, totalValue)

完整的程序代码

# `Dictionary containing time values (mins) per square metre/ per feature
##lawn:20   patio:20  water feature:60
TIME = {'Lawn': 20, 'Patio': 20, 'Water Feature': 60}

# Constant for labour cost
##16.49
LABOUR_COST = 16.49

# Variable for filename of list of quotes made to date
##quotesToDateFile
QUOTES_TO_DATE_FILE = 'quotesToDateFile.txt'



# 'Global variables'

# A dictionary that stores quote data temporarily, contains sub dicts for each
#material type including keys for length, width, cost, time/quantity,cost, time
quote = {'Lawn':{'Length': 0 , 'Width': 0 , 'Cost': 0.0 , 'Time': 0.0},
         'Patio':{'Length': 0 , 'Width': 0, 'Cost': 0.0 , 'Time': 0.0 },
         'Water Feature':{'Quantity': 0 , 'Cost': 0.0 , 'Time': 0.0}}

# A dictionary storing material costs of individual items (can be updated)
materialCost = {'Lawn': 15.5, 'Patio': 20.99, 'Water Feature': 150}


# 'Input'

# Function to input material info defined by a length
##create function with named parameter for 'item'
def inputItemDimensions(item):

    s = 'Enter length of ' + item + ':'

    length = int(input('Enter length of material: '))

    s = 'Enter width of ' + item + ':'

    width = int(input('Enter width of material: '))

    return length, width

# Function to input material info defined by quantity
##create function with named parameter 'item
def inputItemQuantity(item):

    s = 'Enter quantity of ' + item + ':'

    quantity = int(input('Enter quantity of items: '))

    return quantity

# Function for input of area and quantity
def itemInput():

    global quote

    quote['Lawn']['Length'], quote['Lawn']['Width'] = inputItemDimensions('lawn')

    quote['Patio']['Length'], quote['Patio']['Width'] = inputItemDimensions('concrete patio')

    quote['Water Feature']['Quantity'] = inputItemQuantity('water feature')



# 'Cost calculation'

# Function to calculate, output to screen, return the material cost and time
#to install a landscape item installed by length and width
def costCalculation1(num, item, length, width, cost, time):

    print('[{0}]'.format(num))

    print('Length and width of the {0} = {1} x {2}m'.format(item, length, width))

    area = length * width

    print('Total area of {0} = {1:.2f}m^2'.format(item, area))


    print('Cost of {0} per m^2 = £{1:.2f}'.format(item, cost)) 


    totalCost = area * cost 

    print('Total cost of {0} = £{1}\n'.format(item, totalCost))

    totalTime = area * time

    return totalCost, totalTime

# Function to calculate, output to screen and return the material cost and time
#to install a landscape item installed by quantity
def costCalculation2(num, item, quantity, cost, time):

    print('[{0}]'.format(num))

    print('Quantity of {0} = {1} items'.format(item, quantity))

    print('Cost of one {0} = £{1:.2f}'.format(item, cost))

    totalCost = quantity * cost 

    print("Total cost of {0} {1} = £{2}\n".format(quantity, item, totalCost))

    totalTime = quantity * time

    return totalCost, totalTime

# Function to calculate individual costs of items
def calculateItemCosts():

    global quote

    quote['Lawn']['Cost'], quote['Lawn']['Time'] = costCalculation1('1', 'lawn', quote['Lawn']['Length'], quote['Lawn']['Width'], materialCost['Lawn'], TIME['Lawn'])

    quote['Patio']['Cost'], quote['Patio']['Time'] = costCalculation1('2', 'patio', quote['Patio']['Length'], quote['Patio']['Width'], materialCost['Patio'], TIME['Patio'])

    quote['Water Feature']['Cost'], quote['Water Feature']['Time'] = costCalculation2('3', 'water features', quote['Water Feature']['Quantity'], materialCost['Water Feature'], TIME['Water Feature'])


# Function to calculate workimg costs and output them
def workingCost():

    print('Working costs:')

    totalTime = (quote['Lawn']['Time'] + quote['Patio']['Time'] + quote['Water Feature']['Time']) / 60

    labourCost = totalTime * LABOUR_COST

    print('Total time to complete work = {0} mins'.format(totalTime))

    print('Cost of work per hour = £{0}'.format(LABOUR_COST)) 

    print('Total cost of work = £{0}\n'.format(labourCost))

# Calculate total fee payable by customer, output to screen and file
    materialCost = quote['Lawn']['Cost'] + quote['Patio']['Cost'] + quote['Water Feature']['Cost']

    totalCost = materialCost + labourCost

    print('Total cost to pay = £{0}\n'.format(totalCost))


# 'Output functions'

# Output details concerning item
def outputItems():

    outputItems1('1', 'Lawn', quote['Lawn'])

    outputItems1('2', 'Patio', quote['Patio'])

    outputItems2('3', 'Water Feature', quote['Water Feature'])


# Output dimensions and cost for certain item

def outputItems1(num, item, itemDict):

    print('[{0}]'.format(num))

    print('Length of width of {0} = {1}m x {2}m'.format(item, itemDict['Length'], itemDict['Width']))

    print('Total cost of {0} = £{1}'.format(item, itemDict['Cost']))

    print('Time to install {0} = {1}mins\n'.format(item, itemDict['Time'] / 60))

# Output quantity and cost for item

def outputItems2(num, item, itemDict):

    print('[{0}]'.format(num))

    print('Quantity of {0} = {1} items'.format(item, itemDict['Quantity']))

    print('Cost of one {0} = £{1:.2f}'.format(item, itemDict['Cost']))

    print('Time to install {0} = {1:.2f} hours\n'.format(item, itemDict['Time'] / 60))

# Output material cost dictionary
def outputMaterialCostDictionary():

    for key, value in materialCost.items():

        print('{0} = {1}'.format(key, value))

        print('\n')

# Output summary dictionary
def outputSummaryDictionary(summaryD, month, totalV):

    outputSummaryItem1(['Month', month, '', '', ''])

    outputSummaryItem1(['Total', '', 'Total', 'Total', 'Total'])

    outputSummaryItem1(['Working', 'Item', 'Square metre', 'Number', 'Monthly'])

    outputSummaryItem1(['Costs', '', 'Purchased', 'Purchased', 'Value'])  

    outputSummaryItem2('Lawn', summaryD['Lawn'])

    outputSummaryItem2('Patio', summaryD['Patio'])

    outputSummaryItem3('Water Feature', summaryD['Water Feature'])

    outputSummaryItem4(totalV)

# Output summary dictionary item ver 1
def outputSummaryItem1(sList):
    print('|{0:^13}|{1:^13}|{2:^13}|{3:^13}|{4:^13}|'.format(sList[0], sList[1], sList[2], sList[3], sList[4]))

# Output summary dictionary item ver 2
def outputSummaryItem2(name, item):
    print('|{0:^13}|{1:^13}|{2:13.2f}|{3:^13}|{4:13.2f}|'.format('', name, item['Quantity'], '', item['Value']))

# Output summary dictionary item ver 3
def outputSummaryItem3(name, item):
    print('|{0:^13}|{1:^13}|{2:^13}|{3:13.0f}|{4:13.2f}|'.format('', name, '', item['Quantity'], item['Value']))

# Output summary dictionary item ver 4
def outputSummaryItem4(totalValue):
    print('|{0:^13}|{1:^13}|{2:^13}|{3:^13}|{4:13.2f}|'.format('Total', '', '', '', totalValue))




# 'File handling'

# Function to output file
def outputToFile():

    filename = input('Enter file name: ')

    file = open(filename, 'w')

    month = input('Enter month:' )

    print('Filename = {0}....Month = {1}\n'.format(filename, month))

    file.write('{0}\n'.format(month))

    s = '{0} {1} {2} {3}\n'.format(quote['Lawn']['Length'], quote['Lawn']['Width'], quote['Lawn']['Cost'], quote['Lawn']['Time'])
    file.write(s)
    s = '{0} {1} {2} {3}\n'.format(quote['Patio']['Length'], quote['Patio']['Width'], quote['Patio']['Cost'], quote['Patio']['Time'])
    file.write(s)
    s = '{0} {1} {2}\n'.format(quote['Water Feature']['Quantity'], quote['Water Feature']['Cost'], quote['Water Feature']['Time'])
    file.write(s)
    file.close()


# Update quotes to date file 
    file = open(QUOTES_TO_DATE_FILE, 'a')


    s = '{0} {1}\n'.format(month, filename)

    file.write(s)
    file.close()

# Function to input quote from file where file name is not known
def inputQuoteFromFile1():

    filename = input('Enter name for input file: ')

    inputQuoteFromFile2(filename)


# Function to input quote from file when file IS known
def inputQuoteFromFile2(filename):

    file = open(filename, 'r')

    text = file.read()

    list1 = text.split()

    file.close()

# Process the data (ignore first item which is the month)
##declare 'quote' dict as global (this might mean this code is within function)
    global quote

    subDictionary = {'Length' : float(list1[1]), 'Width' : float(list1[2]), 'Cost' : float(list1[3]), 'Time' : float(list1[4])}

    quote['Lawn'] = subDictionary

    subDictionary = {'Length' : float(list1[5]), 'Width' : float(list1[6]), 'Cost' : float(list1[7]), 'Time' : float(list1[8])}

    quote['Patio'] = subDictionary

    subDictionary = {'Quantity' : float(list1[9]), 'Cost' : float(list1[10]), 'Time' : float(list1[11])}

    quote['Water Feature'] = subDictionary

    file.close()



# 'Menu options'

# Function to allow preperation of a new quote
def prepareANewQuote():
    itemInput()

    calculateItemCosts()

    workingCost()

    outputToFile()

# Function to load new material costs
def loadNewMaterialCosts():
    filename = input('Enter filename: ')

    file = open(filename, 'r')

    text = file.read()

    file.close()

    newMaterialCosts = text.split()

# Assign costs to material cost dictionary
    index = 0

    for key in materialCost.keys():

        materialCost['Key'] = float(newMaterialCosts['index'])

        index = index + 1

# Output new material costs # NOTE MAY NEED TO BE INDENTED FURTHER
    outputMaterialCostDictionary()
# Function to view and load existing quote
def viewExistingQuote():
    inputQuoteFromFile1()

    outputItems()

    workingCost()
# Function to generate monthly report summary
def monthlyReport():
    file = open(QUOTES_TO_DATE_FILE, 'r')

    text = file.read()

    file.close()

    quotes = text.split()

    month = input('Enter month: ')

    summary = {'Lawn':{'Quantity' : 0.0, 'Value' : 0.0}, 'Patio' :{'Quantity' : 0.0, 'Value' : 0.0}, 'Water Feature' :{'Quantity' : 0.0, 'Value' : 0.0}}
# Loop through quotes selecting those referencing the appropriate month and
#store the data in summary dictionary
    index = 0

    while True:

        if quotes[index] == month:

            inputQuotesFromFile2(quotes[index+1])    

            summary['Lawn']['Quantity'] = summary['Lawn']['Quantity'] + quote['Lawn']['Width'] * quote['Lawn']['Length']

            summary['Lawn']['Value'] = summary['Lawn']['Value'] + quote ['Lawn']['Cost']

            summary['Patio']['Quantity'] = summary['Patio']['Quantity'] + quote['Patio']['Width'] * quote['Patio']['Length']

            summary['Patio']['Value'] = summary['Patio']['Value'] + quote['Patio']['Cost']

            summary['Water Feature']['Quantity'] = summary['Water Feature']['Quantity'] + quote['Water Feature']['Quantity']

            summary['Water Feature']['Value'] = summary['Water Feature']['Value'] + quote['Water Feature']['Cost']

            index = index + 2

        if (index >= len(quotes)):

            break

        totalValue = summary['Lawn']['Value'] + summary['Patio']['Value'] + summary['Water Feature']['Value']

        outputSummaryDictionary(summary, month, totalValue)         



# 'Main' (initialisation)

# Top level function
def start():
    while True :

        print('Select one of following options')

        print('(1) Prepare new quote')

        print('(2) Load new cost data')

        print('(3) Load and view existing quote')

        print('(4) Generate monthly report summary')

        print('(5) Exit')

        selection = int(input())

        if selection == 1:

            prepareANewQuote()

        elif selection == 2:

            loadNewMaterialCosts()

        elif selection == 3:

            viewExistingQuote()

        elif selection == 4:

            monthlyReport()

        elif selection == 5:

            quit()

        else:

            print('Error unrecognised command')

# Start
start()

【问题讨论】:

  • 使用 return 而不是 quit()?
  • 请仅发布相关代码。另外,究竟是什么不起作用?
  • 我看到了 2 个 while 循环。能具体一点吗?
  • 请不要添加长代码示例,人类真的很懒惰,不想阅读太多,限制你的代码准确描述问题,仅此而已。在不降低质量和清晰度的情况下,尽可能保持简洁。
  • 对代码长度和“while 循环信息”表示歉意,确实有两个循环,我指的是第一个循环(我在位置描述中包含了上面的“标题注释” )我在标题“无法打破无限循环”中定义了我的问题,但将来我将在我的描述中包含参考,以便更容易理解,我还将提供一个单独的“代码窗口”突出显示代码(最有可能在至少)需要修复的代码,我包含了完整的代码,因为有时问题实际上可以归结为程序的一个单独部分。

标签: python python-3.x while-loop infinite-loop break


【解决方案1】:

如果quotes[index] 不等于month,则index 永远不会被修改,因此代码将一遍又一遍地检查相同的值并且永远不会继续。

您应该将index 的分配取消一级。但实际上,这不是一个适当的 while 循环使用;你应该使用for 来迭代quotes

for quote in quotes:

(还要注意这段代码中有两个while循环;实际上过多地使用了全局。)

【讨论】:

    猜你喜欢
    • 2013-03-08
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    相关资源
    最近更新 更多