6.x — Chapter 6 comprehensive quiz

Words of encouragement

Congratulations on reaching the end of the longest chapter in the tutorials! Unless you have previous programming experience, this chapter was probably the most challenging one so far. If you made it this far, you’re doing great!

The good news is that the next chapter is easy in comparison. And in the chapter beyond that, we reach the heart of the tutorials: Object-oriented programming!

Chapter summary

Arrays allow us to store and access many variables of the same type through a single identifier. Array elements can be accessed using the subscript operator ([]). Be careful not to index an array out of the array’s range. Arrays can be initialized using an initializer list or uniform initialization (in C++11).

Fixed arrays must have a length that is set at compile time. Fixed arrays will usually decay into a pointer when evaluated or passed to a function.

Loops can be used to iterate through an array. Beware of off-by-one errors, so you don’t iterate off the end of your array. For-each loops are useful when the array hasn’t decayed into a pointer.

Arrays can be made multidimensional by using two indexes.

Arrays can be used to do C-style strings. You should generally avoid these and use std::string instead.

Pointers are variables that store the memory address of (point at) another variable. The address-of operator (&) can be used to get the address of a variable. The dereference operator (*) can be used to get the value that a pointer points at.

A null pointer is a pointer that is not pointing at anything. Pointers can be made null by initializing or assigning the value 0 (or in C++11, nullptr) to them. Avoid the NULL macro. Dereferencing a null pointer can cause bad things to happen. Deleting a null pointer is okay (it doesn’t do anything).

A pointer to an array doesn’t know how large the array they are pointing to is. This means sizeof() and for-each loops won’t work.

The new and delete operators can be used to dynamically allocate memory for a pointer variable or array. Although it’s unlikely to happen, operator new can fail if the operating system runs out of memory, so make sure to check whether new returned a null pointer.

Make sure to use the array delete (delete[]) when deleting an array. Pointers pointing to deallocated memory are called dangling pointers. Dereferencing a dangling pointer can cause bad things to happen.

Failing to delete dynamically allocated memory can result in memory leaks when the last pointer to that memory goes out of scope.

Normal variables are allocated from limited memory called the stack. Dynamically allocated variables are allocated from a general pool of memory called the heap.

A pointer to a const value treats the value it is pointing to as const.

A const pointer is a pointer whose value can not be changed after initialization.

A reference is an alias to another variable. References are declared using an ampersand, but this does not mean address-of in this context. References are implicitly const -- they must be initialized with a value, and a new value can not be assigned to them. References can be used to prevent copies from being made when passing data to or from a function.

The member selection operator (->) can be used to select a member from a pointer to a struct. It combines both a dereference and normal member access (.).

Void pointers are pointers that can point to any type of data. They can not be dereferenced directly. You can use static_cast to convert them back to their original pointer type. It’s up to you to remember what type they originally were.

Pointers to pointers allow us to create a pointer that points to another pointer.

std::array provides all of the functionality of C++ built-in arrays (and more) in a form that won’t decay into a pointer. These should generally be preferred over built-in fixed arrays.

std::vector provides dynamic array functionality that handles its own memory management and remember their size. These should generally be favored over built-in dynamic arrays.

Quiz time

1) Pretend you’re writing a game where the player can hold 3 types of items: health potions, torches, and arrows. Create an enum to identify the different types of items, and a fixed array to store the number of each item the player is carrying (use built-in fixed arrays, not std::array). The player should start with 2 health potions, 5 torches, and 10 arrows. Write a function called countTotalItems() that returns how many items the player has in total. Have your main() function print the output of countTotalItems().

Show Solution

2) Write the following program: Create a struct that holds a student’s name and grade (on a scale of 0-100). Ask the user how many students they want to enter. Dynamically allocate an array to hold all of the students. Then prompt the user for each name and grade. Once the user has entered all the names and grades, sort the list by grade (highest first). Then print all the names and grades in sorted order.

For the following input:


The output should look like this:

Alex got a grade of 94
Mark got a grade of 88
Joe got a grade of 82
Terry got a grade of 73
Ralph got a grade of 4

Hint: You can modify the selection sort algorithm from lesson 6.4 -- Sorting an array using selection sort to sort your dynamic array.

Show Solution

3) Write your own function to swap the value of two integer variables. Write a main() function to test it.

Hint: Use reference parameters

Show Solution

4) Write a function to print a C-style string character by character. Use a pointer to step through each character of the string and print that character. Stop when you hit a null terminator. Write a main function that tests the function with the string literal “Hello, world!”.

Hint: Use operator++ to advance the pointer to the next character

Show Solution

5) What’s wrong with each of these snippets, and how would you fix it?


Show Solution


Show Solution


Show Solution


Show Solution


Show Solution

6) Let’s pretend we’re writing a card game.

6a) A deck of cards has 52 unique cards (13 card ranks of 4 suits). Create enumerations for the card ranks (2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace) and suits (clubs, diamonds, hearts, spades).

Show Solution

6b) Each card will be represented by a struct named Card that contains a rank and a suit. Create the struct.

Show Solution

6c) Create a printCard() function that takes a const Card reference as a parameter and prints the card rank and value as a 2-letter code (e.g. the jack of spades would print as JS).

Show Solution

6d) A deck of cards has 52 cards. Create an array (using std::array) to represent the deck of cards, and initialize it with one of each card.

Hint: Use static_cast if you need to convert an integer into an enumerated type.

Show Solution

6e) Write a function named printDeck() that takes the deck as a const reference parameter and prints the values in the deck. Use a for-each loop.

Show Solution

6f) Write a swapCard function that takes two Cards and swaps their values.

Show Solution

6g) Write a function to shuffle the deck of cards called shuffleDeck(). To do this, use a for loop to step through each element of your array. Pick a random number between 1 and 52, and call swapCard with the current card and the card picked at random. Update your main function to shuffle the deck and print out the shuffled deck.

Hint: Review lesson 5.9 -- Random number generation for help with random numbers.
Hint: Don’t forget to call srand() at the top of your main function.
Hint: If you’re using Visual Studio, don’t forget to call rand() once before using rand.

