Search

7.x — Chapter 7 summary and quiz

Quick review

The specific sequence of statements that the CPU executes in a program is called the program’s execution path. A straight-line program takes the same path every time it is run.

Control flow statements (also called Flow control statements) allow the programmer to change the normal path of execution. When a control flow statement causes the program to begin executing some non-sequential instruction sequence, this is called a branch.

A conditional statement is a statement that specifies whether some associated statement(s) should be executed or not.

If statements allow us to execute an associated statement based on whether some condition is true. Else statements execute if the associated condition is false. You can chain together multiple if and else statements.

A dangling else occurs when it is ambiguous which if statement an else statement is connected to. Dangling else statements are matched up with the last unmatched if statement in the same block. Thus, we trivially avoid dangling else statements by ensuring the body of an if statement is placed in a block.

A null statement is a statement that consists of just a semicolon. It does nothing, and is used when the language requires a statement to exist but the programmer does not need the statement to do anything.

Switch statements provide a cleaner and faster method for selecting between a number of matching items. Switch statements only work with integral types. Case labels are used to identify the values for the evaluated condition to match. The statements beneath a default label are executed if no matching case label can be found.

When execution flows from a statement underneath a label into statements underneath a subsequent label, this is called fallthrough. A break statement (or return statement) can be used to prevent fallthrough. The [[fallthrough]] attribute can be used to document intentional fallthrough.

Goto statements allow the program to jump to somewhere else in the code, either forward or backwards. These should generally be avoided, as they can create spaghetti code, which occurs when a program has a path of execution that resembles a bowl of spaghetti.

While loops allow the program to loop as long as a given condition evaluates to true. The condition is evaluated before the loop executes.

An infinite loop is a loop that has a condition that always evaluates to true. These loops will loop forever unless another control flow statement is used to stop them.

A loop variable (also called a counter) is an integer variable used to count how many times a loop has executed. Each execution of a loop is called an iteration.

Do while loops are similar to while loops, but the condition is evaluated after the loop executes instead of before.

For loops are the most used loop, and are ideal when you need to loop a specific number of times. An off-by-one error occurs when the loop iterates one too many or one too few times.

Break statements allow us to break out of a switch, while, do while, or for loop (also range-based for loops, which we haven’t covered yet). Continue statements allow us to move immediately to the next loop iteration.

Halts allow us to terminate our program. Normal termination means the program has exited in an expected way (and the status code will indicate whether it succeeded or not). std::exit() is called at the end of main, or it can be called explicitly to terminate the program. It does some cleanup, but does not cleanup any local variables, or unwind the call stack.

Abnormal termination occurs when the program encountered some kind of unexpected error and had to be shut down. std::abort can be called for an abnormal termination.

Scope creep occurs when a project’s capabilities grow beyond what was originally intended at the start of the project or project phase.

Software verification is the process of testing whether or not the software works as expected in all cases. A unit test is a test designed to test a small portion of the code (typically a function or call) in isolation to ensure a particular behavior occurs as expected. Unit test frameworks can help you organize your unit tests. Integration testing tests the integration of a bunch of units together to ensure they work properly.

Code coverage refers to how much of the source code is executed while testing. Statement coverage refers to the percentage of statements in a program that have been exercised by testing routines. Branch coverage refers to the percentage of branches that have been executed by testing routines. Loop coverage (also called the 0, 1, 2 test) means that if you have a loop, you should ensure it works properly when it iterates 0 times, 1 time, and 2 times.

The happy path is the path of execution that occurs when there are no errors encountered. A sad path is one where an error or failure state occurs. A non-recoverable error (also called a fatal error) is an error that is severe enough that the program can’t continue running. A program that handles error cases well is robust.

A buffer is a piece of memory set aside for storing data temporarily while it is moved from one place to another.

The process of checking whether user input conforms to what the program is expecting is called input validation.

std::cerr is an output stream (like std::cout) designed to be used for error messages.

A precondition is any condition that must always be true prior to the execution of some segment of code. An invariant is a condition that must be true while some component is executing. A postcondition is any condition that must always be true after the execution of some code.

An assertion is an expression that will be true unless there is a bug in the program. In C++, runtime assertions are typically implemented using the assert preprocessor macro. Assertions are usually turned off in non-debug code. A static_assert is an assertion that is evaluated at compile-time.

Assertions should be used to document cases that should be logically impossible. Error handling should be used to handle cases that are possible.

Quiz time

Warning: The quizzes start getting harder from this point forward, but you can do it. Let’s rock these quizzes!

Question #1

