C Help: MSVC debugger gets an "error reading characters of string" error... but only sometimes

0

I am making a 5 card poker game, but I keep getting an error when running the program in the debugger.

I ran this code through my debugger 8 times and of those I got an error 5 times — without changing any of the code. What could be causing it to read a string improperly only sometimes? Please help me figure it out.

Necessary code:

-Initialization

char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"};
char *face[13] = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", 
"Eight", "Nine", "Ten", "Jack", "Queen", "King"};
Card p1_hand[5] = {{0,0,0}};

-Function call in main

print_hand(face, suit, p1_hand);

-Functions in header file // Card struct

typedef struct card
{
int card_number;
int face_index;
int suit_index;
} Card;

void print_hand (char *face[4], char *suit[13], Card p1_hand[5]);

-Function itself

void print_hand (char *face[], char *suit[], Card p1_hand[5])
{
int i = 0, j = 0, k = 0;

printf("You're hand:\n");
for(i = 0; i < 5; i++)
{
    j = p1_hand[i].face_index;
    k = p1_hand[i].suit_index;
    printf("%d: %5s of %-8s\n", (i+1), face[j], suit[k]);
}
}

I put a debugger stopping point before the first printf and sometimes I get this out of it

  • face 0x0040fb5c {0x0000000a Error reading characters of string.}

but other times I get this... without changing the code at all

  • face 0x002afe40 {0x013a787c "Ace"} (which is correct)

Please help me figure this out! It's driving me crazy.

EDIT *MY CODE*

main.c

#include "poker.h"

int main (void)
{
//initialize arrays
char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"};
char *face[13] = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", 
"Nine", "Ten", "Jack", "Queen", "King"};
int deck[4][13] = {0};
int num_face_player_1[13] = {0}, num_face_dealer[13] = {0};
int num_suit_player_1[4] = {0}, num_suit_dealer[4] = {0};

//Players' hands
Card p1_hand[5] = {{0,0,0}}, dealer_hand[5] = {{0,0,0}};

//Other
int count = 0;
int menu = 0, choice_menu = 0;
int invalid = 0;

srand ((unsigned) time (NULL));

//MENU
do //menu loop
{
    menu = print_menu ();
    choice_menu = 4; //so its not 0;
    choice_menu = menu_choice (menu);
} while (choice_menu ==0);
if (choice_menu == 2) //closes the game
{
    return 0;
}

system ("cls");
shuffle (deck);
deal (deck, p1_hand);

do //checks to make sure the dealer doesnt have any of the same cards
{
    deal (deck, dealer_hand);
    invalid = 0;
    for(count = 0; count < 5; count++)
    {
        if ((dealer_hand[count].card_number == p1_hand[count].card_number) && (dealer_hand[count].face_index == p1_hand[count].face_index) && (dealer_hand[count].suit_index == p1_hand[count].suit_index))
        {
            invalid = 1;
        }
    }
} while (invalid == 1);

for(count = 0; count < 4; count++)
{
    printf("%s\n", *suit[count]);
}
for(count = 0; count < 13; count++)
{
    printf("%s\n", *face[count]);
}
print_hand(face, suit, p1_hand);

//these populate the number of facecards / suits arrays in order to see what hand you got
pop_num_faces(num_face_player_1, p1_hand);
pop_num_faces(num_face_dealer, dealer_hand);
pop_num_suit(num_suit_player_1, p1_hand);
pop_num_suit(num_suit_dealer, dealer_hand);

return 0;
}

poker.h

#ifndef POKER_H
#define POKER_H

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <dos.h>

typedef struct card
{
    int card_number;
    int face_index;
    int suit_index;
} Card;

int print_menu (void);
int menu_choice (int menu_choice);
void press_any_key (void);
void shuffle (int wDeck[4][13]);
void deal(const int wDeck[][13], Card p_hand[5]);
void pop_num_faces (int num_faces[], Card hand[5]);
void pop_num_suit (int num_suit[4], Card hand[5]);
void print_hand (char *face[4], char *suit[13], Card p1_hand[5]);
void check_hand(Card p1_hand[5], int num_suit[], int num_faces[]);

#endif

poker.c

#include "poker.h"

//prints menu
int print_menu (void)


