Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them, it only takes a minute:

I'm asking users a series of questions and recording their answers. My question-askers check the formatting of these answers and return a flag if a user inputs something strange (like my name is 102).

I'd like this program to break out of the question set if any of these answers are wrong, right away. I'm attempting to use a while loop to do this but it is clear to me that this while loop only checks the value of the flag at the end of each loop, so it won't restart the question asking process until the block of questions are done.

Note the `letter' variable is a surrogate for user input in this example. This is not how the code actually looks.

def string_checker(letter, output):
    if type(letter) != str:
        print('You did not give me a string!')
        output = 1

    return output

output = 0
# this should go until question 3, when the user makes a mistake
while output == 0:

    # question 1
    letter = 'bob'
    print(letter)
    output = string_checker(letter, output)

    # question 2
    letter = 'aldo'
    print(letter)
    output = string_checker(letter, output)

    # question 3 --- user gets this wrong
    letter = 1
    print(letter)
    output = string_checker(letter, output)

    # question 4
    letter = 'angry'
    print(letter)
    output = string_checker(letter, output)

# but it seems to ask question 4, regardless
print('done!')

Is there a way for me to modify this code so that question 4 is never asked?

UPDATED CODE BASED ON JASPER'S ANSWER

Building on Jasper's answer with a full solution... this modification to my problem solved it. By raising a ValueError inside of the checking function, the try block fails immediately and we can escape from main using a return.

def string_checker(letter):
    if type(letter) != str:
        raise ValueError

def main():
    # this should go until question 3, when the user makes a mistake
    try:

        # question 1
        letter = 'bob'
        print(letter)
        string_checker(letter)

        # question 2
        letter = 'aldo'
        print(letter)
        string_checker(letter)

        # question 3 --- user gets this wrong
        letter = 1
        print(letter)
        string_checker(letter)

        # question 4
        letter = 'angry'
        print(letter)
        string_checker(letter)

    # we make a mistake at question 3 and go straight to here
    except ValueError as ve:
        print('You did not give me a string!')
        return 'oops'

    # exit
    return 'done'
share|improve this question
    
possible duplicate of How to break out of multiple loops in Python? – heinst Jul 22 '14 at 15:36
    
Surely you should be using a loop that iterates over the list of letters, something more like: for letter in ['x', 'y', 1, 'z']: print(letter); x = string_checker(letter, x); if x != 0: break (spread over multiple lines, indented properly, and without any semicolons). Seeing almost the same block of code repeated 4 times like that should give you the shivers — or make your nose twitch at the code smell. (There still may be better ways to code that, but it would be a simple step up.) – Jonathan Leffler Jul 22 '14 at 15:36
    
Yes, I do not like this repetition either. However for me to have all of the 'letters' in that list, I would have already had to ask the set of questions, so my user still isn't spared the wasted time if they make a mistake along the way. – jdv Jul 22 '14 at 15:40
    
Do you ever intend to actually loop over the questions? If not, you should throw an exception when a "wrong" answer is given. – Jasper Jul 22 '14 at 15:42
    
So it seems like while loops just don't do what I want them to at all. Raising exceptions doesn't work very nicely, as it breaks the flow of things and forces the user to start over. Imagine this is a small chunk of a 100 question set split into little modules, and if they make an error I just want them to have to repeat a single module. – jdv Jul 22 '14 at 15:49

3 Answers 3

up vote 0 down vote accepted

While this does not answer the question title, I think a loop is the wrong design choice (assuming you are not going to ask the same questions multiple times). Instead, you could raise exceptions:

try:
  # ask question

  if not string_checker(...):
    raise ValueError

  # ask next question

except ValueError as ve:
  print("wrong answer")
share|improve this answer
    
Thanks for the implementation, this works perfectly! I'll edit my answer with the solution. – jdv Jul 22 '14 at 15:55

You can check if the result of string_checker is 1 after each question:

if output == 1:
    break

The break statement will exit the loop immediately.

By doing this, you won't need to have that condition in the while, so you can do an infinite while:

while True:
    ...
share|improve this answer
    
This is a decent solution, but only exacerbates Jonathan Leffler's (and my own) concern of having a large amount of repeated code. – jdv Jul 22 '14 at 15:51
# question 3 --- user gets this wrong
letter = 1
print(letter)
output = string_checker(letter, output)

# Add this to your code:

if output == 1:
    break

The break jumps out of the while loop completely, and you're good to go. The only problem is, the computer will still

print('done!')

So maybe you want to include an error code or something of the like.

Maybe something like?

if output == 1:
    print "You have given an invalid input"
    break

EDIT:

I realized it would print "You have given an invalid input" and then print "Done!"

So instead, you should have the program stop running with the invalid input:

if output == 1:
    print "You have given an invalid input"
    return

The return statement will stop the program completely.

share|improve this answer
    
wow it took you 7 minutes to copy Christian's answer! – John Ruddell Jul 22 '14 at 15:41
    
Lol relax. I didn't see his answer as I was typing mine up. – Mburdzy Jul 22 '14 at 15:42
    
No problem. you should delete your answer though as it is a copy and some people will downvote it as such :) – John Ruddell Jul 22 '14 at 15:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.