Search

4.x — Chapter 4 summary and quiz

Quick Review

The smallest unit of memory is a binary digit, also called a bit. The smallest unit amount of memory that can be addressed directly is a byte. The modern standard is that a byte equals 8 bits.

A data type tells the compiler how to interpret the contents of memory in some meaningful way.

C++ comes with support for many fundamental data types, including floating point numbers, integers, boolean, chars, null pointers, and void.

Void is used to indicate no type. It is primarily used to indicate that a function does not return a value.

Different types take different amounts of memory, and the amount of memory used may vary by machine. See 4.3 -- Object sizes and the sizeof operator for a table indicating the minimum size for each fundamental type.

The sizeof operator can be used to return the size of a type in bytes.

Signed integers are used for holding positive and negative whole numbers, including 0. The set of values that a specific data type can hold is called its range. When using integers, keep an eye out for overflow and integer division problems.

Unsigned integers only hold positive numbers, and should generally be avoided unless you’re doing bit-level manipulation.

Fixed-width integers exist to define integer types with guaranteed sizes. Favor the std::int_fast#_t and std::int_least#_t integers when you need a fixed size guaranteed to be at least a certain size. std::int8_t and std::uint8_t should generally be avoided, as they tend to behave like chars instead of integers.

size_t is an unsigned integral type that is used to represent the size or length of objects.

Scientific notation is a shorthand way of writing lengthy numbers. C++ supports scientific notation in conjunction with floating point numbers. The digits in the significand (the part before the e) are called the significant digits.

Floating point is a set of types designed to hold real numbers (including those with a fractional component). The precision of a number defines how many significant digits it can represent without information loss. A rounding error can occur when too many significant digits are stored in a floating point number that can’t hold that much precision. Rounding errors happen all the time, even with simple numbers such as 0.1. Because of this, you shouldn’t compare floating point numbers directly.

The boolean type is used to store a true or false value.

If statements allow us to execute one or more lines of code if some condition is true. Multiple statements can be executed if they are put inside a block (inside curly braces). The conditional expression of an if statement is interpreted as a boolean value.

Char is used to store values that are interpreted as an ASCII character. When using chars, be careful not to mix up ASCII code values and numbers. Printing a char as an integer value requires use of static_cast.

Angled brackets are typically used in C++ to represent something that needs a parameterizable type. This is used with static_cast to determine what data type the argument should be converted to (e.g. static_cast<int>(x) will convert x to an int).

A constant is a fixed value that may not be changed. C++ supports two types of constants: literal constants, and symbolic constants.

Literals are values inserted directly into the code. Literals have types, and literal suffixes can be used to change the type of a literal from default.

Const variables are variables that can’t be changed after being initialized. Const variables can be either runtime or compile-time constants. constexpr variables must be compile-time constants.

Don’t use magic numbers in your code. Instead, use symbolic constants.

Quiz time

Question #1

Why are symbolic constants usually a better choice than literal constants? Why are const/constexpr symbolic constants usually a better choice than #defined symbolic constants?

Show Solution

Question #2

Pick the appropriate data type for a variable in each of the following situations. Be as specific as possible. If the answer is an integer, pick either int, long, or a specific fixed-width integer type (e.g. std::int_fast16_t) based on range. If the variable should be const, say so.

a) The age of the user (in years)

Show Solution

b) Whether the user wants color or not

Show Solution

c) pi (3.14159265)

Show Solution

d) The number of pages in a textbook (assume size is important)

Show Solution

e) The length of a couch in feet, to 2 decimal places

Show Solution

f) How many times you’ve blinked since you were born (note: answer is in the millions)

Show Solution

g) A user selecting an option from a menu by letter

Show Solution

h) The year someone was born (assuming size is important)

Show Solution

Question #3

Author's note

The quizzes get more challenging starting here. These quizzes that ask you to write a program are designed to ensure you can integrate multiple concepts that have been presented throughout the lessons. You should be prepared to spend some time with these problems. If you’re new to programming, you shouldn’t expect to be able to answer these immediately.

Remember, the goal here is to help you pinpoint what you know, and which concepts you may need to spend additional time on. If you find yourself struggling a bit, that’s okay.

