S.4.x — Chapter 4 comprehensive quiz

Quick review

We covered a lot of material in this chapter. Good job, you’re doing great!

A block of statements (aka. a compound statement) is treated by the compiler as if it were a single statement. These are placed between curly brackets ({ and }) and used pretty much everywhere.

Local variables are variables defined within a function. They are created at the point of variable definition, and destroyed when the block they are declared in is exited. They can only be accessed inside the block in which they are declared.

Global variables are variables defined outside of a function. They are created when the program starts, and are destroyed when it ends. They can be used anywhere in the program. Non-const global variables should generally be avoided because they are evil.

The static keyword can be used to give a global variable internal linkage, so it can only be used in the file in which it is declared. It can also be used to give a local variable static duration, which means the local variable retains its value, even after it goes out of scope.

Namespaces are an area in which all names are guaranteed to be unique. Use of namespace is a great way to avoid naming collisions. Avoid use of “using statements” outside of functions.

Implicit type conversion happens when one type is converted into another type without using a cast. Explicit type conversion happens when one type is converted to another using a cast. In some cases, this is totally safe, and in others, data may be lost. Avoid C-style casts and use static_cast instead.

std::string offers an easy way to deal with text strings. Strings are always placed between double quotes.

Enumerated types let us define our own type where all of the possible values are enumerated. These are great for categorizing things. Enum classes work like enums but offer more type safety, and should be used instead of standard enums if your compiler is C++11 capable.

Typedefs allow us to create an alias for a type’s name. Fixed width integers are implemented using typedefs. Typedefs are useful for giving simple names to complicated types.

And finally, structs offer us a way to group related variables into a single structure and access them using the member selection operator (.). Object-oriented programming builds heavily on top of these, so if you learn one thing from this chapter, make sure it’s this one.

Quiz time!


1) In designing a game, we decide we want to have monsters, because everyone likes fighting monsters. Declare a struct that represents your monster. The monster should have a type that can be one of the following: an ogre, a dragon, an orc, a giant spider, or a slime. If you’re using C++11, use an enum class for this. If you’re using an older compiler, use an enumeration for this.

Each individual monster should also have a name (use a std::string), as well as an amount of health that represents how much damage they can take before they die. Write a function named printMonster() that prints out all of the struct’s members. Instantiate an ogre and a slime, initialize them using an initializer list, and pass them to printMonster().

Your program should produce the following output:

This Ogre is named Torg and has 145 health.
This Slime is named Blurp and has 23 health.

C++11 solution: Show Solution

non-C++11 solution: Show Solution

5.1 -- Control flow introduction
S.4.8 -- The auto keyword

