While loops and arrays

Hello, I was going through a beginner's guide book on C++ and could not understand exactly how this example works, even after pondering for hours.

This program is a card-dealing program which uses a 52-element array in which each element corresponds to a card. Once a card is picked, this array is updated to show that the card should be skipped in the future.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
using namespace std;

int rand_0toN1(int n);
void draw_a_card();
int select_next_available(int n);

char *suits[4] =  {"hearts", "diamonds", "spades", "clubs"};
char *ranks[13] = {"ace", "two", "three", "four", "five",
                 "six", "seven", "eight", "nine",
                 "ten", "jack", "queen", "king" };

int card_drawn[52];
int cards_remaining = 52;

int main() {
    int n, i;

    srand(time(NULL));      // Set seed for random numbers.

    while (1) {
        cout << "Enter no. of cards to draw (0 to exit): ";
        cin >> n;
        if (n == 0)
            break;
        for (i = 1; i <= n; i++)
            draw_a_card();
    }
    return 0;
}

// Draw-a-card function
// Performs one card-draw by getting a random 0-4 and a random
//  0-12. These are then used to index the string arrays, ranks
//  and suits.
//
void draw_a_card() {
    int r;         // Random index (0 thru 12) into ranks array
    int s;         // Random index (0 thru 3) into suits array
    int n, card;

    n = rand_0toN1(cards_remaining--);
    card = select_next_available(n);
    r = card % 13;            // r = random 0 to 12
    s = card / 13;            // s = random 0 to 3
    cout << ranks[r] << " of " << suits[s] << endl;
}

// Select-next-available-card function.
// Find the Nth element of card_drawn, skipping over all those
//  elements already set to true.
//
int select_next_available(int n) {
    int i = 0;

    // At beginning of deck, skip past cards already drawn.

    while (card_drawn[i])
        i++;

    while (n-- > 0) {     // Do the following n times:
        i++;                       // Advance to next card
        while (card_drawn[i])      // Skip past cards
            i++;                   //  already drawn.
    }
    card_drawn[i] = true;        // Note card to be drawn
    return i;                    // Return this number.
}

// Random 0-to-N1 Function.
// Generate a random integer from 0 to N-1.
//
int rand_0toN1(int n) {
    return rand() % n;
}

I mainly have problems with the select_next_available card function.
1.for the " while (card_drawn[i]) ", how is the condition card_drawn[i] used? The initial value of i is 0, so card_drawn[0] is false and the loop shouldnt even start in the first place?

2.For the while (n-- > 0) loop, does that mean n is further reduced by one here? What is the purpose of doing n--, and if n is initially zero (the rand_0toN1 function picks 0 from the numbers 0 to 51), then n-- = -1??

3.Lastly, why is i increased so many times in this function? I can see i++ three times here.

Thanks!
I shall answer in REVERSE NUMERICAL ORDER!!!! :D

3.) i++ is used as an incriminator, it is often used to make a loop run a certain number of times, or move through an array (as it is used here).

2.) You are correct, it takes whatever "n" is and subtracts each iteration through the while loop as long as "n" is greater than 0. If "n" starts out at 0 then it will not run through that loop.

1.) while(chard_drawn[i]) isn't checking to see if the value of card_drawn in position "i" is false but rather if it exists. If the value is anything other than NULL then it will return true and run through the loop.

Hope this helps :)
Hey, stupid question. In reference to the expression while(n-- > 0), is an immediately decremented 'n' being evaluated or just 'n' followed by the decrement. In this context when is it necessary to use a prefixed decrement? Just curious. Sorry for the interruption.
closed account (Lv0f92yv)
n-- > 0 compares n to 0, then decrements n.
--n > 0 decrements n, then compares n to 0.

The order in which the -- or ++ is done matters.
Last edited on
That is correct Desh :D

In this program, I think it would be better to keep it how it is so it can iterate through at least one card as opposed to never getting any cards.

Also.... i apologize for my answer earlier regarding question number one.... I was wrong D: here is the right answer...

1.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    while (n-- > 0) {               // Do the following n times:
        i++;                             // Advance to next card

      /////////////////////////////
     // Skip past cards -This checks to see if the card has a value of true, which means it has
     //been drawn this value is set three lines down after a card has been
     //drawn
     ///////////////////////////////

        while (card_drawn[i]) {

              //////////////////////
              //  This says "Hey, the last card was already drawn so move onto the next one".
              /////////////////////

                 i++
        }
       //////////////////////////
       // This sets the card you have just drawn, that hasn't been previously drawn, to true
       /////////////////////////

      card_drawn[i] = true; 

return i;          // Return this number.
}



All the explanations are in the comments I've changed. Sorry about the confusion, I read the code wrong D:
Last edited on
That's great. (Sorry to interrupt again. This isn't my thread.) I totally understand the general effects of prefix and postfix increment/decrement but the context is kind of confusing. I guess I can see the logic now, though. Now about the headers (if you don't mind), when is it appropriate to include a c standard header rather than c++? Maybe that's not a fair distinction. But in this case, why not include cstdlib, ctime, cmath? Would there be unnecessary overhead? How do you decide which to use in whatever situation. Excluding iostream. Stdio.h obviously wouldn't work with cin and cout. So just asking. It's a good thread.
Okay, nevermind. Sorry for the interruption. Just seemed like a good place to ask that question. Bye.
Don't be so quick to denounce the helpfulness of the cplusplus.com community mr. mucygni. We do have lives so it may sometimes take a little while to get around to responding to questions. Your questions are valid questions and, though maybe not on topic, should be answered :).

It is never appropriate to use C headers in a C++ program. They are out-dated and all functions in those libraries have been converted to new C++ libraries, while keeping the same usage syntax. So while technically they are still C libraries, they are included in a slightly different way

cstdio.h is included like this
 
#include <stdio.h> 


iostream's is typically when using cout and cin while stdio.h is typically used with fprint() and fprintf() and a few other useful functions. Here is a link with a reference for all C++ libraries that you can use to learn just how to use each of them effectively: http://cplusplus.com/reference/
Thank you so much. I fully appreciate everything everyone has to say on this site, even when it doesn't come as quickly as I might expect. (Which I shouldn't do.) There's a lot of people on here that seem to know a real lot about C++. It must be really nice to be in that position. So I'll keep working on it.

Hey, don't mean to be cocky or anything but it kind of seems like you're saying cstdio.h is included by calling stdio.h. After reading the part about C headers being out-dated, it seems unlikely that that is what you meant.

Again, please excuse the seemingly cocky comment. I couldn't help it. I have another question but won't ask in this thread. Bye.
Hey, I still don't mean to be cocky but <cstdio> doesn't have an extension. Like everything else in C++, it seems. I remember reading that all C++ headers used to have the .h extension but that was dropped. For portability, I think. So just pointing that out, in case anyone else reads this discussion. I think it should be clear.

I'd kind of like to be sure--just to satisfy my curiosity, really--that the standard C headers aren't necessary for compilation of C++. Are the new C++ headers a complete replacement or are the original headers still called through them on some occasions.

Sorry to continue the questioning when I said I was done here. No rush to respond. Bye.
It's okay, I'd rather you ask questions than assume and make mistakes. You are correct, you could include it in the standard C++ way with
 
#include <cstdio> 

Though many people still use #include <stdio.h> because thats how they've done it since before C++. A compiler will still grab the library designated for C++ programs though (even though they're pretty much the exact same thing). When I said, don't use C libraries, I was talking if you were linking/compiling via command line, I didn't want you to download some C library from 1970 and try using it with your C++ program but instead use the newer versions typically included in modern compilers (sorry for the confusion).

Now for the differences <iostream> vs <cstdio>
1
2
3
4
5
6
The <iostream> library offers two major advantages compared to C's <stdio.h>:
it can be extended to support user-defined types and it's type-safe. Yet
programmers often complain that <iostream> has poorer performance and a bloated
and unintuitive interface (especially in output formatting).

-Eric Gannon


They are different, as this post says, mainly in their use but not totally in their function. There are a few advantages to each and as with any tool, it is the job of the programmer to decide which tool is best for the job.
Thanks so much. Have a nice day.
Topic archived. No new replies allowed.