samturner
samturner

Reputation: 2223

Initialisation from incompatible pointer type and arrays of structs

I'm learning C at the moment and having a bit of trouble getting my head around pointers and arrays of structs. Here's a simple program I've written:

#include <stdio.h>

typedef struct {                                        /* Define the structure Pokemon that contains a nickname, type and level*/
    char nickname[11];
    char type[11];
    int level;
} Pokemon;

int main(void) {

    char nickname[11];
    char type[11];
    int level;

    for (int i = 0; i < 3; i++) {                      /* Iterate through the loop three times, each time create a new pokemon */
        printf("Pokemon %i \n", i);
        printf("Nickname: ");
        scanf("%s", &nickname);
        printf("Type: ");
        scanf("%s", &type);
        printf("Level: ");
        scanf("%i", &level);

        Pokemon * poke = {nickname, type, level};                /* Insert the pokemon into the array of Pokemon */

        printf("%s, %s, %i", poke->nickname, poke->type, poke->level);
    }
}

Basically I want to create a struct for a pokemon that takes the three characteristics. In the main function I want the user to input the characteristics of 3 pokemon and then create an instance of the struct pokemon with these three characteristics and print out these characteristics to stdout. With this code, it compiles but I'm getting the warnings:

pokemon.c:33:9: warning: initialization from incompatible pointer type [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]
pokemon.c:33:9: warning: excess elements in scalar initializer [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]
pokemon.c:33:9: warning: excess elements in scalar initializer [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]

Not sure why this is - I imagine it's something to do with the pointers I've set up, but as I say, still trying to get my head around it.

I'd also like to put each instance of pokemon into an array of three pokemon. So far I've got this:

Pokemon p [3];

// This bit inside the for loop and after the 'poke' struct instantiation
p[i] = poke;
printf("%s,%s,%i inserted\n", poke.nickname, poke.type, poke.level );

But that doesn't want to compile - I imagine it's another pointer error.

Upvotes: 0

Views: 719

Answers (5)

Dipto
Dipto

Reputation: 2738

The problem is with the line

Pokemon * poke = {nickname, type, level};                /* Insert the pokemon into the array of Pokemon */

So, instead of initializing like that, you also can simply use this:

    Pokemon *poke = malloc(sizeof(Pokemon));
    strcpy(poke->nickname,nickname);
    strcpy(poke->type,type);
    poke->level=level;   

Upvotes: 1

teppic
teppic

Reputation: 8195

In this line:

   Pokemon * poke = {nickname, type, level};

You're only declaring a pointer, so you can't initialise it as a struct. And since your struct has character arrays, you can't assign a string pointer.

If you're using C99 you can use a compound literal:

   Pokemon * poke = &(Pokemon){.level = level}; 

Otherwise you'll need to declare a structure, and then assign its address instead.

For the next section, you need

   p[i] = *poke;

To copy the structure pointed to into a new one.

However, initialising this way won't copy the strings into the struct. What you can do instead:

   strcpy(p[i].nickname, nickname);
   strcpy(p[i].type, type);

You should also remove the & in these lines:

   scanf("%s", &nickname);
   scanf("%s", &type);

Upvotes: 1

qPCR4vir
qPCR4vir

Reputation: 3571

Why not directly read into your array?

#include <stdio.h>
typedef struct {         /* Define the structure Pokemon that contains a nickname, type and level*/
    char nickname[11];
    char type[11];
    int level;
} Pokemon;

int main(void) 
{
    Pokemon p[3];

    for (int i = 0; i < 3; i++)   /* Iterate three times, each time create pokemon */
    {                      
        printf("Pokemon %i \n", i);
        printf("Nickname: ");
        scanf("%10s", p[i].nickname);
        printf("\nType: ");
        scanf("%10s", p[i].type);
        printf("\nLevel: ");
        scanf("%i", &p[i].level);

        printf("\n%s, %s, %i\n", p[i].nickname, p[i].type, p[i].level);
    }
}

Upvotes: 1

SomeWittyUsername
SomeWittyUsername

Reputation: 18348

Given the description of the desired functionality I'd say there is no need in pointers at all. Just read the data and store it directly into your array:

int main(void) 
{
    Pokemon p[3];
    for (int i = 0; i < 3; i++) 
    {
        printf("Pokemon %i \n", i);
        printf("Nickname: ");
        scanf("%s", &(p[i].nickname));
        printf("Type: ");
        scanf("%s", &(p[i].type));
        printf("Level: ");
        scanf("%i", &(p[i].level));

        printf("%s, %s, %i", p[i].nickname, p[i].type, p[i].level);
    }
    return 0;
}

Upvotes: 1

Valeri Atamaniouk
Valeri Atamaniouk

Reputation: 5163

Pokemon p[3];
...
Pokemon poke;
strncpy(poke.nickname, nickname, sizeof(poke.nickname));
strncpy(poke.type, type, sizeof(poke.type));
poke.level = level;
p[i] = poke;

Edit: fixed temporary struct init.

Upvotes: 1

Related Questions