//decides what to do with the menu choice
int menu_choice (int menu_choice)
//Shuffles the deck
void shuffle (int wDeck[4][13])
{
int row = 0;
int column = 0;
int card = 0;

for (card = 1; card <= 52; card++)
{
    do
    {
        row = rand () % 4;
        column = rand () % 13;
    } while (wDeck[row][column] != 0);

    wDeck[row][column] = card;
}
}

//deals the deck to the player
void deal(const int wDeck[][13], Card p_hand[5])
{
int row = 0;
int column = 0;
int card = 0;
int index = 0;

for(card = 1; card < 52; card++)
{
    for (row = 0; row <4; row++)
    {
        for (column = 0; column < 13; column++)
        {
            if(wDeck[row][column] == card)
            {
                p_hand[index].card_number = card;
                p_hand[index].face_index = column;
                p_hand[index].suit_index = row;
            }
        }   
    }
    index++;
}
}

//populates num faces
void pop_num_faces (int num_faces[], Card hand[5])
{
int i = 0;

//program keeps populating num_faces with random numbers, so i have to  re-initialize here
    num_faces[0] = 0;
    num_faces[1] = 0;
    num_faces[2] = 0;
    num_faces[3] = 0;
    num_faces[4] = 0;
    num_faces[5] = 0;
    num_faces[6] = 0;
    num_faces[7] = 0;
    num_faces[8] = 0;
    num_faces[9] = 0;
    num_faces[10] = 0;
    num_faces[11] = 0;
    num_faces[12] = 0;

for(i = 0; i < 5; i++)
{
    switch(hand[i].face_index)
    {
    case 0: num_faces[0] ++;
        break;
    case 1: num_faces[1] ++;
        break;
    case 2: num_faces[2] ++;
        break;
    case 3: num_faces[3] ++;
        break;
    case 4: num_faces[4] ++;
        break;
    case 5: num_faces[5] ++;
        break;
    case 6: num_faces[6] ++;
        break;
    case 7: num_faces[7] ++;
        break;
    case 8: num_faces[8] ++;
        break;
    case 9: num_faces[9] ++;
        break;
    case 10: num_faces[10] ++;
        break;
    case 11: num_faces[11] ++;
        break;
    case 12: num_faces[12] ++;
        break;
    }
}
}

//populates num_suit
void pop_num_suit (int num_suit[4], Card hand[5])
{
int i = 0;
num_suit[0] = 0;
num_suit[1] = 0;
num_suit[2] = 0;
num_suit[3] = 0;

for(i = 0; i < 5; i++)
{
    switch(hand[i].suit_index)
    {
    case 0: num_suit[0] ++;
        break;
    case 1: num_suit[1] ++;
        break;
    case 2: num_suit[2] ++;
        break;
    case 3: num_suit[3] ++;
        break;
    }
}
}

void print_hand (char *face[4], char *suit[13], Card p1_hand[5])
{
printf("You're hand:\n");
for(i = 0; i < 5; i++)
{
    j = p1_hand[i].face_index;
    k = p1_hand[i].suit_index;
    printf("--DEBUG--: %d %d %d\n", p1_hand[i].card_number, j, k);
    printf("%d: %5s of %-8s\n", (i+1), face[j], suit[k]);
}
}
c
string
compiler-errors
asked on Stack Overflow Apr 16, 2013 by Clayton Fetzer • edited Apr 16, 2013 by Clayton Fetzer

2 Answers

2

The problem is in the deal() function. Here's a debugging version of it:

void deal(int wDeck[][13], Card p_hand[5])
{
    int row = 0;
    int column = 0;
    int card = 0;
    int index = 0;

    for (card = 1; card < 52; card++)
    {
        for (row = 0; row < 4; row++)
        {
            for (column = 0; column < 13; column++)
            {
                if (wDeck[row][column] == card)
                {
                    p_hand[index].card_number = card;
                    p_hand[index].face_index = column;
                    p_hand[index].suit_index = row;
                    printf("Assign %d\n", index);
                }
            }
        }
        index++;
        printf("Index: %d\n", index);
    }
}

When run, index goes from 1 to 52; pity the p_hand array only has 5 elements! And the Assign gets printed numerous times. You've got array indexes horribly out of control.


Incidentally, you're too fond of switches. This:

