Search

D.2.10 — Chapter D.2 comprehensive quiz

Quick Review

Integers are used for holding whole numbers. When using integers, keep an eye out for overflow and integer division problems. Use the int type when the size of an integer doesn’t matter. Use fixed-width integers when the precise size of an integer is important (either due to range or memory usage concerns).

Floating point numbers are used for holding real numbers (which can have fractional components). When using floating point numbers, keep an eye out for precision issues, rounding errors, and comparison issues.

Boolean values hold only true and false. They do not have any major issues.

Char values are integers that can be interpreted as an ASCII value. When using chars, be careful not to mix up ASCII code values and numbers, and watch for overflow and integer division problems.

Use the const keyword to declare symbolic constants instead of #define. It’s safer.

Comprehensive quiz

Question 1

Why are symbolic constants usually a better choice than literal constants? Why are const 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 a specific fixed-width integer type (e.g. int16_t) based on range. If the variable should be const, say so.

a) The age of the user (in years)
b) Whether the user wants color or not
c) pi (3.14159265)
d) The number of pages in a textbook (assume size is important)
e) Your height in inches (to 2 decimal places)
f) How many times you’ve blinked since you were born (note: answer is in the millions)
g) A user selecting an option from a menu by letter
h) The year someone was born (assuming size is important)

Show Solution

Question 3

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

Hint: Write three functions: one to get a double value, one to get the arithmetic symbol, and one to calculate and print the answer.
Hint: You can check if the user has entered a plus symbol using an if statement, covered in section 2.6 -- Boolean values. Use if/else statements to check whether the user has entered any of the arithmetic symbols.

Show Solution

Extra Credit: Question 4

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 includes a namespace called myConstants. In the myConstants namespace, define a symbolic constant to hold the value of gravity (9.8). See section 2.9 -- Symbolic constants and the const keyword for a reminder on how to do this.

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.

Show Solution

O.3.1 -- Operator precedence and associativity
Index
D.2.9 -- Const, constexpr, and symbolic constants