Show Solution

6h) Write a function named getCardValue() that returns the value of a Card (e.g. a 2 is worth 2, a ten, jack, queen, or king is worth 10. Assume an Ace is worth 11).

Show Solution

7) Alright, challenge time! Let’s write a simplified version of Blackjack. If you’re not already familiar with Blackjack, the Wikipedia article for Blackjack has a summary.

Here are the rules for our version of Blackjack:
* The dealer gets one card to start (in real life, the dealer gets two, but one is face down so it doesn’t matter at this point).
* The player gets two cards to start.
* The player goes first.
* A player can repeatedly hit or stand.
* If the player stands, their turn is over.
* If the player hits, they get another card and the value of that card is added to their total score.
* An ace normally counts as a 1 or an 11 (whichever is better for the total score). For simplicity, we’ll count it as an 11 here.
* If the player goes over a score of 21, they bust and lose immediately.
* The dealer goes after the player.
* The dealer repeatedly draws until they reach a score of 17 or more, at which point they stand.
* If the dealer goes over a score of 21, they bust and the player wins immediately.
* Otherwise, if the player has a higher score than the dealer, the player wins. Otherwise, the player loses.

In our simplified version of Blackjack, we’re not going to keep track of which specific cards the player and the dealer have been dealt. We’ll only track the sum of the values of the cards they have been dealt for the player and dealer. This keeps things simpler.

Start with the code you wrote in quiz #6. Create a function named playBlackjack() that returns true if the player wins, and false if they lose. This function should:
* Accept a shuffled deck of cards as a parameter.
* Initialize a pointer to the first Card named cardPtr. This will be used to deal out cards from the deck (see the hint below).
* Create two integers to hold the player’s and dealer’s total score so far.
* Implement Blackjack as defined above.

Hint: The easiest way to deal cards from the deck is to keep a pointer to the next card in the deck that will be dealt out. Whenever we need to deal a card, we get the value of the current card, and then advance the pointer to point at the next card. This can be done in one operation:

This returns the current card’s value (which can then be added to the player or dealer’s total), and advances cardPtr to the next card.

Show Solution

6h) Extra credit: Critical thinking time: Describe how you could modify the above program to handle the case where aces can be equal to 1 or 11.

Hint: It’s important to note that we’re only keeping track of the sum of the cards, not which specific cards the user has.

Show Solution

7.1 -- Function parameters and arguments
6.16 -- An introduction to std::vector