void pop_num_suit (int num_suit[4], Card hand[5])
{
    int i = 0;
    num_suit[0] = 0;
    num_suit[1] = 0;
    num_suit[2] = 0;
    num_suit[3] = 0;

    for(i = 0; i < 5; i++)
    {
        switch(hand[i].suit_index)
        {
        case 0: num_suit[0] ++;
            break;
        case 1: num_suit[1] ++;
            break;
        case 2: num_suit[2] ++;
            break;
        case 3: num_suit[3] ++;
            break;
        }
    }
}

Should be:

void pop_num_suit(int num_suit[4], Card hand[5])
{
    int i;
    for (i = 0; i < 4; i++)
        num_suit[i] = 0;
    for (i = 0; i < 5; i++)
        num_suit[hand[i].suit_index]++;
}

The space saving in pop_num_faces() is even more dramatic.

answered on Stack Overflow Apr 16, 2013 by Jonathan Leffler • edited Apr 16, 2013 by Jonathan Leffler
0

It's a bit big for a comment, hence a CW answer.

void print_hand(char *face[], char *suit[], Card p1_hand[5])
{
    printf("Your hand:\n");
    for (int i = 0; i < 5; i++)
    {
        int j = p1_hand[i].face_index;
        int k = p1_hand[i].suit_index;
        printf("--DEBUG--: %d %d %d\n", p1_hand[i].card_number, j, k);
        printf("%d: %5s of %-8s\n", (i+1), face[j], suit[k]);
    }
}

This prints the data from each entry of p1_hand before trying to use that data. This may tell you something about what's going on. You could add assertions as an alternative, or addition:

        assert(j >= 0 && j < 13);
        assert(k >= 0 && j < 4);

SSCCE Code

This is more nearly an SSCCE — just over 100 lines of code that crash on Unix in the same general way it was crashing on Windows, in the print_hand() function.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct card
{
    int card_number;
    int face_index;
    int suit_index;
} Card;

void shuffle(int wDeck[4][13]);
void deal(int wDeck[][13], Card p_hand[5]);
void print_hand(char *face[4], char *suit[13], Card p1_hand[5]);

static void print_deck(int deck[4][13]);

int main (void)
{
    char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"};
    char *face[13] = {"Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
        "Nine", "Ten", "Jack", "Queen", "King"};
    int deck[4][13] = { { 0 } };
    Card p1_hand[5] = {{0,0,0}};

    srand ((unsigned) time (NULL));

    printf("Shuffle\n");
    shuffle(deck);
    print_deck(deck);

    printf("Deal player\n");
    deal(deck, p1_hand);

    printf("Print player's hand\n");
    print_hand(face, suit, p1_hand);

    return 0;
}

static void print_deck(int deck[4][13])
{
    for (int x = 0; x < 4; x++)
    {
        for (int z = 0; z < 13; z++)
            printf(" %2d", deck[x][z]);
        putchar('\n');
    }
}

void shuffle(int wDeck[4][13])
{
    int row = 0;
    int column = 0;
    int card = 0;

    for (card = 1; card <= 52; card++)
    {
        do
        {
            row = rand () % 4;
            column = rand () % 13;
        } while (wDeck[row][column] != 0);

        wDeck[row][column] = card;
    }
}

void deal(int wDeck[][13], Card p_hand[5])
{
    int row = 0;
    int column = 0;
    int card = 0;
    int index = 0;

    for (card = 1; card < 52; card++)
    {
        for (row = 0; row <4; row++)
        {
            for (column = 0; column < 13; column++)
            {
                if (wDeck[row][column] == card)
                {
                    p_hand[index].card_number = card;
                    p_hand[index].face_index = column;
                    p_hand[index].suit_index = row;
                }
            }
        }
        index++;
    }
}

void print_hand(char *face[4], char *suit[13], Card p1_hand[5])
{
    int i = 0, j = 0, k = 0;

    printf("Your hand:\n");
    for (i = 0; i < 5; i++)
    {
        j = p1_hand[i].face_index;
        k = p1_hand[i].suit_index;
        printf("--DEBUG--: %d %d %d\n", p1_hand[i].card_number, j, k);
        printf("%d: %5s of %-8s\n", (i+1), face[j], suit[k]);
    }
}

The good news is that the shuffle() function appears to be OK.

answered on Stack Overflow Apr 16, 2013 by Jonathan Leffler • edited Apr 16, 2013 by Jonathan Leffler

User contributions licensed under CC BY-SA 3.0