1

I have an assignment for my programming fundamentals class. In this, I have to accept invalid inputs a certain number of times (in this case, five) before the program terminates. The book doesn't seem to explain limiting number of loop runs in this context, so I've included my code for guidance. As written, it continues to loop and doesn't stop.

max = 5
#Input miles to be converted
miles = float(input('Enter the number of miles to convert to kilometers: '))
milesToKms = miles*1.6 #miles to kilometers formula
for counter in range(max):
    if miles >= 0:
        print ('Miles converted: ', miles)
        print ('Kilometers: ', milesToKms) #display kilometers result
        break
    elif miles <0:
        while miles < 0:
            print ('Invalid value entered.')
            miles = float(input('Enter a valid number of miles to convert: '))
else:
    print ('Too many invalid entries submitted.')
    exit ()              
martineau
  • 119,623
  • 25
  • 170
  • 301
  • What's wrong with it? – Mad Physicist Oct 03 '18 at 18:56
  • 1
    Could you fix the indentation please? It's difficult to tell where everything is in relation to the loop – Patrick Haugh Oct 03 '18 at 18:57
  • It continues the loop and doesn't end when it's meant to. – A Weingartner Oct 03 '18 at 18:58
  • Indentation has now been fixed. – A Weingartner Oct 03 '18 at 19:00
  • also : tha name `max` is already used by the function `max` ... if you introduce a variable of the same name you shadow this function - bad idea. dont name things : `min,max,range,list,tuple,dict,set,len,abs,...` etc (see https://docs.python.org/3/library/functions.html ) – Patrick Artner Oct 03 '18 at 19:06
  • 1
    Just in case you did not yet read that: [asking-the-user-for-input-until-they-give-a-valid-response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) has plenty of cool answers regarding input validation (what essentially is what you are doing here) – Patrick Artner Oct 03 '18 at 19:26
  • I had not found that one in my search. Thank you for the resource! – A Weingartner Oct 03 '18 at 19:28

3 Answers3

2

You don't need or want the while loop here. Your outer for loop limits the number of attempts on its own, and rechecks the condition on each loop, so it does the job all by itself.

I've cleaned it up a bit to remove redundant input code, which also provides the side-benefit of avoiding prompting for input after the final attempt failed, when the loop would stop anyway:

import sys

max = 5
for counter in range(max):
    # Input miles to be converted
    miles = float(input('Enter the number of miles to convert to kilometers:'))
    if miles >= 0:
        # May as well defer calculation of milesToKms until we know
        # the miles value is valid
        milesToKms = miles * 1.6 # miles to kilometers formula
        print('Miles converted:', miles)
        print('Kilometers:', milesToKms) #display kilometers result
        break
    else:  # No need for elif miles < 0; anything not valid is invalid
        print('Invalid value entered.')
else:
    # sys.exit is correct way to exit program, and it can output error for you
    sys.exit('Too many invalid entries submitted.')
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • @PatrickArtner: So you're just saying it should use `range(max + 1)`? I mean, if the goal is no more than five invalid inputs, this allows five attempts, and if all five are invalid, it exits, so I'm not sure what the problem is? `range(max + 1)` would allow six invalid inputs. – ShadowRanger Oct 03 '18 at 19:13
  • This seems to have worked perfectly. ShadowRanger is right, I don't want it to accept more than five entries, which it is performing perfectly now. – A Weingartner Oct 03 '18 at 19:16
  • This is only one part of the full code. After a valid input is entered it goes on to the next conversion. Running it through, it seems to be functioning well still (maybe it helps that there are only five conversions being made?). – A Weingartner Oct 03 '18 at 19:24
0

Solution to keep calculating until 5 wrong inputs are given:

import sys

invalids = 0
maxWrongInputs = 5

# loop until too many wrongs were done
while invalids < maxWrongInputs:
    miles = float(input('Enter the number of miles to convert to kilometers:'))
    if miles >= 0:
        milesToKms = miles * 1.6 
        print('Miles converted:', miles)
        print('Kilometers:', milesToKms) 
    else:  
        # add another to your counter of invalid attempts
        invalids += 1
        print('Invalid value entered.')
else:
    sys.exit('Exited after {} invalid entries.'.format(invalids))

Input: 3. 4. 5. 6. 7. 8. -1. -1. -1. 4. -1. -1.

Output:

Enter the number of miles to convert to kilometers:3
Miles converted: 3.0
Kilometers: 4.800000000000001
Enter the number of miles to convert to kilometers:4
Miles converted: 4.0
Kilometers: 6.4
Enter the number of miles to convert to kilometers:5
Miles converted: 5.0
Kilometers: 8.0
Enter the number of miles to convert to kilometers:6
Miles converted: 6.0
Kilometers: 9.600000000000001
Enter the number of miles to convert to kilometers:7
Miles converted: 7.0
Kilometers: 11.200000000000001
Enter the number of miles to convert to kilometers:8
Miles converted: 8.0
Kilometers: 12.8
Enter the number of miles to convert to kilometers:-1    # 1.
Invalid value entered.
Enter the number of miles to convert to kilometers:-1    # 2.
Invalid value entered.
Enter the number of miles to convert to kilometers:-1    # 3.
Invalid value entered.
Enter the number of miles to convert to kilometers:4
Miles converted: 4.0
Kilometers: 6.4
Enter the number of miles to convert to kilometers:-1    # 4.
Invalid value entered.
Enter the number of miles to convert to kilometers:-1    # 5.
Invalid value entered.
Exited after 5 invalid entries.
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • 1
    I don't get the impression that the OP needs to *keep* converting until they have five invalid inputs. The clear intent is to perform a *single* conversion, allowing up to five attempts to provide a valid value if an invalid input is provided, but ending immediately if a valid input is provided and converted. – ShadowRanger Oct 03 '18 at 19:22
  • @ShadowRanger that makes sense as well. – Patrick Artner Oct 03 '18 at 19:24
-1

your inner while loop is causing the issue:

max = 5
#Input miles to be converted
for counter in range(max):
    miles = float(input('Enter the number of miles to convert to kilometers: '))
    milesToKms = miles*1.6 #miles to kilometers formula
    if miles >= 0:
        print ('Miles converted: ', miles)
        print ('Kilometers: ', milesToKms) #display kilometers result
        break
    elif miles <0:
        print ('Invalid value entered.')

if counter == (max - 1):
    print ('Too many invalid entries submitted.')
    exit ()

Valid output:

Enter the number of miles to convert to kilometers: 10
('Miles converted: ', 10.0)
('Kilometers: ', 16.0)

Invalid output:

Enter the number of miles to convert to kilometers: -1
Invalid value entered.
Enter the number of miles to convert to kilometers: -2
Invalid value entered.
Enter the number of miles to convert to kilometers: -3
Invalid value entered.
Enter the number of miles to convert to kilometers: -4
Invalid value entered.
Enter the number of miles to convert to kilometers: -5
Invalid value entered.
Too many invalid entries submitted.
user3713719
  • 325
  • 3
  • 8
  • The `else` condition on the `for` loop wasn't a mistake; replacing it with `if counter == (max - 1):` isn't necessary (and very mildly slows the code). `for` loops can have associated `else` blocks that only execute if the `for` loop is exited by running to completion without `break`ing, `return`ing, or raising an exception. – ShadowRanger Oct 03 '18 at 19:14
  • Thanks for that info. I didn't know that. – user3713719 Oct 03 '18 at 19:22