In the chapter 4 comprehensive quiz, we wrote a program to simulate a ball falling off of a tower. Because we didn’t have loops yet, the ball could only fall for 5 seconds.

Take the program below and modify it so that the ball falls for as many seconds as needed until it reaches the ground.

In constants.h:

In your main code file:

Show Solution

Question #2

A prime number is a natural number greater than 1 that is evenly divisible (with no remainder) only by 1 and itself. Complete the following program by writing the isPrime() function using a for loop.

Show Solution


8.1 -- Using a language reference
Index
7.17 -- Assert and static_assert

819 comments to 7.x — Chapter 7 summary and quiz

  • Swaraj

    Is this a good solution for quiz 1:

    • nascardriver

      You tell me what's wrong
      - Line 8, 28, 41, 52, 55 (Lesson 1.4)
      - "\t", "\n" (Lesson 4.11)
      - Line 28 again (Lesson 4.8)
      - "accduetog" (Lesson 1.7)
      If you need help, please ask

      Additionally
      - Your naming is inconsistent (All lower case, camel case, upper camel case, all upper case). Choose one name style and stick to it.
      - Your formatting is inconsistent. Use your editor's auto-formatter.
      - You're calling `TimeTakenToHitGround` in every iteration of your loop. Call it once and store the return value in a variable. Use that variable in your loop's condition.
      - math.h is a C header. C++ has cmath.
      - `sqrt` should be `std::sqrt`. This was wrong in the lessons too, sorry about that.

      • Swaraj

        I understood everything except for "-Line 28 again (Lesson 4.8)".
        Thank you for this wonderful tutorial and for replying.

        • nascardriver

          - Line 8, 28, 41, 52, 55: Should be initialized with list initialization.
          - "\t", "\n": Should use single quotes, because they're characters.

          - Line 28 again: Should be 2.0 to prevent accidental integer arithmetic.

          - "accduetog": Don't use abbreviations.

          • Swaraj

            "Should be 2.0 to prevent accidental integer arithmetic"

            I thought of that but wont the integer literal 2 be promoted to 2.0 because heightoftower and accduetog are type double......or should I use 2.0 because it is good programming practice in
            general?

            • nascardriver

              2 will be promoted to `double`, because `heightoftower` is a `double`. It's bad practice to mix types in arithmetic, so 2.0 should be used.

  • samira

    I was wondering if my solution is good enough as I implemented all the steps using functions!

    • nascardriver

      I'll give line numbers, you guess what's wrong with these lines. If you need help, just ask

      - Line 36, 37, 72, 76
      - Line 47
      - Line 100

      In addition to those

      - Avoid recursion (A function calling itself) (`startPlayingGame` -> `replayTheGame` -> `startPlayingGame` -> ...). Your program will crash after a couple of runs because you run out of stack memory. Use loops instead.
      - Printing a space before a line feed doesn't make sense. If you don't like having the \n touching the last word, you can put it in a separate string literal ("Correct!You win!" "\n"). The compiler will concatenate the literals.

  • samira

    Do you think this  can be a short solution for Question #1 with preserving all the functions used in the first place?

  • Innervate

    This was my attempt at the second questions. I'm not entirely comfortable using for-loops, so I fell back to using While and do-While, and relying on if-statements. I would appreciate it if anyone would give me some advice on where I can improve, or what steps I should start thinking about in order to optimize it.

    Many thanks!

    • nascardriver

      HI!

      Line 39 should be `else if`, line 46 should be `else`.
      Line 33-37 and 42-45 should be moved out of the conditional part.
      Magic string: 7. Use your constant.

      • Innervate

        Thanks for the feedback nascardriver!
        for line 7, How should I approach to use my constant to replace the while statement? I am guessing I should use the condition while(RemainingGuesses > 0) instead of while(true). But doing so without another return statement gives me the error "Semantic issue: Control may reach end of non-void function".

        I have changed the following:

        • nascardriver

          Not line 7, the string "7" in what is now line 85. You can move `RemainingGuesses` above that line and use it to print the message.

          • Innervate

            Ahh okay that makes sense. is it still alright to use the condition "while(true)" in GetPlayerGuess() to test for invalid input?

            This is my updated code:

  • Eric

    Hey, just FYI - the error check doesn't prevent a user from entering a real number (double). When ::cin is expecting an int it therefore truncates the decimal? if so how would I detect a double type input?
    Thanks!

  • Eric

    Firstly thanks for this tutorial series! You're helping a lot of us learn to program well; I'm grateful.

    I want to keep all of my quiz solutions in an efficient manner. Do you have a suggestion for storing/ managing these? it seems like creating a project in Visual studio for each of these is a bit of overkill.

    Cheers and thanks again!

  • phil

    If I don't enter anything and just press enter, when asked to enter a number. I get flashing cursor on the next line. Is there a way to fix that ?

  • RJ

    Could someone critique my work I want to see how i'm progressing. I know there are many ways to solving problems in C++.

    This program was separated into different files when i made it, but I posted it like this just to keep it simple.

    • nascardriver

      `GenerateRandomNumber` isn't random. Sees random number generators only once.
      `&` is a bitwise and. You probably meant to use the modulus operator `%`.
      Use your editor's auto-formatter.
      Don't use goto, use loops.
      Magic string: 7. Use your constant.
      Use ++prefix unless you need postfix++. postfix++ is slower.
      Use characters for characters. Using integers is wildly confusing.
      Line 83 is always true on the first iteration. Use a do-while-loop instead.
      Separate code into as many functions as possible to make it easier to read, maintain, and reuse.

  • Saiyan

    This is what I have. Thanks for sharing your knowledge. Always regretted dropping out of Intro to C++ so many years ago.

    • nascardriver

      Hi!

      - Name variables descriptively. "x" isn't helpful.
      - Compile-time constants should be `constexpr`.
      - Line 59 is always true.
      - The caller of `playAgain` shouldn't care about what the user input looked like. Return a `bool` instead. Then you can remove line 83 and 87 and just call `playAgain` in the main loop's condition.

      • Saiyan

        Thanks for the feedback! Regarding your last point, would something like this be more preferable?

        • nascardriver

          Yes, that's what I meant. Now the caller doesn't have to worry about how the user interface is implemented. Say you translate your program to french and you use 'o'/'n' as input. You just have to update `playAgain`, and not every call to it.

          You never need an `if`-statement like this

          it can and should be replaced with

          You now have a duplicate comparison of `ch` to 'y'. That can be avoided by checking `ch` inside of the loop.

  • M.J

    Hello everyone.
    This is question #2
    i copied the code of part b and used it in my function to validate user input. however it shows zero and continues when i test invalid input. can anyone suggest solution?

    • nascardriver

      Please use an auto-formatter. You code is hardly readable.

      • M.J

        yeh sorry about that, I updated.

        • nascardriver

          You're returning from your `while (true)` loop no matter what happened before. Even if you detect invalid input in line 32, you're returning in line 43.

          Other notes:
          - `generateRandomNumber` isn't random. Seed random number generators only once.
          - Enable compiler warnings, read them, fix them.
          - By returning a `char` from `getUserChoice`, you're forcing the caller to perform another check for 'y'/'n'. Return a `bool` instead.
          - Magic numbers/strings. Add constants.
          - Use ++prefix unless you need postfix++. postfix++ is slower.
          - Line 102 is always true.
          - Line 106-120 and 126-142: Duplicate code.

          If you have questions to any of those points, please ask. Feel free to post your code for review when you're done with the quiz :)

          • M.J

            I tried fixing most issues you mentioned. i tried getting rid of the extra duplicate code. i ended up with a smaller block of duplicate code :p
            - i ran the program several times and got different random numbers, so i couldn't figure the random number generator's seeding part you mentioned.
            - i have "w-error" activated in code blocks as mentioned in ch 0.11
              the program runs fine now.
            here is the updated version.
            THANKS a lot for your efforts... much appreciated. :)

            • nascardriver

              > I tried fixing most issues you mentioned
              - `generateRandomNumber`

              Outputs the same number over and over again, because you're re-seeding `mersenne` every time, resulting in the random sequence being reset. Make `mersenne` `static` so it only gets created once no matter how often the function is called.

              - compiler warnings
              It looks like you're not compiling with -Wall -Wextra. There are still warnings, because the parameters of `gamePlay` are unused.

              - getUserChoice
              Looking good now :)

              - Magic numbers/strings
              Still there. Add a constant for `7`, use that in line 108, 112, 149.

              - ++prefix
              Yep, gone.

              - Line 102 is always true
              Correct fix

              - Duplicate code
              You can move the game part (Line 104-164, but without 132-140 and 153-161) into a new function. That will get rid of the duplicate code and the `goto`.

              Notes on your updated code:
              - Line 78 and 86 are basically returning the value of `userChoice`. You can remove these lines and add an unconditional `return userChoice;` to the end of `replay`.

              • M.J

                hey! thank you fro your note.
                - I declared 'mersenne' in an namespace. as i saw it in one of the comments, that seems to have solved the issue with random number generation. thank your for pointing that out.
                - I added the provided extensions to my compiler settings.
                - i decided to go for a do while loop as it seems to have solved most problems lol :))
                this is my final version of the code :)

                p.s.
                I want to solve more similar problems to try improve my logic and computational thinking before advancing to the next chapters. If you happen to have any useful resources on where i can find such. Please be generous.
                Thank you again.. :)

                • nascardriver

                  > logic and computational thinking
                  The best source to get that is by practice. Keep on programming and you'll get better.

                  Unless you're using notepad, your editor probably has a feature to auto-format your code. You should look into that.

  • Raul T

    Hi!
    In the first instance I wanted to put the 'secondsPassed post-increment' in the for loop 'end-expression', but from that resulted in a small bug.
    Assignment #1

    • nascardriver

      > I wanted to put the 'secondsPassed post-increment' in the for loop 'end-expression'
      If you don't know how often a loop will run, a `while`-loop is usually the better choice.

  • These lessons have been awesome! I have followed from the very first chapter, and I can tell my skills are better now. I hope to land a job with this skill. Take a look at my solution. Could I have done anything better?

    constants.h

    main.cpp

  • Fosterwerks

    Just wondering if my uses of const and static inside my version of startGame() are good uses or not. (Did not include the whole program for brevity). Thanks!

    • nascardriver

      Hi!

      `mt` is right, but `dist` is problematic. `startGame` can be called multiple times, with different `numRange`. But `dist` is only created once, at doesn't care about any `numRange` after the first one.

  • mindenki

    Hey! Here is my solutioon for question #1? Is it any good?

    • nascardriver

      If it works, it's good.

      Suggestions:
      - Initialize variables with list initialization.
      - Use double literals for doubles (0.0).
      - Duplicate calculation of the current height. Add a variable.
      - Line 22 and 24 break your program. The given formula calculates this distance fallen since the beginning.
      - Line 32 is never false.

  • Nathuunn

    I made height a global variable, im wondering if thats okay, and if its not why?

    • nascardriver

      Global variables are bad, we explained why in lesson 6.9. You can get rid of it with minimal modifications to your code, just add a return value to `calculateAndPrintHeight`.
      Avoid `static` local variable. `incrementSeconds` isn't reusable. Say you wanted to let the simulation run several times, each time asking the user for another height, you can't do that.

  • veqes

    Hello again! I had a go at Q2 and I ran into a really frustrating problem. I don't know how to avoid using goto at the end of my "win" condition. Could you please have a look at my code and give me some clues on how to avoid it in this case?
    I'd appreciate feedback on the rest of the code as well if possible :)
    Thank You!

    • nascardriver

      `getRandomNumber` isn't random. Don't re-seed random number generators.

      Use `bool` with `false`/`true` for values that have only 2 options, not `int`.

      When the number is correct, you can `break` the loop. Now you just have to move the "Sorry" message (Don't duplicate it!), or find a way of remembering the result until after the loop, so you only print the message when the user lost.

  • Anto

    i know it could be better, but i tried to change the least possible.

  • Gabe

    Quiz 2

    What could I have changed? I feel it could have been better.

    constants.h

    main.cpp

    • nascardriver

      - Initialize variables with list initialization.
      - Magic string: 7
      - "user_input" isn't a good name for what the function does. "play_game" or similar would be better.

      If `validate_user_input` returns false, the user loses a guess. If that's not what you intended, you could decrement `count` in the event of an input failure or use a different kind of loop.
      Your play again loop is good, many people get this part wrong ;)

      • Gabe

        Thanks again! Yeah I was aware of the "user loses a guess" part;however, I thought my code was a bit messy the way it was already, so I didn't add it I guess.

        Also, for the "magic string, " I should have added the NUM_OF_GUESS instead?

  • Sahib

    Can I get some feedback?

    • nascardriver

      - Inconsistent formatting. Use your editor's auto-formatting feature.
      - Magic number/string: 7
      - Your main loop can be simplified by using a do-while-loop. You don't need `replay` if you do that. Try rewriting it to make sure you know how to do it in the upcoming quizzes. If you need help, don't be afraid to ask :)

  • Miko

    Hello and greetings from Finland! Thank you for all the amazing lessons on this site. I've been going through these lessons for a week now and what a ride it has been. Probably the best free curriculum on anything I've ever stumbled upon.

    Here's my attempt on the second quiz question. All comments and suggestions will be highly appreciated.

    constants.h :

    user_input.hpp :

    main.cpp :

    user_input.cpp