Here are some tips:

  • Don’t try to write the whole solution at once. Write one function, then test it to make sure it works as expected. Then proceed.
  • Use your debugger to help figure out where things are going wrong.
  • Go back and review the answers to quizzes from prior lessons in the chapter, as they’ll often contain similar concepts

If you are truly stuck, feel free to look at the solution, but take the time to make sure you understand what each line does before proceeding. As long as you leave understanding the concepts, it doesn’t matter so much whether you were able to get it yourself, or had to look at the solution before proceeding.

Write the following program: The user is asked to enter 2 floating point numbers (use doubles). The user is then asked to enter one of the following mathematical symbols: +, -, *, or /. The program computes the answer on the two numbers the user entered and prints the results. If the user enters an invalid symbol, the program should print nothing.

Example of program:

Enter a double value: 6.2
Enter a double value: 5
Enter one of the following: +, -, *, or /: *
6.2 * 5 is 31

Show Hint

Show Hint

Show Solution

Question #4

Extra credit: This one is a little more challenging.

Write a short program to simulate a ball being dropped off of a tower. To start, the user should be asked for the height of the tower in meters. Assume normal gravity (9.8 m/s2), and that the ball has no initial velocity (the ball is not moving to start). Have the program output the height of the ball above the ground after 0, 1, 2, 3, 4, and 5 seconds. The ball should not go underneath the ground (height 0).

Your program should include a header file named constants.h that contains a symbolic constant to hold the value of gravity (9.8).

Use a function to calculate the height of the ball after x seconds. The function can calculate how far the ball has fallen after x seconds using the following formula: distance fallen = gravity_constant * x_seconds2 / 2

Sample output:

Enter the height of the tower in meters: 100
At 0 seconds, the ball is at height: 100 meters
At 1 seconds, the ball is at height: 95.1 meters
At 2 seconds, the ball is at height: 80.4 meters
At 3 seconds, the ball is at height: 55.9 meters
At 4 seconds, the ball is at height: 21.6 meters
At 5 seconds, the ball is on the ground.

Note: Depending on the height of the tower, the ball may not reach the ground in 5 seconds -- that’s okay. We’ll improve this program once we’ve covered loops.
Note: The ^ symbol isn’t an exponent in C++. Implement the formula using multiplication instead of exponentiation.
Note: Remember to use double literals for doubles, eg. 2.0 rather than 2.

Show Solution

Question #5


Find 2 issues (affecting 3 lines) in the following code.

Sample output

How old are you?
6
Allowed to drive a car in Texas [ ]
How old are you?
19
Allowed to drive a car in Texas [x]

Show Solution


5.1 -- Operator precedence and associativity
Index
4.13 -- Const, constexpr, and symbolic constants