206 comments to S.4.x — Chapter 4 comprehensive quiz

  • Jonathan

    The longest code I"ve ever wrote! Please give me some comment!

    • Jonathan

      I've updated a bit.

      • * Initialize your variables with brace initializers. If you add a member to @monsterData and forget to assign to it in @getMonsterInfo, this member will have an undefined value. Either initialize @monster, or all members in the struct definition.
        * You're using the same name style for variable, functions, and types. This will lead to confusion.
        * Avoid abbreviations. The time you save writing them is time wasted reading them. Code is more often read than written, you're wasting time.
        * Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
        * @getTBDA: You don't need temporaries, you can return directly

        * @traitString can always be determined by @trait. Remove the member and add a conversion function, just like you did with @getTypeString.
        * Inconsistent formatting. Use your editors auto-format feature.
        * @getTypeString::num should be an @monsterType.
        * Line 116, 123: Don't use string concatenation to print, use the stream's @operator<<.

        • Jonathan

          thanks for the detailed suggestions! For the function of getting string, is it better to use switch() instead of using if/else statement? I just go through the control flow!

          And for the abbreviation, I feel like "TBDA" seems to be more readable than "TraitBloodDefenceAttack".

          • > is it better to use switch() instead of using if/else statement?
            Whenever you have a limited set of values (eg. char, enum), use a switch. The compiler can optimize switch-statements better than if-statements.

            > I feel like "TBDA" seems to be more readable than "TraitBloodDefenceAttack"
            You might understand it, but everyone else who reads your code has no idea what TBDA is supposed to mean. And you won't either, if you look back at your code in a couple of months or years (You might not look back at this code, but some projects will require maintenance after a long time).

  • Merlin

    Is this a problem if I don't define an enum class? There is a shorter way and it works fine!
    (like the solution)

    I would really like to hear your thoughts about it, thanks! :)

  • Dimbo1911

    Any advices or suggestions on the following?

    • Hi!

      * Line 14, 15, 16: Initialize your variables with brace initializers.
      * @main: Missing return-statement.
      * Line 23-29 should use "else if". (Covered next chapter)
      * Line 39: Unnecessary space before line break.

      What's up with the Xs in front of every comment? It makes them harder to read.

      • Dimbo1911

        Thank you for your input, is there any difference in "if" and "else if", if every of the cases will result in return statements?
        Since they are not real comments but more of a to do list (I usually do not keep them in code, or move them to a different .txt file), I keep track of stuff I have doen with putting X in front of it haha

        • > is there any difference in "if" and "else if", if every of the cases will result in return statements?
          No. If conditions exclude each other, they should be in else-ifs. That way, if you decide to remove the return or replace it with something else, your code will still work as expected. It also allows a reader to understand your code without having to look at the if's body.

  • Mitchell Zakocs

    Just finished the quiz question, would love any criticism you can provide.

    • Hi Mitchell!

      * Line 12, 13, 14: Initialize your variables with brace initializers.
      * Line 32: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 20ff: Should be else-if.

  • Alireza

    Hi there,

    I've done that quiz. I think I've just used another way to do that, however.

    Is this code good to use the same ?

    • * Line 15, 16, 65: Initialize your variables with brace initializers. You used copy initialization.
      * Line 18, 21: Initialize your variables with brace initializers. You used direct initialization.
      * Line 15: Use @std::string's default constructor (ie. don't pass arguments).
      * Line 30-50: Should be else if.
      * @printMonsterStat doesn't need a forward declaration if it's declared above @setMonsterStat.

      They're called ogre.

  • Brian Gaucher

    I completed it solving all my issues alone, without peeking.
    But could I improve anything. (Looking for feedback)

    I also typed it all in Dvorak Programmer layout.

    • Hi Brian!

      * Line 13, 14, 15: Initialize your variables with uniform initialization.
      * @printType, @printMonster: Bad name
      * @printType: If you have a limited set of values, use a switch. It allows for better compile-time optimization.
      * @printType: Return a const char *. Constructing an @std::string every time @printType is called is slow.
      * @main: Missing return value

      > I also typed it all in Dvorak Programmer layout
      Let me know how it went once you got used to it. I've never learned it, because I'm afraid I'll forget qwerty and be lost when I have to use a regular layout. Switching from qwertz (ger) to qwerty (us) was a good step for me.

  • Rai

    I decided to make a small RPG. I'm having some problems so if anyone could help me out here.




    I was testing some stuff like auto and typedef.



    2. This works but I believe it causes a segementation fault?! The console just goes blank after you put a number. I tried with an online copiler instead and it showed an segementation error after std::cin >> number
    It seems to be std::string userFavColour causing the problem. (this happens when I type in the std::cin.ignore command to fix the first problem)

    3.Also I was wondering how to forward declare a enum statement, because all my code had to be squished into main.cpp

    • * Initialize your variables with uniform initialization
      * Use your editors auto-formatting feature and use curly brackets
      * Read compiler warnings and fix them
      * Use enum class instead of enum
      * Don't call @std::string::string manually
      * Inconsistent use of 'or' and '||'
      * Don't use @int16_t. Use @std::int_fast16_t or @std::int_least16_t
      * Line 151, 155: @printColour is called twice without the argument changing inbetween
      * Line 154, 155: Should be guarded by the if-else-statement below
      * Magic numbers

      @std::cin::operator>> extracts until '\n' and leaves '\n' in the input stream.
      @std::getline extracts everything and removes the '\n'. If '\n' is left in the input stream after an @std::cin.operator>> operation, @std::getline will extract the trailing '\n' and stop extraction. You need @std::cin.ignore

      You wrote 'n', not '\n'. @std::cin.ignore runs until it finds a 'n'. There is no 'n'. So it runs indefinitely.

      Use enum class. Enum class can be forward declared like everything else.
      If you want to forward declare an enum, you have to specify its size

      • Rai

        Thank you. The main problem was that I used 'n' instead of '\n' for std::cin.ignore. Silly me.

        why use int_fast16_t or int_least16_t ? whats the difference?

        where did I call std::string::string manually?

        Can you not forward declare enum class? I tried this but wasn't working.

        • > why use int_fast16_t or int_least16_t ? whats the difference?
          @std::int16_t is implementation defined, ie. not all compilers support it.
          @std::int_least16_t is the smallest integer type with at least 16 bits.
          @std::int_fast16_t is the fastest integer type with at least 16 bits

          > where did I call std::string::string manually?
          Line 96, 98, 100, 101, 108, 110, 112, 114, 115, 125. You didn't in @getMonsterIDString

          > Can you not forward declare enum class? I tried this but wasn't working.

  • Boteomap2

    Hi... let give me some advice for code better....



  • Dean Cutillar

    I wrote a program to solve this assignment but I used a enum class called "monsterType", which held the type of monster, and a class called "individualMonster", which held the type, name, and health points as members.

    I got it working with an array of type "individualMonster", and wanted to have it work with a vector of "individualMonster".  

    My program has the user input all the monster info, from the keyboard.

    I was able to get it to work using regular for loops, but was not able to print out the vector using a "for each" loop.  Below is the code for the program.  Please let me know how to code it using a for each loop.  Thanks.


    #define MAX_MONSTERS 5

    enum class monsterType {
        OGRE = 1,

    class individualMonster {
        monsterType m_type;
        std::string m_name;
        int m_health;
        monsterType setMonsterType();
        void setMonster();
        void printMonster();

    monsterType individualMonster::setMonsterType() {
        bool validInput = false;
        int userInput;
        while (!validInput) {
            std::cout << "Please enter monster type: \n";
            std::cout << "Enter numbers\n1) Ogre\n" << "2) Dragon\n" << "3) Orc\n" <<
                "4) Giant Spider\n" << "5) Slime\n";

            std::cin >> userInput;
            std::cin.ignore(1000, '\n');
            if ((userInput > 0) && (userInput < 6))
                validInput = true;
                std::cout << "Please enter number between 1 and 5\n";
        return static_cast<monsterType>(userInput);

    void individualMonster::setMonster() {
        m_type = individualMonster::setMonsterType();
        std::cout << "Please enter monster name: ";
        std::cin >> m_name;

        bool validInput = false;
        while (!validInput) {
            std::cout << "Please enter monster health with a number greater than zero, less than 100:\n ";
            int userInput;
            std::cin >> userInput;
            std::cin.ignore(50, '\n');
            if ( // has a previous extraction failed?
                // yep, so let's handle the failure
                std::cin.clear(); // put us back in 'normal' operation mode
                std::cin.ignore(32767, '\n'); // and remove the bad input
            else {// else our extraction succeeded
                m_health = userInput;
                validInput = true;

    void individualMonster::printMonster() {
        std::cout << "This";
        switch (m_type) {
        case monsterType::OGRE:
            std::cout << " Ogre ";
        case monsterType::DRAGON:
            std::cout << " Dragon ";
        case monsterType::ORC:
            std::cout << " Orc ";
        case monsterType::GIANT_SPIDER:
            std::cout << " Giant Spider ";
        case monsterType::SLIME:
            std::cout << " Slime ";
            std::cout << " Unknown";
        std::cout << "is named " << m_name << " and has " << m_health << " health.\n";

    int main() {
        std::vector<individualMonster> monsterArray[MAX_MONSTERS];

        bool userDone = false;
        int counter = 0;
        while (!userDone) {
            individualMonster temp;
            std::cout << "Enter details for Monster number: " << counter + 1 << std::endl;
            std::cout << "Done entering Monsters? \n";

            std::string userResponse;

            std::cin >> userResponse;
            if (userResponse == "y") {
                userDone = true;

        std::cout << "Here are your Monsters: \n";
        for (int index = 0; index <= counter; index++) {
        /* int ind = 0;
        for (individualMonster &index : monsterArray) {
            std::cout << "index number " << ind << std::endl;
            std::cout << "index number " << ind << std::endl;
        }  */

        //pause code
        int pause;
        std::cin >> pause;
        std::cin.ignore(1000, '\n');

        return 0;

    • @monsterArray is an array of vectors. It should be

      Once you've done that, the loop you commented out will work. It will break other parts of your code, which you have to fix.

      * Initialize your variables with uniform initialization
      * Read the documentation of @std::cin.ignore
      * Don't use preprocessor macros for constants
      * You're using the same name style for functions, variables and types. This will lead to confusion
      * @monsterType::OGRE doesn't need to be set to 1, because 1 is the default value
      * You don't need to return from a void
      * Inconsistent use of curly brackets. Always use curly brackets

  • Ajalle Perfej

    The solution just returns a string constant and then prints what is returned to the console. Is there a way to have the monster names and health assigned to variables connected to the relevant struct enums?

  • mjr

    I've been looking over this and I don't know why it isn't working.

  • Outrageous Gem

    How would I sort this programm if I wanted to separate it into multiple files?

    "enum class MonsterType" and "struct Monster" could probably just be defined inside a header "monster.h" but where would I put "getMonsterTypeString(Monster monster)" ? Put it into a monster.cpp and forward declare it in monster.h?

  • emanon

    I have 2 questions.

    why did we have to use "monster.type" here? I dont really understand the use of the "."
    and the next question is,

    why did we use the "::" here?

    I probably should revisit where that was explained but I coudnt find it, it would be very kind if you can tell me which lessen to reread, thank you very much!

  • kaden

    my program is not working
    i can not find the reason for 2days.
    is there any problem in my code?

  • DAT


    enum class Monster

    struct MonsterDescript
        Monster type;
        int health;
        std::string name;

    std::string monsterType(Monster x)
        if (x == Monster::ORC)
            return "Orc";
        else if (x == Monster::ORGE)
            return "Orge";
        else if (x == Monster::SLIME)
            return "Slime";
        else if (x == Monster::DRAGON)
            return "Dragon";
            return "Unknown";

    void printInformation(MonsterDescript x)
        std::cout << "this " << monsterType(x.type) << " is named " << << " and has " << << " health.";
        std::cout << "\n";

    int main()
        MonsterDescript adam{ Monster::ORC,145,"Stupid" };
        MonsterDescript eva{ Monster::DRAGON,235,"Adam" };
        return 0;

Leave a Comment

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