LeoG
LeoG

Reputation: 25

fprintf does not display value properly

I'm trying to represent a battle cards game :

typedef struct list_of_cards* p_loc;
typedef struct game game_s;

struct list_of_cards {
    char card[4]; // card is represented like 10C or KS
    p_loc ncards; // next card
};

struct game {
    p_loc loc; // list of card
    p_loc lcard; // last card
}; 

p_loc init_cards(p_loc loc, int n) {
    loc = malloc(sizeof(struct list_of_cards));
    scanf("%s", loc->card);
    fprintf(stderr, "%s\n", loc->card);
    if (n == 1)
        return loc;
    init_cards(loc->ncards, n-1);
}

int main()
{
    int n; // the number of cards for player 1
    scanf("%d", &n);
    game_s player1;// the n cards of player 1
    player1.lcard = init_cards(player1.loc, n);
    fprintf(stderr, "%s %s\n", player1.loc->card, player1.lcard->card);
}

The first fprintf give me what I want (like AD KC QC) but the second displays

�(�� QC

. So my question is, why �(�� is player1.loc->card value. Thanks

Upvotes: 2

Views: 64

Answers (2)

maazza
maazza

Reputation: 7193

The reason why player1.loc->card is some weird string is due to the fact it is uninitialized and the memory contains random characters which are not always printable in ascii. You need to modify your loc in your init to do so you can pass your loc as a pointer to the first element of your list,but the best way is probably to initialize you whole player struct in one function.

p_loc init_cards(p_loc* loc, int n) {
    *loc = malloc(sizeof(struct list_of_cards));
    scanf("%s", (*loc)->card);
    fprintf(stderr, "%s\n", (*loc)->card);
    if (n == 1)
        {
            (*loc)->ncards = NULL;
            return *loc;
        }
    return init_cards(&((*loc)->ncards), n-1);
}

int main()
{
    int n; // the number of cards for player 1
    scanf("%d", &n);
    game_s player1;// the n cards of player 1
    player1.lcard = init_cards(&player1.loc, n);
    fprintf(stderr, "%s %s\n", player1.loc->card, player1.lcard->card);
}

Upvotes: 3

Rabbid76
Rabbid76

Reputation: 211278

You have to return the allocate card and assign it back to the member p_loc of its predecessor.Further you need an output parameter for the last card of the deck:

p_loc init_cards( int n, p_loc *lastCard )
                            // ^ output parameter
{
    if ( n <= 0 )                        // terminate recursion
        return NULL;                     // successor of last card is NULL

    p_loc loc = malloc(sizeof(struct list_of_cards)); // allocate new card
    if ( loc != NULL )
    {
        scanf("%s", loc->card);
        fprintf(stderr, "%s\n", loc->card);

        *lastCard = loc;                 // new card is last card
        loc->ncards = init_cards( n-1 ); // next card is successor of act card
    }
    return loc;                          // return new card
}

int main()
{
    int n; // the number of cards for player 1
    scanf("%d", &n);
    game_s player1;// the n cards of player 1
    player1.lcard = NULL;
    player1.loc   = init_cards( n, &player1.lcard );
    fprintf(stderr, "%s %s\n", player1.loc->card, player1.lcard->card);
}

But you can easily do that without recursion:

p_loc init_cards( int n, p_loc *lastCard )
{
    *lastCard = NULL;
    p_loc head;
    p_loc *act = &head; // init pointer to first card
    for ( int i = 0; i < n; i ++ )
    {
        *act = malloc( sizeof(struct list_of_cards) ); // allocate next card right to target
        if ( *act == NULL )
            break;

        scanf( "%s", (*act)->card );
        fprintf( stderr, "%s\n", (*act)->card );

        *lastCard = *act;         // last card is act card
        act = &((*act)->ncards);  // set pointer to member ncards of last card
    }
    *act = NULL;                  // successor of last card is NULL
    return head;                  // return first card
}

Upvotes: 2

Related Questions