简体   繁体   中英

Nested while loops not working as expected

Created a simple maths calc:

After user does their first calc they are asked 3 questions.

  1. Do more math with the final answer.
  2. Restart fresh
  3. Quit completely.

Used nest while loops to achieve this.

Picture below shows

  1. Success at doing a calc.
  2. User was then asked if they wanted to do more with the final answer. Answer was 'n'.
  3. They were then asked if they wanted to start fresh or quit completely. Answer was quit: 'n'.
  4. So program ended successfully.

Successful end to code

However on retest

  1. Calc successful.
  2. Do want to continue with final answer = no.
  3. Do you want to start fresh? = yes.
  4. Program restarts. Great!
  5. Calc successful.
  6. Do want to continue with final answer = no.
  7. Do you want to start fresh? = no.
  8. At this point the program should end (as it did above) BUT it continued as if the user in step 2 above had said 'yes'.

Keeps looping and it shouldn't

Cannot work out why. Tried using breakpoints to see what is happening but still too inexperienced on how to correctly used this tool. Used Thonny as well. Thonny shows that it acknowledges the 'break' command (so it should slip out of the while loop) however it then skips ahead to the next coded line and the calc continues.

enter code here
    more_calc = user_continue_check(data=math_question)

    if more_calc == 3:
        break

    elif more_calc == 2:
        main()

    print("Error checking: When do we get to here?")
    start_calc += 1

Is the problem in the nested while loops below? Just don't know. Been hacking away at this for hours. Using Thonny this nested loop works fine. It breaks out correctly returning the correct variable int result. So confused.

enter code here
     def user_continue_check(data):

         user_answer = False
         ans = True

         while not user_answer:

             more_calc = str(input("\n\tDo you want to do more math with the calculated result of "
                          + fg.orange + "{0}".format(data['result']) + fg.rs + "?" + fg.blue + " y/n: "
                          + fg.rs)).strip().lower()

             if more_calc == "n":
                final_check = True

                while final_check:

                   final_user_check = str(input("You you want to start a new calculation: y/n: ")).strip().lower()

                   if final_user_check == "n":
                        ans = 3
                        break
                   elif not final_user_check == "y":
                        print(fg.red + "\t\tYou need to enter y or n" + fg.rs)
                   else:
                        ans = 2
                        break
               break
    
             elif not more_calc == "y":
                print(fg.red + "\t\tYou need to enter y or n" + fg.rs)
             else:
                ans = 1
                break


         return ans

Below is a link to the whole script. I just don't know where to look for the answer. Cannot work out why it does work then doesn't.

enter link description here

The reason is because your break does indeed break all three loops, but you are using recursive calls on your main, so you are getting back to a lower recursive call of your main.

So to explain:

main => enter loop => enter main => enter loop => enter loop => enter loop => exit all three last loops => exit main

You are still in the first loop in the first main, which called the second main which you just terminated.

When a function calls itself using recursion, it is not terminated, once the inner call is finished, the function continues its execution right after the call.

But generally, I would work a little bit on improving the quality of the code first, you might find it easier to debug in the future, here are some suggestions:

  • Use explicit, non ambiguous names (no "ans" "fg" "final_check/final_user_check")
  • don't use break if it can be avoided (and it can here in most cases)
  • don't repeat code
  • don't reassign different types to your variable (ex: ans starts as True, but then becomes a number)
  • don't use recursion, it is almost never worth it. <= in this case this will fix the issue

That will be a decent start.

Your code does something extremely simple yet it's hard to understand and that is a bad sign. It's great that you are trying to incorporate all these concepts into it, but you need to keep your code tidy in order to be able to continue working on it, and understand the problems with it

@jeekiii has explained the problem, that you recurse into main in if more_calc == 2: , which does restart the calculation, but once the inner main exits, control returns to the outer main and just picks up where it left off (repeating the calculation). What you probably should do here is instead of calling main() there, just clear the state variables by doing:

if more_calc == 2:    
    num_used_list = []
    math_question = {}
    start_calc = 0

like you do at the top of main .

You already have a new_calc variable you check at the top of your loop so you can additionally avoid having to use break at all by just setting new_calc = False under if more_calc == 3: .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM