'0' character oddity

I'm working on a Poker game for a class project and I've come across an unexpected behavior of the '0' character. One I know it might be better to use '1' but, I haven't, up to this point anyway. I'm just wonder if anyone could explain to me why this code is actually working. It confounds me. Is it a bug

I'm trying to sort a hand of Card objects, implemented as such:

struct Hand {
const static int COUNT = 5;
Cards cards[COUNT];

...

};

I know I need to overload the < operator. Here's class Cards:

struct Cards {
char suit, value;

void setSuit(char suit) { this->suit = suit; }
void setValue(char value) { this->value = value; }

bool operator ==(const Cards& card) {
return (this->suit == card.suit && this->value == card.value);
}

bool operator < (const Cards& card) {

// is this really necessary

if ( card.value == '0' &&
( this->value == 'a' ||
this->value == 'k' ||
this->value == 'q' ||
this->value == 'j' ||
this->value == '0' ) ) {
return false;
} else if ( card.value == '0' &&
( this->value == '9' ||
this->value == '8' ||
this->value == '7' ||
this->value == '6' ||
this->value == '5' ||
this->value == '4' ||
this->value == '3' ||
this->value == '2' ) ) {
return true;
}
// is this really necessary


if ( this->value == '0' &&
( card.value == 'a' ||
card.value == 'k' ||
card.value == 'q' ||
card.value == 'j' ) ) {
return true;
} else if ( this->value == '0' &&
( card.value == '0' ||
card.value == '9' ||
card.value == '8' ||
card.value == '7' ||
card.value == '6' ||
card.value == '5' ||
card.value == '4' ||
card.value == '3' ||
card.value == '2' ) ) {
return false;
} else if ( this->value == 'j' &&
( card.value == 'a' ||
card.value == 'k' ||
card.value == 'q' ) ) {
return true;
} else if ( this->value == 'q' &&
( card.value == 'a' ||
card.value == 'k' ) ) {
return true;
} else if ( this->value == 'k' &&
card.value == 'a' ) {
return true;
} else if ( this->value == '9' ||
this->value == '8' ||
this->value == '7' ||
this->value == '6' ||
this->value == '5' ||
this->value == '4' ||
this->value == '3' ||
this->value == '2' ) {
return (this->value < card.value);
} else {
return false;
}
}
};

Now if I call:

sort(hand.cards, hand.cards+hand.COUNT);

for (int i=0; i<hand.COUNT; i++){
cout << hand.cardsIdea.suit;
cout << hand.cardsIdea.value << endl;
}

the sorting works. But if I take out the conditions between the "is this necessary" comments, the sorting does not work. Here are some examples of the output:

With "is this necessary":

3 4 8 10 q

5 7 9 10 a

Without "is this necessary":

6 10 6 8 q

4 10 5 q a

I'm using Windows XP; SP2, and although I have a license for VS.NET 2003, I'm using the cl.exe that came with the Microsoft Visual C++ Toolkit 2003 to compile the program.



Answer this question

'0' character oddity

  • ftplds

    Oops forgot a bit of detail. My cards number array, in order of lowest to highest for poker, is:

    cards[0] = '2';

    cards[1] = '3';

    cards[2] = '4';

    cards[3] = '5';

    cards[4] = '6';

    cards[5] = '7';

    cardsDevil = '8';

    cards[7] = '9';

    cardsMusic = '0'; //chosen representation of 10 in a single char

    cards[9] = 'j';

    cards[10] = 'q';

    cards[11] = 'k';

    cards[12] = 'a';

    I know there are MANY MUCH better ways to handle this type of structure, but it's part of the requirements for the project.

    So the operator overloading is necessary to maintain the cards value in relation to one another, since I can't just count, card.value+1.


  • MickRivers

    Ah. I see. I guess I was assuming that C++ would do the conversion for me like most of the other languages I usually use.
  • Ilkin

    ...right. Got it. Sorry. Thank you. I was wondering as I was programming this how to do that. I'm still learning some of the more basic, "worker" functions that are available for use. Good lesson. Thank you all.
  • farseer

    Hi Frogstarr,

    I don't know if you're still looking for an answer here, but there's a bug in your logic.

    If you take out the "// is this necessary" code, consider follow the case where card->value == '0' and this.value == 7. With your "if/else if" code, you will eventually end up with this line:
    --------------
    return (this->value < card.value);
    --------------

    which translates to ('7' < '0'). Logically, you want to return 'true', because 7 is less than 10. However, the ASCII '7' is greater than the ASCII '0', so this line actually returns 'false'.

    This problem exists whenever card.value is '0' and this->value is a card between '2' and '9'. This also explains why it works fine when you include the additional code - the additional code traps these cases.

    Hope that helps,
    Brad

  • Cody65

    sure, I was just replacing the same identical test, but with less code. You basically need to handle the special cases, which means you need to test if either value is 0, or a letter, and if it is, then code the comparisons yourself. Otherwise, you can check which is greater out of the two digits. My code was one example of how you could do one of those tests with a lot less code, which would make it far easier to read.



  • The Blind Wig

    isalpha and isnumeric will simplify the tests you're doing.

    For example

    if ( card.value == '0' &&
    ( this->value == 'a' ||
    this->value == 'k' ||
    this->value == 'q' ||
    this->value == 'j' ||
    this->value == '0' ) ) {
    return false;
    } else if ( card.value == '0' &&
    ( this->value == '9' ||
    this->value == '8' ||
    this->value == '7' ||
    this->value == '6' ||
    this->value == '5' ||
    this->value == '4' ||
    this->value == '3' ||
    this->value == '2' ) ) {
    return true;
    }

    becomes

    if (!card.value) // if value is 0

    {

    return (!::isalpha(this->value); // return false for a letter, true for anything else.

    }



  • '0' character oddity