634 comments to D.2.10 — Chapter D.2 comprehensive quiz

  • Paulo Filipe

    Could any pro guy review my code for the question 4?

    I am reading these lessons for about a week and I am in love with programming!! Thanks to the authors for the effort put into these.
    Very comprehensive text!!

    I wanted to add an extra feature to the program to calculate the exact moment in seconds of when the ball hits the ground, so I did some Google searches and this is my program:

    const.h

    main.cpp

    I confess that I took a peak at how the main function was structured in the solution (I was stuck cuz I'm still a noob) but after that, never had to look into the solution anymore!

    • Hi Paulo!

      main.cpp
      * Line 18: Initialize your variables with brace initializers. You used copy initialization.
      * Line 18, 35: Use double literal when calculating with doubles (2.0 instead of 2)
      * Line 10, 26: Initialize your variables with brace initializers.
      * Line 31, 36, 38, 53: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 25: Misleading reassignment. The new value is no longer a height

      • Paulo Filipe

        Thanks for the review, but I have one question:

        * Line 10, 26: Initialize your variables with brace initializers.
        Am I supposed to initialize  a variable that is going to be assigned a value in the next line inputted by the user?

        The rest was clear enough and I get it. =)

        • Yep, initializing everything prevents forgetting an initialization where you would have needed it.
          Prior to C++11, @std::cin::operator>> didn't override the value of the variable if extraction failed. Unless you read the documentation, don't assume a function is able to handle uninitialized variables.

  • Paulo Filipe

    How do I leave a comment with code? Sorry about the noob question.

  • Alireza

    What about this solution, I think it's shorter than others. X-D

    • * Line 12, 29: Initialize your variables with uniform initialization. You used copy initialization.
      * Line 18, 26, 27: Initialize your variables with uniform initialization.
      * Line 24, 31, 32, 37: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 29: Use ++prefix unless you need postfix++
      * @main: Missing return statement
      * Line 37-42: Should use the conditional operator
      * Use double literals when calculating with doubles (2.0 instead of 2)

  • RVJonah

    I am really enjoying these tutorials and I learning a lot and fast. Can I make a suggestion that you change to the statement in the formula in part 4. It currently reads:
    "distance fallen = gravity_constant * x_seconds2 / 2"
    and to make it clear should read:
    distance fallen = (gravity_constant * x_seconds2) / 2
    as it is very easy to miss read this as
    distance fallen = gravity_constant * (x_seconds2 / 2)
    which gives completely different results.

  • Paul

    When attempting to debug how do you enter the value of variables such as the initial height used in question four?

    • Alex

      Once you debug past the line that accepts input, your program will wait for you to enter input before proceeding in the debugger. You should be able to enter input in the normal way, via the console window your program opens when it is launched.

  • FoxKid777

    • Hi!

      * Line 19, 21, 38, 39, 54: Initialize your variables with uniform initialization. You used copy initialization.
      * Line 31: Initialize your variables with uniform initialization.
      * Line 22, 37, 47, 49: Limit your lines to 80 characters in length for better readability on small displays.
      * Don't use "using namespace"
      * Use ++prefix unless you need postfix++
      * Use double literals when calculating with doubles (2.0 instead of 2)
      * Unnecessary forward declarations. Move @main below the other functions.
      * Line 49: height-height is 0.0

  • n1fty

    • constants.h
      * Line 5: Initialize your variables with uniform initialization. You used direct initialization.

      main.cpp
      * Line 8, 17, 18, 23, 24: Initialize your variables with uniform initialization. You used copy initialization.
      * Line 9, 40: Initialize your variables with uniform initialization.
      * Line 17, 26, 37: Limit your lines to 80 characters in length for better readability on small displays.
      * @main: Missing return-statement.
      * Line 8: 1 is an int. Use 1.0
      * Line 9, 10: @i should be declared in the for-loop's init block
      * Use ++prefix unless you need postfix++
      * Line 11: You can use the *= operator.
      * Line 17: 2 is an int, use 2.0
      * Line 28: +=
      * Line 25: 0.0
      * Line 43: Initialize to 0.0
      * Don't use "using namespace", it can lead to name collisions
      * You're using the same name style for variables, constants and functions. This can lead to confusion.

      • n1fty

        Very eye opening to have someone pick apart your code I love it man. I know better from reading on this awesome site. I did miss one thing.. Name styles. I'll shoot back and read again! And then I'll fix the issues for the sake of learning.

  • n1fty

    Is this how its done? I LOVE homework!

    • Hi!

      * Line 22, 48, 55, 67, 68, 70: Initialize your variables with uniform initialization. You used copy initialization.
      * Line 18, 43: Initialize your variables with uniform initialization.
      * Line 20, 24, 26, 52: Limit your lines to 80 characters in length for better readability on small displays.
      * Variable names should be descriptive.
      * @eCheck should be a boolean
      * Line 55: You're declaring a new variable called "eCheck", which is unrelated to @eCheck in line 48.
      * @std::cin.ignore ignores only 1 character unless you tell it do ignore more.
      * Line 37, 40: Can be replaced with

      * Line 26: | is a bitwise or, you want ||
      * Line 20, 26: Duplicate code
      * @errCheck should be a boolean

  • Nathan

    For some reason, this won’t work.  Can you help?

    If (seconds == 1 && height >= 0)
    ...

    It might be something else in the program, but everything else seems to run fine.  It won’t end up checking for the height.

  • Haydo

    Howdy, just wanted to see how I went for question 3, I realise that the solution written combines calculation and print. I wasn't sure if it was worth making another function just for print, but with the way I've determined operators it feels like that would add a bunch of useless lines to the code. Not sure if the 'do while' loops are up to standard either, I just wanted to do them so had a quick google.

    Thanks for the awesome lessons so far.

    • Hi!

      * Line 51, 53, 56, 58: Initialize your variables with uniform initialization. You used direct initialization.
      * Line 5, 12, 15, 47: Initialize your variables with uniform initialization.
      * Line 14, 42, 59: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 17-23: Use the or-operator (||)
      * Line 26: You're setting @validResponse to true even if it's true already. A while(true) loop would've been more appropriate, since you're not using the condition.
      * @calculateResult: Missing return-statement. If a function has a non-void return type, it has to return.

      Splitting functions is usually a good thing to do.

      • Haydo

        Thanks for the comments, really appreciate the help. Just wanted to get some clarification as I go back and try to improve.

        I read in an earlier chapter that using direct initialization if a variable is going to be instantly assigned is fine. I can see why you would use uniform though, is this a best practice sort of thing?

        To split the lines that are over 80 characters should I just literally split them and use another std::cout to print again (e.g line 14)? I only ask if there is a way to improve readability whilst not adding an extra command.

        Using || was something I didn't think of that makes it much more concise.

        What I can't get my head around is making a concise while(true) loop. It seems super obvious but I cant think of it. I tried this:

        Which I thought would just check if it was a valid operator and print the message and repeat if it wasn't. It seems to just accept any input which will then cause an error when looked up later.

        I know this is probably super obvious but I can't think at the moment.

        Thanks again for all the help.

        • > I read in an earlier chapter that using direct initialization if a variable is going to be instantly assigned is fine
          That doesn't make a whole lot of sense. I could understand that not initializing a variable at all is fine if it's being assigned a value right after. But there's no point in saying initialization X is fine if a value is assigned right after. Could you try to find the lesson stating this?
          Assuming my guess is correct: Yes, you can omit initializations. But doing so could lead to forgetting an initialization where it's necessary, or removing the assignment later and forgetting to initialize the variable. I'm suggesting to initialize all variables, because it prevents you from doing hard-to-debug mistakes.

          > To split the lines that are over 80 characters [...]
          Line 14 could be split into 2 lines by splitting the output

          This adds another call to @operator<<, which slows down your program (minimally). Since this isn't sensitive code (ie. it doesn't require high efficiency), the reduced efficiency can be neglected.
          If efficiency was important (eg. if the code was in a rendering loop, which doesn't make sense, but let's say it was), you could split the string in 2 lines:

          Note that the second line cannot be indented, as the space would be part of the string.
          The messed up indentation is worse than exceeding 80 characters, so either keep the line as it is or split the output. The 80 character limit isn't a rule, it's a just a guideline.

          > enterOperator
          Line 8: You can't compare values like that.
          You first compare @userOperator to '+', this will evaluate to true if @userOperator is '+', as expected. The next expression is independent of the previous. '-' will be converted to a bool. Every non-zero value is true, so '-' is true and the if's condition is fulfilled.

          • Haydo

            That's what I meant just used wrong terms. Understood now though.

            All makes sense now though, as I thought I was just being an idiot.

            Thanks for that.

  • Anonymous

    Here is my gravity program: https://repl.it/@Cprogrammer/Gravity

    Any suggestions? I did it a little differently and a little clunkily too. I mainly wanted to not take up space by having lots of intermediate variables.

    • Hi!

      > I mainly wanted to not take up space by having lots of intermediate variables.
      You're using just as much memory as you'd do if your code was readable.

      main.cpp
      * The return value of @calculateAndPrintHeight is always the same as the value returned by @getHeight. Remove @calculateAndPrintHeight's return and store @getHeight's return value in a variable.

      constants.h
      * Use constexpr for compile-time constants

      functions.cpp
      * Line 6: Initialize your variables
      * Line 12: Variable names should be descriptive. Use single-letter names for iterators only.

      • Anonymous

        Updated based on your reccomendations: https://repl.it/@Cprogrammer/Gravity

        > * Line 6: Initialize your variables

        I didn't understand this. Elaborate? Do I have to initialize with blank values?

        > You're using just as much memory as you'd do if your code was readable.

        Why is that? I thought that having intermidiate variables would use up more memory as we now have to set aside memory for them.

        • > Elaborate

          This is the same as what you currently have, but this way even a non-cpp reader can know what the initial value of @height is. Initializing variables, even if they get overridden, places your program in a predictable state between declaration and assignment, which is good for debugging. It also prevents accidental use of uninitialized variables.

          > Why is that?
          When you're using the return value of a function without storing it, a temporary variable is created to store the return value.

          EDIT:
          * You're using the same name style for variables and functions. This can lead to confusion.
          * 0.5*constants::gravity could be stored in a constant so you don't have to recalculate it all the time

  • Anonymous

    Hey Alex! Nice to see the updated site.

    When I compile this(https://repl.it/@Cprogrammer/Calculator) or rather the part that has been commented out in main.cpp, it causes problems. More specifically the order of inputs is inverted. What could be the reason?

    • Hi!

      The evaluation order of function arguments is undefined. If you need your arguments to be evaluated in a specific order, do as you did in the code that works fine.

      • Anonymous

        Thanks! I have one question though. Why does it invert the order of the inputs specifically instead of doing something random everytime?

        • > instead of doing something random everytime?
          It is well defined what your compiler does, ie. the same will happen every time. But if you switch compilers, something else might happen. The behavior isn't standardized, so every compiler developer can make up something on their own.

          > Why does it invert the order of the inputs specifically
          I have to guess, because I'm not your compiler developer.
          I'm assuming you're compiling your program in 32bit x86. Most 32bit x86 calling conventions (if not all) pass arguments by pushing them onto the stack. They do so right-to-left. If you're calling a function and passing it's return value as an argument, the function call is only performed when the value is needed. Calling it earlier would be a waste of memory. Since arguments are pushed right-to-left, the second @getValue is called first, then @getOperator, followed by the first @getValue.

  • Hey, I finally got mine working but I noticed it's a bit different than the answer.  Also, I noticed that in the example answer they said the ball would have fallen 5 meters, and it's been 7 years since I've taken physics, but after one second shouldn't it have fallen 9.8 meters, then after two seconds 9.8 meters + (9.8 * 2)?  Anyways, I'll post my code, I appreciate any feedback.

    equations.h

    equations.cpp

    main.cpp

    • Note: I realize I used double for everything, I did this super late at night and was just trying to get it to work.

    • Hi Chris!

      > but after one second shouldn't it have fallen 9.8 meters
      Nope. After 1 second, your velocity is 9,8m/s. You fell 4,9m in that second. After 2 seconds you fell 19,6m. Wikipedia has all the handy formulas https://en.wikipedia.org/wiki/Equations_for_a_falling_body#Equations

      equations.cpp
      * Line 4: Initialize your variables with uniform initialization.
      * Line 5: Initialize your variables with uniform initialization. You used direct initialization.
      * @height should not be a global variable. Pass it around as an argument and return value.
      * Line 16, 22 and main.cpp line 8-13: Use double literals when calculating with doubles. (2.0 instead of 2, 0.0 instead of 0, etc.).
      * Line 23, 25: Duplicate code and strings. Use a conditional statement

      > I used double for everything
      double is the correct choice.

  • Oscar R.

    Hey Alex, I think the process you showed for Q3 is not a good practice because it disobeys the "One Function, One Purpose" rule that you talked about. In yours, printResult does two things - calculate the answer and print the result. Shouldn't those be two separate functions? Heres what I did.

    • Alex

      Your answer doesn't comply with the expected output of the program. It should print: 6.2 * 5 is 31, not "Your answer is: 31".

      For how you wrote your program, I think your answer makes sense. With my answer, both the text and the answer are conditional based on operator. I thought it was more comprehensible to combine them than have that conditional logic split out over two functions.

  • Oscar R.

    Shouldn't the answer for Q2A be const instead of int because the user's age does not change?

  • Sascha

    Hi my new compact code;

  • Sascha

    Hi, thats my solution of question nr.3

    • Hi Sascha!

      * Don't repeat code. It increases the binary's size and harder to update, often leading to undesired behavior.
      * Variable names should be descriptive
      * The first argument to @calc is unused
      * Initialize your variables with uniform initialization
      * Misleading formatting. Use the auto-formatting feature of your editor
      * Use double literals when calculating with doubles (2.0 instead of 2)

      Take a look at Alex' solution if you haven't already.

  • Oscar R.

    Hi, I'm getting an error when trying to compile a program i'm making and I do not understand the cause. Can you please help me?

    Error :

    ||=== Build: Debug in Area of Circle Calculator (compiler: GNU GCC Compiler) ===|
    D:\My Stuff\Projects\Learning C++\CBProjects\Area of Circle Calculator\main.cpp||In function 'int main()':|
    D:\My Stuff\Projects\Learning C++\CBProjects\Area of Circle Calculator\main.cpp|7|error: cannot convert 'float (*)()' to 'float' in initialization|
    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

    main.cpp:

    io.cpp:

    io.h:

Leave a Comment

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