191 comments to 6.x — Chapter 6 comprehensive quiz

  • Brad

    I wanted to try to create a function out of the "creation step" of the deck, so that if we wanted to create multiple decks (ie. deck1, deck2, etc), we could do so with ease.  My concern here is if this will create copies and impact performance or create leaks? Here’s the relevant code:

    Compiles and run’s fine.

    • Alex

      This program only “runs fine” because you aren’t doing anything with deck1. I’m surprised your compiler doesn’t complain.

      The big flaw here is that your createDeck() function returns a reference to a local variable. That’s a no-no. When your deck variable goes out of scope at the end of the function, it will get destroyed. Then what you end up passing back to main() is a destroyed variable. When you try to use it, you’ll get undefined results.

      There are several ways you can deal with this. But the easiest one is to have main() create an empty deck, pass it into createDeck() as a reference parameter, have createDeck() fill up the deck, and return it. That way you know the deck you return won’t have gone out of scope when it returns back to main because main created it.

      Other ways would be to create a Deck object dynamically rather than as a local variable. Dynamic memory doesn’t go out of scope at the end of a function, so you could return a pointer to the Deck at the end of the function. This might be more syntactically aligned with how you’re thinking about things. But don’t forget to delete the pointer when you’re done.

      • Brad

        Thanks for the feedback. Weird, I’m using the GNU code::blocks compiler. I even continued on with the quiz and made the shuffle function and used it on deck1 (without any problems that I noticed). It must be that deck1 is still pointing to the memory addresses of the destroyed local variable "deck", but nothing has overwritten those memory addresses yet (but could down the line, and then things would be messed up and probably crash). I tried compiling using cloud9 and it indeed threw a warning about returning a referenced local variable. So I understand your part about making it dynamic, does this mean I could just change the type from std::array to std::vector and I wouldn’t need to delete any pointers since the vector class handles all of that for you?

        • Alex

          No, swapping out std::array for std::vector won’t solve the issue -- either way, the variable will go out of scope at the end of the createDeck() function and clean up after itself. The fact that vector does dynamic allocation internally is immaterial. What I was suggesting was something like this:

          Since you’re doing the allocation here, you’re responsible for cleaning it up.

          • Brad

            I tried using the vector instead of the array and it compiled and ran fine (before your reply, on more than one compiler) and had no compiler issues and no visible memory issues. So I was curious to why it worked and did a little research. According to this, it’s fine as long as you aren’t returning the local variable by reference:

            The vector is copied into the variable it is being returned to, and then the local variable is destroyed. I’m guessing this is okay on a small scale (ie. 52 array deck of cards), but on a large scale, such as a data file, we wouldn’t want to copy the entire data file to the other variable once it’s already been populated to a local variable? Is this where your pointer implementation or the idea of creating the array in main and then passing it by reference would be beneficial?

            EDIT: Oh looks like compilers can optimize the process so it does not copy, but rather move instead (c++11 or newer):
            So I guess we don’t have to worry about returning a large vector that was created in a function.

            • Alex

              Yes, in C++11, std::vector is move-capable, so if you return it by value, it will “move” its content instead of making a copy. I cover this in chapter 15. This does not apply if you return it by reference.

  • mat

    Thank you for the words of encouragement and for the tutorials so far!

  • loveu

    why dont you use a for each loop for your shuffle function?

    and as always thanks for such a great tutorial!

  • Andy

    This code prints 317162.
    Why doesn’t it prints deck[1]?

  • Sihoo

    The blackjack problem was stunning. I really enjoyed trying to code the problem & it was really good practice to review and apply the concepts learned in the previous chapters. I really appreciate it Alex.

  • Jonas

    Hi alex! great site of yours.
    Now it is my problem:
    in initDeck I get compiler error  "no match for operator [] operand types are ‘Card’ and ‘int’"  

    #include <iostream>
    #include <array>
    #include <cstdlib> // for rand() and srand()
    #include <ctime>   // for time()
    using namespace std;

    enum   CardRank {C2,C3,C4,C5,C6,C7,C8,C9,C10,JACK,QUEEN,KING,ACE, MAX_RANK};
    struct Card {CardRank rnk; CardSuit suit;}; int LEN=MAX_SUIT*MAX_RANK;

    int  randMinMax(const int min,const int max)  { static const auto r = RAND_MAX+1; return static_cast<int>(((double)rand()/r)*(max-min+1)+min); }
    void mswp(auto &x,auto &y) {auto tmp=x;x=y,y=tmp;}
    void shuffleDeck(auto &a)  {for(auto &item : a) a[randMinMax(0,a.size()-1)]=item;}
    //int  getCardValue(const auto &val) { if (IsB10(val)&&(val!=ACE)) return static_cast<int>(val+2); if (val==ACE) return 11;  return 10; }
    void printCard(const auto &c)
        switch (c.rnk)
            case C10  :cout<<‘T’;break;
            case JACK :cout<<‘J’;break;
            case QUEEN:cout<<‘Q’;break;
            case KING :cout<<‘K’;break;
            case ACE  :cout<<‘A’;break;
            default   :cout<<static_cast<char>(‘2’+c.rnk);
        switch (c.suit) { case SUIT_CLUB    :cout<<‘C’;break; case SUIT_DIAMOND :cout<<‘D’;break; case SUIT_HEART   :cout<<‘H’;break; case SUIT_SPADE   :cout<<‘S’;break;};
    void initDeck(Card &d)
       for(int i=0; i<MAX_SUIT;++i)
            for (int j=0; j<MAX_RANK; ++j)
                d[i*j+j].suit=static_cast<CasrSuit> (i);
                d[i*j+j].rnk =static_cast<CardRank> (j);

    void printDeck(const auto &adeck) {  int i=0; for(const auto &card: adeck) { ++i; printCard(card); cout<<‘ ‘; if (i%13==0) cout<<‘\n’; }; }

    int main()
    array<Card,52> aDeck;
    return 0;
    in initDeck I get compiler error #include <iostream>
    #include <array>
    #include <cstdlib> // for rand() and srand()
    #include <ctime>   // for time()
    using namespace std;

    enum   CardRank {C2,C3,C4,C5,C6,C7,C8,C9,C10,JACK,QUEEN,KING,ACE, MAX_RANK};
    struct Card {CardRank rnk; CardSuit suit;}; int LEN=MAX_SUIT*MAX_RANK;

    int  randMinMax(const int min,const int max)  { static const auto r = RAND_MAX+1; return static_cast<int>(((double)rand()/r)*(max-min+1)+min); }
    void mswp(auto &x,auto &y) {auto tmp=x;x=y,y=tmp;}
    void shuffleDeck(auto &a)  {for(auto &item : a) a[randMinMax(0,a.size()-1)]=item;}
    //int  getCardValue(const auto &val) { if (IsB10(val)&&(val!=ACE)) return static_cast<int>(val+2); if (val==ACE) return 11;  return 10; }
    void printCard(const auto &c)
        switch (c.rnk)
            case C10  :cout<<‘T’;break;
            case JACK :cout<<‘J’;break;
            case QUEEN:cout<<‘Q’;break;
            case KING :cout<<‘K’;break;
            case ACE  :cout<<‘A’;break;
            default   :cout<<static_cast<char>(‘2’+c.rnk);
        switch (c.suit) { case SUIT_CLUB    :cout<<‘C’;break; case SUIT_DIAMOND :cout<<‘D’;break; case SUIT_HEART   :cout<<‘H’;break; case SUIT_SPADE   :cout<<‘S’;break;};
    void initDeck(Card &d)
       for(int i=0; i<MAX_SUIT;++i)
            for (int j=0; j<MAX_RANK; ++j)
                d[i*j+j].suit=static_cast<CasrSuit> (i);
                d[i*j+j].rnk =static_cast<CardRank> (j);

    void printDeck(const auto &adeck) {  int i=0; for(const auto &card: adeck) { ++i; printCard(card); cout<<‘ ‘; if (i%13==0) cout<<‘\n’; }; }

    int main()
    array<Card,52> aDeck;
    return 0;

  • Gapo

    Hey Alex , I went back a little bit to practice quizes from older lessons and I just realised I don’t know how to properly validate string input , this function still accepts intiger input  :

  • Hugh

    Hi, love the tutorials. I’m pretty new and I’ve been struggling through the quiz challenge for a few hours. I thought I finally had it down and I understood everything but everytime I try to run it, the app crashes and tells me that the "array subscript has gone out of range" and points to the same line no matter what I change. The line is

    and the full code follows if you’re interested

    • Alex

      (snipping your code since it’s long)

      This is where you should be using a debugger. Run your program in debug mode, and when it crashes, drop into debugging mode and inspect the variables to see what values they have.

      The problem is in this loop:

      Inspection shows that card has value 52 (when it should never go above 51), which is why it’s crashing. So how did it get to 52? The loop conditions must be incorrect. Looking at the loop variables, rank has value 52 and suit has value 0, which is clearly wrong. That indicates maybe the problem is in your loop conditions. 🙂 See the error yet?

      • Hugh

        I’m afraid I don’t. I’ve been looking at the debugger but for now its gibberish to me. Give me an hint, is my problem solely in this loop or do I need to be looking at the enum’s or something?

      • Hugh

        I think what you’re saying is that the loop isn’t working for the suits but it is for rank (or something along those lines). Why that might be I’m not sure

        • Alex

          Here’s how you can debug this: put a breakpoint on int card = 0, then step through your loop, line by line. Watch the value of the variables (suit, rank, and card).

          From your code, you’re clearly intending the following:
          suit should range from 0 to 3
          rank should range from 0 to 11

          What you will see is that suit starts iteration 0, then rank starts counting up with each iteration… 0, 1, 2, 3, etc… It should stop when it gets to 12, but it doesn’t. It keeps going. This implies there’s a bug in the stop condition of this line of code:

          Do you see it yet?

          Hint: one of these things is not like the other

          • Hugh

            oh dear lord I’ve just seen it… I guess all I can say is thank you for your patience. I’m amazed that I managed to overlook that. Thanks for you help

            • Alex

              It’s so so easy to make simple mistakes like that, and they can be _very_ difficult to find, especially without a debugger. Now that you know where the error is, use this as an opportunity to get more comfortable with your debugger -- breakpoint the area and step through your code and watch how it goes wrong.

          • Hugh

            So everything works nicely now and I’ve got a do while loop in there again so people can play again if they want (which may not sound amazing but I’m pretty happy that I managed to do on my own) but I’ve noticed that sometimes a card can be dealt with a value of 0? Like the dealer sometimes starts on 0 or a move results in no change in his overall value

            • Alex

              My best guess: getCardValue() is returning 0 in some case.

              Run your code in the debugger, and put a breakpoint on the line that returns 0. See if it gets hit. If it does, you can inspect the Card parameter to see what’s wrong with it. Then you can backtrace (look at the caller) to figure out where that Card is coming from (how it’s being created or getting its values erroneously).

  • saeid

    hi Alex.
    in quiz 6 i follow the quiz and in fact i wrote codes 40% of total and i had to look at the solutions you writhed. given that i’m new in c++ and i just learning c++ with your tutorials is this normal or not?

    • Alex

      The quizzes are meant to be challenging, and point out where you may need extra study. If you couldn’t answer one of the quiz questions, make sure you can at least understand the provided answer, and where your knowledge was lacking. You may also want to find additional supplemental material on the topic.

  • Elruin

    I have tryed to use everything i can think of in this quiz#2. Vector, for each loops, std::cin checks… I know there is nasty nasting. I would like to hear about mistakes etc.

  • Zee

    Okay, so obviously I didn’t exactly follow the "not keeping track of cards" bit, and it took me a while to figure out how to count the ace correctly.
    This is the final version I wrote, and I’m wondering if there’s anything that stands out as bad (structure or solution-wise).
    It was repeatedly tested with almost the entire deck being aces before I figured out my mistakes and had to rewrite everything related to counting the score. (Always counting the first ace as 11 was my biggest problem.)

  • Michiel

    I think i got a much easier solution to exercise 6h)

  • Jonas

    I have written 6d) like this:

  • Doe

    You an use the std::sort function instead of your own. On quiz #2 you can do it like:

  • DemonFace

    I already made a Blackjack program during or after chapter 5, with the knowledge I knew that time. I’m proud of myself 😀

  • Jared

    Hey, Sensei Alex!
    … I got stuck on Quiz #2
    In the following excerpt:

    The segment of code "sortStudents(students, numOfStudents);" prints the following error "no suitable conversion function from "std::vector<Student, std::allocator<Student>>" to "Student *" exists". When I comment the statement out, the program works just fine. Anyways, I tried to make this issue as clear and concise as I can to help save your time, and just in case, in advance, thanks for the help <3.

    • Alex

      You’re mixing your types here. Your students variable is of type std::vector, but your sortStudents() function is expecting a Student pointer. C++ doesn’t know how to convert one to the other.

      If you make your function parameter of type “std::vector &” then it will compile and works as you expect.

  • Mike

    Why isn’t this compiling please help Alex and others.
    #include "stdafx.h"
    #include <iostream>
    #include <array>
    #include <ctime>
    #include <random>
    using namespace std;

    enum  Cardrank


    enum  Suit


    struct everycard
        Suit suits;
        Cardrank cards;
    void printCard(const everycard &card)
        switch (
        case _1:                          cout << "1"; break;
        case _2:                          cout << "2"; break;
        case _3:                          cout << "3"; break;
        case _4:                          cout << "4"; break;
        case _5:                          cout << "5"; break;
        case _6:                          cout << "6"; break;
        case _7:                          cout << "7"; break;
        case _8:                          cout << "8"; break;
        case _9:                          cout << "9"; break;
        case _10:                          cout << "10"; break;
        case Jack:                          cout << "J"; break;
        case Queen:                          cout << "Q"; break;
        case King:                          cout << "K"; break;
        case Ace:                          cout << "A"; break;

        switch (card.suits)
        case Club: cout << "C"; break;
        case Diamond: cout << "D"; break;
        case Heart: cout << "H"; break;
        case Spade: cout << "S"; break;


    void printdeck(array<everycard, 52> &deck)
        for (auto &card : deck)

            cout << " ";
        cout << ‘\n’;
    void swapCard(everycard &a, everycard &b)
        everycard dor = a;
        a = b;
        b = dor;

    int getRandomNumber(int min, int max)
        static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);  // static used for efficiency, so we only calculate this value once
                                                                                     // evenly distribute the random number across our range
        return static_cast<int>(rand() * fraction * (max - min + 1) + min);

    void shuffleDeck(std::array<everycard, 52> &deck)
        // Step through each card in the deck
        for (int index = 0; index < 51; ++index)
            // Pick a random card, any card
            int swapIndex = getRandomNumber(0, 51);
            // Swap it with the current card
            swapCard(deck[index], deck[swapIndex]);
    int getCardValue(everycard &card)
        switch (
        case _1:                          return 1;
        case _2:                       return    2;
        case _3:                         return  3;
        case _4:                     return      4;
        case _5:                           return 5;
        case _6:                          return 6;
        case _7:                           return 7;
        case _8:                            return 8;
        case _9:                           return 9;
        case _10:                         return  10;
        case Jack:                        return  10;
        case Queen:                       return  10;
        case King:                        return  10;
        case Ace:                         return  11;

        return 0;

    int main()

        array <everycard, 52> deck;

        int card = 0;
        for (int suit = 0; suit < 13; ++suit)
            for (int rank = 0; rank < 5; ++rank)
                deck[card].suits = static_cast<Suit>(suit);
                deck[card].cards = static_cast<Cardrank>(rank);

        return 0;

    • Alex

      It compiles fine for me (but crashes when running). What compile error are you getting?

      • Mike

        Sometimes it randomly throws of an error that can’t open the file which contains solution, but it crashes everytime too.
        Why does it crash ?

        • Alex

          If you run your program in a debugger it should tell you.

          The problem is this line:

          This is causing an out of array bounds issue (rank should go from 0 to 3, not 0 to 4).

  • Nelson

    Hi Alex,

    Thx for all this information, it’s been a very nice read!

    Now, when writting my code for the card game, i got stuck in 6g and when I solved this issue, I never really understood what happened.

    I created several files for the project.  I included my enums in the header "Enums.h", my functions in a separate file named "Functions.cpp" and added a header for forward declarations named "Forwards.h"

    It all worked well until I wrote shuffleDeck().  At this point, i always got the error

    error LNK2019: unresolved external symbol "void __cdecl shuffleDeck(class std::array<struct Card,52> const &)"

    I read my function over and over, it was fine.  So, I moved the function definition to the same .cpp where my main() was, and voila, it all worked.

    So, my question is: Why did this particular forward prototype gave an error or why did it work when i moved the function to the same file where my main() was?

    Hope I was clear explaining my doubt.  
    Thanks in advance,

    • Alex

      I’m… not sure. It sounds like maybe the function wasn’t getting compiled when it lived in the header file. Either the header wasn’t being properly included or the header guards were preventing compilation for some reason.

      As a side note, organizing your code by “function” (enums, functions, forwards, etc…) generally isn’t the best way to organize. You’re better off organizing by feature area (Card, Deck, game, etc…).

  • Gapo

    Is it bad if I almost always need to look into solutions in order to finish my quiz ?

    • Alex

      It’s not ideal. But comparing the reference solutions with your provides another avenue for learning. As long as you’re reading the solutions and understanding them (and where you went wrong), you’re probably okay. You might want to find some additional quizzes on other sites to reinforce your learning.

      • Mateo

        Thank you for replying Alex .
        I will just keep trying until I make sure I understood the whole chapter. I do sometimes feel to stupid for this but that’s not gonna stop me. This is my first programming language ever so it was probably a bad idea to choose such a hard language as my first one . Anyway I love c++ and I won’t rest till I master it .

        • Alex

          C++ certainly isn’t the easiest language to learn -- other toy languages like Pascal are a bit easier because they are simpler. But the advantage of C++ is that you’re learning something that’s actually useful. Nobody writes applications in Pascal. Stick with it!

  • Andy

    Hi There, love this site.
    I have completed question 2 but now instead of my own sort i am trying to use std::sort from <algorithm> but getting a compiler error.

    I am using :

    and i get an compiler code:
    error: request for member ‘begin’ in ‘students’, which is of pointer type ‘Student*’ (maybe you meant to use ‘->’ ?)|

    error: request for member ‘end’ in ‘students’, which is of pointer type ‘Student*’ (maybe you meant to use ‘->’ ?)|
    Can you provide some insight as to what i am doing wrong?

    • Alex

      Yup, but explaining it in a way that makes sense at this point in the tutorials is a little difficult.

      std::sort is implemented using iterators (a topic that I haven’t really written a tutorial about yet, but plan to soon). Basically, iterators provide an abstract way to step through each element in a container (such as an array). begin() is typically used to get an iterator to the first element, and end() is typically a special symbol representing the end of the list.

      The problem here is that students is a C-style array. C-style arrays don’t know anything about iterators.

      So, the simplest solution here would be to change students to a std::array or std::vector, as both of those classes contain built-in support for iterators.

  • Turya


    Just wanted to crosscheck the extra credit problem. Any comment is welcome

  • Matt

    I loved your Blackjack challenge. I finally wrote a program that seems to serve a purpose… and I only cheated on the random number formula.

    Also, I noticed a mistake in your blackjack solution. When the dealer is dealt his first card, the comment says the the player is given the card.

  • asker

    Help me the question commented in the code bellow:

    Thanks in advance.

    Edit: ah, I’ve seen that the variable total is not set to 0. 😀

    Edit2: After I edited this post, the [code] tag would not work??? Sorry if it’s my mistake.

  • Kees

    I made a typo in the code of question 4. (std::cout << str; instead of std::cout << *str;)
    The result was:

    Hello World!ello World!llo World!lo World!o World! World!World!orld!rld!ld!d!!

    Why does i print this?

    • Alex

      str is a pointer to a char. std::cout assumes that pointers to chars are meant to be printed as strings, and will print everything from the first character being pointed to until it hits a null terminator. So first, str points to the H in Hello world!, which prints the entire string “Hello world!”. Then you increment str, so it now points the e, which prints “ello world”. And so on, until str points to the string’s null terminator and the loop condition exits.

  • Kārlis

    So I wrote a code for Blackjack game. I wanted for program to show not only score but drawed card as well. The code got longer and didn`t look good. To make code more readable I invented new enum:

    Now I want to make a single function drawCard(PlayerType playertype) which would contain printCard(..) and getCardValue(..) so that my main() would look like this

    can I declare both dealer and player scores as global variable so that drawCard() would change the value if them accourding of input(player/dealer)? In tutorial you suggested to stay away from them. Is there a way to reset the value of glabal variable if I wanted to implement play again function?

    • Alex

      I still suggest you stay away from them. Instead, I suggest you pass playerTotal and dealerTotal as reference parameters to your drawCard() function. This will allow drawCard() to modify those values directly. See lesson 7.3 if you need more help with reference parameters.

  • Kārlis

    Why is it neccessary to write:

    int getCardValue(const Card &card)

    in task 6h instead of just:

    int getCardValue(Card card)


    • Alex

      It’s not necessary, it just avoids an making an unnecessary copy. In the latter case, the value of the argument will be copied into parameter card. In the former, reference variable card will be used as an alias for the argument, so no copy is made.

  • HI Alex,
    Having one doubt.
    While trying to print the deck. I used value "10" instead of "T" like "case RANK_10:std::cout << ’10’; break;" here am a using value10instead of ‘T’. But am getting some garbage value instead of 10. why it’shappening

  • Alexander

    Can’t really decide whether to be proud of my elegant solution to 6e), or ashamed that the reason I tried to find a substitute for the obvious switch was literally just that I was too lazy to type that much! I guess programming is about optimization, so… 😀

    • Alex

      Cool solution, though rankChars and suitChars will have to get initialized every time the function is called. You should make them static so they only initialize once (since they don’t change).

  • Seamus


    First of all, fantastic tutorials.  Thank you.

    I’m trying to write the program for problem #7, but for some reason the compiler is throwing up a warning on the line:
    saying that expression (cardPtr) must be a pointer to a complete object type.  This only occurs when I include the ++ operator.  It looks exactly like the code suggested.  Please help.

    • Alex

      I’m not sure. You can break this up into two equivalent lines:

      See if your compiler is okay with that.

      • Seamus

        Still not working for the same problem.  Here’s some of the surrounding code to give it more context.  The error is on the pointer being incremented:

        bool playBlackJack(const std::array<Card, numCards> deck)
            const Card *cardPtr = &deck[0];
            int pScore{ 0 };
            int dScore{ 0 };
            dScore += getCardValue(*cardPtr);

        • Alex

          I think something else is going on here. Best guess is that whatever file this is only sees Card as a forward declaration instead of a complete class. I’d investigate why this function can’t see the complete definition for Card (maybe you forgot to include Card.h?)

  • David

    I tried ex 2.This is the code:

    As i writed in the comment if i change from this "<" to this ">" my program crashes.I must mention that at first i ran the program without deleting the array.Eventually I noticed and i deleted the array.

    Can you tell me what is the problem?
    Thank you for your tutoriols.You are doing a great job

  • Hans Dampf

    Two minor questions about your solution for the Blackjack program:


    Since there are only two options, wouldn’t it be better to return a bool value (if user enters ‘s’ return true)? I don’t know what’s best practice. Does it even matter? Both char and bool use 1 byte. Later in playBlackjack, we would then just check

    and 2)
    This is about the "no magic numbers" rule. Instead of declaring the array with

    why not use our MAX_SUITS and MAX_RANKS?


    • Alex

      1) You could return a bool in this case if you wanted. I chose to return a char to leave room for future choices (e.g. double down).
      2) You definitely could do this as well. In fact, you could probably use a constexpr constant to give MAX_SUITS * MAX_RANKS a better name (e.g. NUM_CARDS).

  • DianYi Liu

    Hi,Alex,thank you very much!I read this great tutorial from beginning!
    In your function of playBlackjack(),I think there is a little problem. If after shuffleDeck, the 2nd’s and the 3rd’s cards’ ranks both happen to be Ace, then the program will say the player wins. But player’s score has already gone over 21. Player should lose.
    So, just after dealing the player the first 2 cards, some codes should be added to decide whether player’s score has gone over 21 or not.

    • Alex

      True. I’ve reordered the statements in the player’s while(1) loop to first check to see if the player is busted before asking them if they want to hit or stand.

  • Vlad

    Well, this was quite the heavy quiz. To me, pointers are still fuzzy (not by their meaning, but rather all their combinations), as well as interweaving enums and structs and arrays (I didn’t quite figure that out by myself).

    But, I made it. Probably childish code, though due to some minor misunderstandings, I made the blackjack a bit different. I won’t post the code, it’s long enough (I will if you want to), but here’s what it outputs (one example):

    There still is a small problem with displaying the cards after hitting ‘s’ (the first cards are not displayed, it’s some pointer magic), it’s something very small but right now, I deserve a break (excuse for a beer).

    Because yesterday I made a Bessel polynomial generator with user input (I had to find an external, small library to support more than long long, it needs (2*N)! -- ttmath) and I feel confident enough that I can create a root finding algorithm (Durand-Kerner) and then it’s off to my initial goal and the starter of this C++ quest (not saying yet, there’s time).

    So, here’s a virtual cheers: to you, Alex!

    PS: I wanted to ask you, are symlinks similar to pointers?

    • Alex

      I’d say symlinks are more like references than pointers.

      • Vlad

        I can almost hear a voice saying: "That’s English language to you! The symlink is said to point to another location via a reference." 🙂

        Now see I forgot to modify the output. I set codeblocks to use the basic xterm for output, and it doesn’t allow copying, neither by RClick or Ctrl+Insert (or Ctrl+Shift+Insert, I tried). So, after 3 runs, seeing that the program doesn’t output what I want, I thought it simpler to just visually copy-paste a line and modify it, rather than modify the code, compile, run, and then visually copy-paste. That’s why the first "dealer’s cards" says AS 11p, but the rest 4p. Ah well…

  • Darren

    Not one for letting an argument die but I’ve refactored your code for the player’s loop to remove the break statement. The original code reads:

    The refactored code looks like this:

    Not only does this remove the break statement it also mirrors the loop for the dealer’s turn, without the call to ‘getPlayerChoice()’ of course. To me this reads better.

    • Alex

      Of course, now you’ve duplicated the output line to tell the player what their score is. To me, redundancy is a bigger sin than a break.

      • Darren

        That’s not a redundant line. The player needs to see their score in order to decide whether or not to stick or to hit on the first entry to loop. But notice that if they already have 21 i.e. blackjack (ace and a picture card) there’s no need to enter the loop, they’ve already won (this requires an if conditional with a return value of true somewhere). If what you meant was repeated code, then I’m willing to trade a single line of that for removal of a break statement in the middle of a while loop.

        • Darren

          Besides we could always change the initial output message to something other than that repeated in the while loop and then the lines wouldn’t look as repeated as they do!! 🙂

  • Nyap

    Question 1:

    Question 2:

    Question 3:

    Question 4:

    Question 5;
    Did it in my head, got most but one right

    Question 6 and 7:
    Know nothing about card games and I can’t be bothered to learn them just for this test xD

    overall I think I did ok, just need to review std::array and std::vector

  • Nyap

    damn this test is long
    also, I struggled this chapter, and I won’t be suprised if I fail ;-;

    • Nyap

      whats wrong with this (I know I should probably use std::vector but I rushed the lesson on it because I just want to get this chapter done and over with :cry:)


      How many students do you wish to enter?: 2

      50 got a grade of 0
      75 got a grade of 0

  • J3ANP3T3R

    Oh i hit a dead end. need to go back and review the previous articles.

    i did not know that "int items[MAX_ITEMS]{ 2, 5, 10 };" works given that the array item was not dynamic. it is highlighted in red line by the IDE but the compiler did not give any errors.

    also thought that when passing fixed array on functions it will decay into a pointer and could not be used in the function as a regular array. wasn’t aware that i can still use it to loop through the elements in the actual array.

    this quiz is very enlightening. i basically failed this chapter >_<

    • Alex

      This chapter is hard. It introduces a lot of complicated topics, and those complicated topics have some weird behaviors.

      The good news is that things generally get easier ahead.

  • J3ANP3T3R

    Words of encouragement



  • Amin Ashofteh Yazdi

    In the name of God

    Dear Teacher,
    i am in problem with design nested loop, and need to train my brain, in first step i use flowchart but i want to know that is a simple or logic way to reach to this power .
    thank for any of your guides.

    Hope to God

  • Satwant

    Please remove "words of encouragement ". Its highly distracting.
               In normal course of this tutorial, finding something irrelevant ,it completely gets you out of track.

    • Alex

      Some readers may find the difficulty of chapter 6 discouraging. This section exists to let them know that good things are ahead, that their struggles are worthwhile.

  • Peter Pan

    I have a very complicated solution for 6h. Like for example, the player’s score is 3. Then he hits and gets an ace. So his score can be 4 or 14. Then he gets a nine, so his score is now 13.

  • Shiva


    Awesome quiz to wrap up the chapter! Just loved it, especially #6-7 Blackjack game. Being an advocate of bottom-up designing, I enjoyed the way you made us build it from scratch, writing the individual modules first and then finally putting them all together. And all the stuff I’ve learned from here so far was put to test. I think I did it pretty well. 😀 And great summary, too.

    BTW I’ve got some suggestions:
    * In quiz #1 solution, the enumerator’s name is given as ITEM_HEAL_POTION (you asked us to enumerate ‘Health potions’)
    * In multiple solutions, you used the [] syntax while passing arrays to functions, but you recommended using the pointer (*) syntax before. I think this was deliberate in the context of quiz #5 c), but you should be consistent in the rest of the solutions.
    * In your Blackjack game, you pass the std::array deck to playBlackjack() by value, not by reference. Typo?

    Lastly, I found an alternative solution to quiz #6 h) : pass the player’s current score as a second parameter to getCardValue(), and let it determine what value to return for an Ace. This is what I did, and I think it’s neat:

    I’m tempted to post the whole solution, but it is some 350 lines, so I’m not cluttering this comment section with all that code. However you can view it on my GitHub if you have some time to spare. I’d greatly appreciate it. 🙂

    Thanks once again, expecting more such challenges!

    • Alex

      Thanks for the feedback!
      1) Changed enum to ITEM_HEALTH_POTION for consistency.
      2) Good call. Updated the syntax to use the pointer syntax over the array syntax.
      3) Yup, the pass by value instead of reference was unintentional. Fixed.
      4) I think this works for one ace, but what if the user has more than one ace?

      • Shiva

        Umm.., I believe it still works for more than one Ace. The current score is updated every time getCardValue() is called, so the function receives the latest score to calculate the suitable value for an Ace. Even if the first two cards dealt to the player are Aces, it can handle it well:

        Suppose the player Hits, and he gets yet another Ace:

        This way we need not count the Aces a player has, since we’ve checked it _before_ we incremented their score. I mean, that’s how we do it in real life: we draw a card, and consider our current score before choosing the suitable value, not after. Is there anything missing?

        And I just noticed some more typos:
        * In the solution to quiz #2, you still have the [] syntax while passing the array to the sortNames() function. The comment just above its definition is also broken: "Since names (should be ‘students’) is a pointer…"
        * In your Blackjack game, you passed the deck to printDeck() by value too.

        Thumbs up for the quick corrections. 🙂

        • Alex

          You are correct indeed! I’ve added it as an alternative solution to the final quiz question (with credit to you, of course).

          • Shiva

            That’s so nice of you. Appreciate it. 🙂

            So I won the extra credit, didn’t I? B-)

          • Tyler

            The only problem with this is that if the player or dealer drew an ace before it would’ve busted him/her, there is no way for this ace to return to the value of 1 later.

            Player draws an ace
            Player draws a two
            Player hits and draws a ten

            Then the player is stuck at a bust regardless of having the ace. While it’s much simpler it doesn’t cover all the bases.

  • tejas

    I had great fun writing my very own BlackJack game! Got interested in writing games and am now working with a buddy to create a military battle game like the "World War 2 in Western Europe" (1995).

  • Baubas

    Quiz 4:

    I did it with for:

    Why can’t I use "ptr < word + sizeof(word)" but this version "ptr < word + 13" works fine?

  • Rob G.

    Hi Alex, am getting duplicates. As in the values above. Random fx and swap fx below. Is it as simple as the fact that the random number generator can produce copies in this short range? First do you agree there are duplicates?
    Fx returning random val 1->52.

    Fx shuffling the deck using random value call.

    Thx Alex

  • Rob G.

    Let me post an expanded pool…52 swaps. There are duplicates in this array. The intent was to step though the array, as you suggested, and swap with a randomly generated card.
    Simple enough except my implementation is faulty….ideally you don’t want a duplicate correct? The unshuffled deck is on the left and the shuffled on the right. I am sorry the output takes up so much room.

    0    7
    1    47
    2    16
    3    18
    4    6
    5    36
    6    2
    7    15
    8    33
    9    1
    10    40
    11    47
    12    16
    13    5
    14    13
    15    14
    16    46
    17    14
    18    8
    19    43
    20    40
    21    35
    22    26
    23    41
    24    22
    25    10
    26    26
    27    6
    28    52
    29    26
    30    9
    31    29
    32    6
    33    52
    34    45
    35    19
    36    46
    37    46
    38    7
    39    32
    40    3
    41    37
    42    6
    43    23
    44    31
    45    1
    46    39
    47    4
    48    15
    49    16
    50    12
    51    19

    • Alex

      No, it’s okay to have duplicates in this case. We’re not pre-determining a new ordering of cards, we’re just picking a random card to swap with and doing the swap immediately. Because the loop ensures each card gets swapped at least once with a randomly chosen card, this results in a pretty good shuffle.

      Consider what happens if two cards pick the same card to swap:
      2 1
      3 1

      First, card 2 will be swapped with card 1. Then card 3 will be swapped with card 1 (which was the card in 2). So the new order of cards 1 2 3 is 3 1 2.

  • Rob G.

    oops, forgot output:


    Shuffling deck…
    Cards to be swapped:
    0    48
    1    29
    2    46
    3    9
    4    15
    5    39
    6    47
    7    36
    8    26

    • Alex

      I’m probably missing something obvious, but… what do you think is wrong here?

      It looks like your cards should be getting shuffled properly.

  • Rob G.

    Hi Alex in my shuffle deck function I am not getting 4 of every card type, randomized, in my output.

    My shuffle fx:

    I call the function to generate the random number inside the shuffle fx:
    srand() is at top of main.

  • Rob G.

    Alex, I think I get it! In any event I see that a lot of enumerator benefits are for the programmer’s side. The static cast allows an integer to be an enumerator…Briefly what are the most appropriate situations in which the conversion of integers to enumerator would be applied?

    • Alex

      Yes, enumerators are for the programmers benefit, because they are a more descriptive way to label a set of discrete items than picking an integer.

      I think the only case I’ve ever done an integer to enum conversion was for randomly picking (or generating) items from a set of enumerators. Generate a random integer between 0 and MAX_ITEMS-1 (where MAX_ITEMS is the last enumerator) and then static_cast the result back to an enum.

  • Rob G.

    I hate to ask this, I don’t want to monopolize the forum. Can you make a small example of the latter part of your response? I’m very close to understanding. Thx

  • Rob G.

    Hi Alex, I accept your teaching points on enumerators, self-documentation, etc. But I am still trying to sell myself on it.
    Is it true that enumerations only go "one -way" meaning:

    enum foo
    {   submarine 3,  //explicit values
        carrier 4
    They resolve to an integer: x = submarine  (3).

    However, you can’t go backwards from 3 to submarine. How is this helpful?

    "Which integer suit represents hearts? I have no idea." Even with enumerator, you will still have to look it up right?

    Or can it?

    You’ve got a great site, learning so much from it. Enumerators are my weak "suit" no pun intended. I am just seeking understanding.

    • Alex

      Enumerators aren’t strictly one way. Normal enumerators will silently convert to an integer. However, you can explicitly convert an integer to an enumerator by using a static_cast.

      Generally you shouldn’t ever need to convert from an integer back to an enum.

      Perhaps the best way to think of enumerators is as descriptive names for a set of integers. Like you said, you have no idea which integer suit represents hearts. You could arbitrarily pick a value (0, 1, 2, or 3) but it’s not very self-documenting. However, if you use an enumerator, it’s clear which one is hearts: SUIT_HEARTS is hearts. This relieves you from having to remember the integer/concept mapping, and makes your code clearer.

  • Rob G.

    Hi Alex I am struggling with 6d: I didn’t end up using static casts or enumerators. Am I missing the point here?
    The code is similar though. Do I need to rewrite my solution?
    your solution:(comparing yours/mine)

            deck[card].suit = static_cast<CardSuit>(suit);
            deck[card].rank = static_cast<CardRank>(rank);


    My solution:

    • Alex

      Using enumerators is clearer than using integers since it’s more self-documenting. Which integer suit represents hearts? I have no idea.

      Having an index member in your card is a little odd. Typically you want to rely on your container (in this case, the array) to provide the ordering, not make the cards themselves responsible for knowing how they are ordered.

  • Soul


    Ummm, I just popped in the code in answer #7 and my compiler can’t make it work. I get the error "warning: enumeration value ‘MAX_RANKS’ not handled in switch [-Wswitch]|". There’s another like it underneath it that mentions MAX_SUITS.

    When I commented them out, I got RAND_MAX was not declared in this scope for line 88.

  • Soul

    EDIT: Never mind, just went back to the chapter on for each loops and discovered they don’t work on dynamically allocated arrays.

    Hi, I’m having some trouble here:

    This give me an error at the first for each loop, and says something along the lines of 'no matching function for call to 'begin(students*&)'.

    I have yet to implement anything else but was giving my current code a test run until I came to this little problem. I have no idea why this is giving me issues.

    Please help, thanks.

  • Satwant

    Quiz 2, in solution line no. 22.

            // Look for largest element remaining in the array (starting at startIndex+1).  // WRONG
                   // Look for largest element in the remaining array( starting at start index+1).  //RIGHT

  • Jazz

    Hi Alex,

    I want to share a beauty with you, with the next swap function in #3 quiz:

    Many thanks to you, Alex!

    • Alex

      This is a neat little integer trick that sometimes gets asked in programming interviews.

      Please don’t ever do this in real code, as it’s not obvious what the code is doing. 🙂

      • Jazz

        I’m agree with you, it’s realy looks like "magic literals". But, what about algorithms, that are not obvious too?
        This function returns Greatest Common Divisor, and it doesn’t look simple.

        Or i’m talking about different things?

        • Alex

          Good question and food for thought. I think the difference is this:

          * There’s a good alternative for the swap() function that’s not only more intuitive, but also works for non-integer types (use a temp variable, or std::swap). The algorithm presented above is “clever” (which makes it an interesting interview question), but clever isn’t a good qualification for an algorithm.

          * There isn’t really a good alternative for the GCD algorithm that’s going to be more intuitive, and GCD is only meaningful in the context of integers anyway. This is a standard way of calculating GCD. I think in this case, a good comment will go a long way.

  • Sandro

    Hello. For the #7 quiz, I wrote the program below. It works, but if you play it several times (the game allows you to keep playing), the variables starts to get weird numbers, like 20030006113. Can someone explain me why?