992 comments to 4.x — Chapter 4 summary and quiz

  • Zephirus

    Hi, new to C++, in lines 42 to 47 of the answer for question 4, it looks like you're using magic numbers. Is this the case? Why? I was also wondering if my code is ok.

    constants.h:

    gravityCalculator.cpp:

    Thanks,
    Z.

    • nascardriver

      Those numbers are magic, that's right. We don't yet have the tools to unmagicify them. We could do what you've done, but that solution is rather lengthy. In the next chapter, we'll introduce the increment operator, which makes this a lot easier.

      To your code
      - Don't use fixed-width integers unless you have a reason to. Use a plain `int` if you don't care about the width.
      - Use double literals for doubles to prevent accidental integer arithmetic. 2 is an integer, 2.0 is a double.
      Otherwise good job :)

  • kutlu

    Thank you for lectures, they are great sources for me to learn as newbie. Can you evaluate my code. It works as yours but I wrote a function by using for loops that ask also time to play with code. But I break the rule "one job for a function" in calculateHeight.cpp. I will improve that. But what will be your advice to improve this code in the manner of coding logics?

    constant.h

    askHeight.h

    askHeight.cpp

    calculateHeight.h

    calculateHeight.cpp

    main.cpp

    • nascardriver

      - Initialize variables with list initialization
      - Use ++prefix unless you need postfix++

      The rest looks good :)

      • kutlu

        Really Thank you for your answer and evaluation :) Actually I have used uniform initialization, but I look at list initializaition but I dont understand it what is the difference. And what is the advantages prefix over postfix ( ++i over i++)?

        • nascardriver

          Line 12 is using copy initialization

          `i++` has to create a copy of `i`, because it returns the value that `i` had before incrementing it. `++i` increments `i` and returns the new value, no copy is necessary. We cover this in the next chapter.

  • Tiwi

    Is it bad that i couldn't do the fourth question

  • alex

    Hey! I'd appreciate some feedback on my solution to the second challenge. I used a while loop to solve the issue of going past 5 seconds, even though they haven't been taught yet, because I'm already pretty familiar with them. I think my calculateHeight function is pretty convoluted but otherwise it works pretty well.

    constants.h

    main.cpp

    • nascardriver

      Hey!

      - `distanceFallen` isn't used outside of the loop. Define it inside.
      - Use ++prefix unless you need postfix++. Postfix++ is slower.
      - Inconsistent formatting. Consider using an auto-formatter.
      - Use double literals for double to prevent accidental integer arithmetic (1.0, 0.0)

      Good job, feel free to whatever features you know already :)

  • Chaya

    Here's how i solved the second challenge. I'm super new to this so I would love some feedback, especially because it's very different to the solution given.

    constants.h

    main.cpp

    • nascardriver

      It's not all too different from the solution.

      - `constants::seconds*` hardly add value to your code. You could instead define a `seconds` variable in `main` and increment it after every call to your functions.
      - Your `main` is very repetitive, this can be avoided by added another function that calls `distance_fallen` and `current_height`.
      - Use double literals for doubles to avoid accidental integer arithmetic. `0` is an integer, `0.0` is a double. Same for `2` and `2.0`.

  • Patryk

    Hello. My solution has only 3 functions and I don't know if it's ok. Thanks for the reply if there will be any! Love the site. Can't wait to continue :D

  • Simone

    Hi, I'm learning C++ after spending some time on more abstract languages (python, js). I'm still going through most of the lessons in order not to miss some important detail in the journey, I cheated a bit by using a for loop on the height program.
    I was wondering: is it really good / common practice to split code in so many small functions? I don't want to come off as rude, I'm honestly wondering if it's exaggerated to get us into the habit of using multiple function in bigger and more complex programs or if to write good code I really need to minimize the amount of logic in the main body.
    Thank you for the tutorial!

    • nascardriver

      Yes, many functions really are good. If I wanted to write a program like this in reality, I'd probably do everything in `main`, because why bother adding function if the program is that simple. But we're not writing these programs to use them, we write them to practice, and if we do everything in main in practice, we won't learn how to do it properly.

  • Tony

    Question about the ball height was much more difficult. I did it in a different way, but it was impossible for me to remove the (double) "seconds"! Is this any bad? Thanks for your time @nascardriver, amazing work!

    constants.h:

    • nascardriver

      You got pretty close :) All you needed was a function that combines that calculation and the printing.

      • Tony

        Thanks for the fast reply again. I checked the solution... never thought of that in all honesty haha.

        Do you think I should proceed with the next chapter? I believe that I understood the main concepts,  although writing them down on a program is a complete different story.

      • JamesR

        The only other thing I would add to this is that you chose int userHeight, should be double towerHeight since that is where you store the input from the user in getTowerHeight earlier.
        This is more of a nitpick, but it is best practice and helps make your code more clear.

  • Tony

    Hi Alex & nascardriver (again, lol!)

    I've done Question 3 differently. I created a separate function (printResult) so I don't have to type std::cout every time, but just once. Also, I tried to use everything I learned on this chapter (bools, const, etc). Is this code ok, and where can it get better? Thanks!

    • nascardriver

      Enable compiler warnings, read them, fix them. `getResult({}, {}, {})` causes undefined behavior because the function doesn't return.

      You never need this. It's equivalent to

      Don't use `std::exit` unless there's no way around it. You're in `main`, return instead.

      `printResult` only makes sense if you're going to use it from more than one place. If that's the case, then you can easily adjust the output message for your entire program.

      > I don't need const, since the result might vary (?)
      `result` never changes after it has been initialized, so it can be `const`.
      Your description fits `constexpr`. The value is always the same no matter how often you run the program. The function could be called by the compiler once and take load off of the runtime. That's not possible here, because the call depends on user input.

    • Tony

      Thanks @nascardriver!
      I've changed the boolean.

      "Don't use std::exit unless there's no way around it" > There indeed was, just I didn't find it in the first attempt. I noticed that typing down the prototype of the program on paper works for me, and actually I find more ideas!

      I tried again. Is the following ok? Thanks for the help by the way!

  • Monnito

    How can I put a code in the comment

  • Volatus

    On question 5, I believe (given what has been taught so far) I found another issue with the code.

    In this case, as previously seen, although 16 clearly specifies the minimum age for driving in Texas, it can be considered a magic number! I wonder if it wouldn't be better to use a symbolic constant defined as a constexpr with a name such as minimum_driving_age or something...

  • Shtimpo

    Question #4 possible solution:

  • BeanSprugget

    In question 2 you write: "specific fixed-width integer type (e.g. int16_t) based on range".
    Is this supposed to be "int_fast#_t" and int_least#_t" instead, which are seen in the answers and are more useful?

    Also, shouldn't the answers in Question 2 that have "int_fast#_t" and "int_least#_t" be prefixed with "std::" (questions d, f, and h)?

  • It's+Me

    Sadly my mind stopped at Question #4 :(

  • Amir

    gravity.cpp

    constants.h

    main

  • Amir

    calc.h

    calc.cpp

    main.cpp

  • Luxary

    Is calculateAndPrintHeight() in Quiz #4 really necessary? I get that refactoring needs to be as "atomic" as possible, but in this case the identifier name itself seems to contradict the "one (and only one) task" guideline. This is what I came up with before peeking at the solution:

    I guess my actual question is, is it worth refactoring code even when it literally adds more clutter and makes you deal with return values multiple times? Or is it okay to leave it as is and then refactor it when the time comes (if it ever comes)?

    Thanks!

    • nascardriver

      Your `printFallDistance` and the quiz' `calculateAndPrintHeight` do the same, only with different names. The quiz' `printHeight` could be reused, for example for a throw that goes up and down, or for dropping something in water (Which is slower). If you wanted to do that in your code, you'd have to copy line 23-26 all over the place or also add a `printHeight` function.

  • rupp_bin

    main.cpp

    gravity.h

    • nascardriver

      - Use an auto-formatter.
      - Use double literals for doubles to prevent accidental integer arithmetic.
      - Initialize variables with list initialization for higher type safety.
      - Use ++prefix instead of postfix++. postfix++ is slower.
      - `gravity` is a `float`, but `9.8` is a `double`. Use `double` unless you have a reason to use `float`.

  • Keshav

    ques. 4 answer
    main.cpp

    constants.h

    • nascardriver

      Initialize variables with list initialization. When you do that, you'll find that `newHeight` should be a `double`. Don't use `float` unless you have a reason to. Use double literals to prevent mixed types in arithmetic. 2 should be 2.0 and 0 should be 0.0.
      postfix++ is slower than ++prefix, so you ++prefix unless you need postfix++.

  • Zolee

    Hi, I was wondering if my code makes sense, from a programmer's perspective.
    I'm new to this and don't really know, if i could have done something better here or not.
    Thank you

    #ifndef constants_hpp
    #define constants_hpp
    constexpr double GRAVITY {9.8};
    #include <stdio.h>

    #endif /* constants_hpp */

    ```
    #include <iostream>
    #include "constants.hpp"

    double getTowerHeight()
    {
        std::cout << "Enter the height of the tower in meters: ";
        double towerHeight {};
        std::cin >> towerHeight;
        return towerHeight;
    }

    double ballHeight(int sec)
    {
        double distanceFallen {GRAVITY * (sec * sec)/2};
        return distanceFallen;
    }

    void distanceFallen(double sec, double height)
    {
        if (ballHeight(sec) < height)
            std::cout << "At " << sec << " seconds, the ball is at height: " << height - ballHeight(sec) << " meters.\n";
        else
            std::cout << "At " << sec << " seconds, the ball is on the ground.\n";
    }
    int main()
    {
        double height {getTowerHeight()};
        distanceFallen(0, height);
        distanceFallen(1, height);
        distanceFallen(2, height);
        distanceFallen(3, height);
        distanceFallen(4, height);
        distanceFallen(5, height);
        
        return 0;
    }
    ```

    • nascardriver

      stdio.h is a C header and you're not using anything from it. You need iostream.
      Prevent mixed types in arithmetic. 2 should be 2.0.
      You're calculating the ball height twice in `distanceFallen`. Store the result in a variable.
      The rest looks good. learncpp doesn't support markdown. You get code highlighting by using code tags as shown below the text field when you write a comment.

      • Zolee

        Hi,
        Thank you for the quick reply, and the suggestions!
        stdio.h was just a preset in Xcode header file.

        I hope this time it is better:

  • Math

    On solution to question 4 you say:
    "Note that calculateHeight() doesn’t print the height itself, under the best practice that functions should do one and only one thing. We use a different function to do the printing." but in the solution to question 3 the function printResult(double x, char op, double y) checks the symbol validity AND prints the answer. Wouldn't be better if we make a separate function to check if the operator entered by the user is valid?

    • nascardriver

      `printResult` doesn't check to operator to make sure it's valid, it checks it because it has to decide which calculation to perform. However, you're right in saying that the function does too much. We could add another function `calculate(double x, char operation, double y)` that performs the calculation without printing the result.
      The problem is that the quiz demands "If the user enters an invalid symbol, the program should print nothing". This means that we'd have to compare the operation twice to first make sure it's valid before calling `calculate`. That's also bad, and at this point, we don't have the tools to let `calculate` indicate that an error occurred.

  • :)

    Hello :)!
    Here's my attempt on question 4, I have a problem of making my code too complicated
    or too simple (adding more functions than necessary or adding very few functions) so I could really use some feedback on this code :)
    constants.h:

    main.cpp:

  • :)

    Hello,
    is this program okay?
    1- I think in the main() fuction the program looks a little bit wonky but I don't know how to fix it (I haven't looked at the solution yet)
    2- Can I pass fuctions to other functions as parameters and how do I do that? I tried searching it online but I only got confused.
    ( I thought of passing in the inputSymbol() function as a parameter to the isSymbolValid() function )

    double.h :

    main.cpp :

    double.cpp :

    • nascardriver

      - `isSymbolValid` has a misleading name and description. It's purpose isn't to check if the symbol is valid. It's purpose is to read input and perform the calculation. The validation of the symbol is just a side effect.
      - Use double literals for doubles to avoid accidental integer arithmetic.

      1- The only issue is your `isSymbolValid` function. It doesn't do what its name suggests, and it does too much. You can make the code easier to read and maintain by passing the symbol as an argument.

      2- You can, but there's no reason to do so in this case. You can pass the symbol as an argument.

      • :)

        Thank you so much for the feedback :)
        Is 'calculateAnswer' a better name for 'isSymbolValid'?

        • nascardriver

          That's a step in the right direction, but you'd still end up with "readSymbolAndCalculateAnswer" or similar. If you pass `symbol` as a parameter, "calculateAnswer" is a good name.

  • Math

    The year someone was born (assuming size is important)

    The answer is int_least16_t
    but isn't making it a const better since the year can't change?
    also (assuming size is important)
    what should I understand from this statement?
    and if you didn't write it would the answer be different?

  • AcesZ

    Here's my attempt at the second challenge. Left in a couple comments to show difference between initial code and current. I think there's a bit of redundancy here but not sure, could use feedback.

    constants.h

    main.cpp

    • nascardriver

      Looks pretty good:)
      The loop should use list initialization and ++prefix. It's a good idea to use double literals for doubles to prevent accidental integer arithmetic.

      • AcesZ

        Not sure what you mean with list initialization, I guess it wasn't mentioned yet.
        As for the loop, I assume changing it to the below code is what you meant.

        Also adjusted ballHeightAtXSeconds with a double literal. Is there another spot I'm missing using a double literal? Couldn't spot any.

        Thank you

Leave a Comment

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