5.6 — Do while statements

One interesting thing about the while loop is that if the loop condition is initially false, the while loop will not execute at all. It is sometimes the case that we know we want a loop to execute at least once, such as when displaying a menu. To help facilitate this, C++ offers the do-while loop:

while (condition);

The statement in a do-while loop always executes at least once. After the statement has been executed, the do-while loop checks the condition. If the condition is true, the path of execution jumps back to the top of the do-while loop and executes it again.

Here is an example of using a do-while loop to display a menu to the user and wait for the user to make a valid choice:

One interesting thing about the above example is that the selection variable must be declared outside of the do block. Why do you think that is?

If the selection variable were to be declared inside the do block, it would be destroyed when the do block terminates, which happens before the while conditional is executed. But we need the variable to use in the while conditional -- consequently, the selection variable must be declared outside the do block.

Generally it is good form to use a do-while loop instead of a while loop when you intentionally want the loop to execute at least once, as it makes this assumption explicit -- however, it’s not that big of a deal either way.

5.7 -- For statements
5.5 -- While statements

93 comments to 5.6 — Do while statements

  • giang

    Here is the code I think should be used to ask whether user want to play again:

    But when I ran this, it just kept printing "Want to play more??? _ press y/n: " and let me input a char again and again. So instead, I tried:

    And this worked as I expected, but can anybody explain where I went wrong in the first code?? Thank u so much

    • nascardriver

      The while-loops stops if the condition is false. But your condition can never be false. `play` would have to have all values at once to make your condition be false, that's impossible.

  • james

    can someone tell me why the menu is repeating twice after the answer is showing?, it should show the menu again after the answer is calculated?

    • When you enter

      Where <enter> is you pressing the enter key, the input stream stores

      Where '\n' in a line feed. When you call `scanf("%c", &ch)`, you're asking for one character to be extracted. `ch` is set to 'x', the input stream still holds

      The next time you call `scanf("%c", &menu_option)`, that \n is still there and gets stored in `menu_option`.
      If you want the first call to remove the '\n', you can add it to the format string.

      I don't know C so I can't tell if this has any side effects, but it seems to work from my tests.

    • Bombi Barlsson

      I'm not very proficient at C++, but from what I can tell

      works as a solution. I believe ignore() was mentioned in a previous tutorial. Clear removes the error flag for cin in case there's an invalid input type, while ignore ignores any character in the next 32767 characters until the next line. It's a type of flushing mechanism, and I tend to use it for my inputs for this tutorial but I have no idea if it's proper form.

    • JackTheHopper

      Put the break at the end of each case not outside, because the break you are using is causing the while loop to halt. :(

  • Benur21

    Wouldn't a normal while work as good as this one?
    Like this:

    Another question: Why when I input a letter for the selection, like "r", it will loop forever?

    • You're accessing an uninitialized variable in line 8 and 9, this causes undefined behavior.
      You want the first cycle of the loop to be unconditional, so use a do-while-loop.

      > Why when I input a letter for the selection, like "r", it will loop forever?
      'r' cannot be extracted into an `int`. Extraction fails, the stream enters a failed state and all further operations on it are ignored. This is covered later in this chapter.

  • Parsa

    Why isn't this working?
    (I enter -1 as input but it doesn't go back to the do loop.

  • Anastasia

    Hi! First I would like to thank Alex and nascardriver for the wonderful work you are doing, it's the best structured and comprehensive C++ course I've ever seen. Now, I'm a C++ beginner and I wrote a little counting coins programm summarizing the latest concepts I've learned. Could somebody review it for me, please? I have some doubts about whether I've handled certain aspects correctly (or at least at an acceptable level) in particular the exit of the selection choices, the default case of the switch (what would be the best way to end the execution there?) and whether it's acceptable to create a new struct every time the while statement executes (in the printSum() function). Thank you!

    • Hi!

      - Initialize your variables with brace initializers.
      - Line 23-30 and 40-70 should use the indexes of `Coin_type`.
      - Line 35, 36: `return {};`.
      - Line 43, 49, 55... are all the same, move them out of the switch.
      - Create a coin before the switch-statement, assign to it inside the switch, return after the switch.
      - Use single quotation marks for characters.
      - Line 93 causes undefined behavior, `sum` is uninitialized.
      - Use double literals for doubles (100.0 instead of 100).
      - Inconsistent formatting, use your editor's auto-formatting feature.

      > is there a better way to handle this?
      Yes, you'll learn about `assert` later.

      > creating a new struct with each iteration
      You're not creating a "new struct", you're creating a new instance of a struct.

      > the exit is not explicit enough?
      It's fine. You could also use a `while (true)` loop and `break` to remove the need of `exit`.

      • Anastasia

        Thank you so much for your response, nascardriver, it helps a lot, I hope I understood everything right.

        > Initialize your variables with brace initializers.
        > Line 93 causes undefined behavior, `sum` is uninitialized.
        I did initialize it to 0 with brace initialization (line 85 above). Did I do it wrong?

        > Line 23-30 and 40-70 should use the indexes of `Coin_type`.
        With an enum class the compiler doesn't allow to convert an enumerator to int and it would require to use static_cast to use the indexes. I changed Coin_type to a simple enum and it works this way.

        Hopefully this looks a bit better now:

        • > I did initialize it to 0 with brace initialization (line 85 above). Did I do it wrong?
          No, that's correct. Either I missed it or you edited it after/while I looked at your code.

          - Line 31, 63: Initialize your variables with brace initializers.

          Line 17-22 should use the enumerators.
          Line 24 should use the enumerators.
          Line 35, 38, ...: You already know the type of the coin, there's no need to repeat it

          • Anastasia

            > Either I missed it or you edit it after/while I looked at your code.
            No, you didn't miss it. I did in fact edit this line shortly after posting. I was just worrying that it is not the right way(or place) to initialize it.

            > Line 17-22 should use the enumerators.
            I wasn't sure whether I should use enumerators here, because the code is just asking for the user's input.

            I think I fixed everything this time. Won't post it, because I'm afraid I've already taken too much space.

            Thank you one more time for your help and patience.

  • Envy

    I just skimmed the comments and there were only several questions if we couldn't replace the && with || in do-while loop, which is obviously wrong. But what I thought about is why won't we use

    instead of

    If we would add a 5th option to choose from you had to add another "&& selection != 5", whereas in my example you just had to change the 4 into a 5. I know this only works here because we use consecutive numbers but it just bothered me a bit :D

    • Walter

      You're right, this would work, because we use numbers as stand-in for explicit options. Selection 2 is 'Subtraction', but it's also the number 2. It makes sense to say "2 + 1 is 3", but you can't say "Subtraction + Addition is Multiplication".

      We should be using an enum for the options here, but for brevity, this has been excluded. The following doesn't really make sense, for example:

      I believe this is the reason the conditional is written the way it is.

  • SamiraFerdi

    Alex and nascardriver, can you check this for me?

    • * Initialize your variables with uniform initialization
      * Unnecessary forward declarations. Move @main below the other functions
      * @isEvenOrOdd can be done in 1 line. Give it another try
      * You don't need to switch a bool. Use an if-statement
      * @displayEvenOrOddNumberResult can also be done in 1 line

      • SamiraFerdi

        Thank you for reply!

        what about this?

  • I'm in love with alex's tutor

    Good day! Dear Mr Alex/NAS
       Can we change nested while statements to a do..while ? I kindly & respectfully  ask you to show me how to change nested while loops that you previously showed up in section 5.5 as shown below.I have been trying my best but i cant execute what i need.

    God Bless you all!!!!

    • Alex

      • I'm in love with alex's tutor

        My hero Mr Alex!
        I very++ thank you to open my eyes to see the path of programming world. I am addicted to your tutorial really.

  • Hi Alex,

    Borrowed your menu and made a simple calculator with it:

  • Star Light

    Your website is a treasure that I believe it's must-known for every C++ learner. I always recommend it for anyone how wanna begin with C++. Really love it.

    Btw, I have an idea. It is accepting a number arguments/parameters when ran program. This one is easy. But I want to make the program auto-restart when it take a wrong parameter. Anyway, let check the code:

    I've read the previous lesson about GOTO statement. But, in the end, those args only fetch when program starts. However, I don't know the return code to make program auto-restart. Or do we have other function for this case? And I would like to avoid: (replace "cls" with my name software)

    Because people said antivirus don't like it and I have to register path to window var environment. And if user change software name then it die :p

    I hope you could gimme some advice for this.

    • nascardriver

      Hi Star Light!

      There are ways to restart you program, but there's no point in doing so programmatically, because you need the user to pass new arguments.
      If you want your program to keep running even if the user entered an erroneous command line you need to manually ask the user for input (@std::cin, @std::getline) and parse it.
      This will require the user to re-enter the entire command line whereas they'd only need to press the up arrow and correct their mistake if you let them restart the application.

      • Star Light

        Yeah, you have a point. But I really want input as an array. std::cin or std::getline could do that, but it isn't as good as taking arguments right from the start.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]