Search code examples
cfunctionpointersstructpointer-to-pointer

Add data dynamically to array of pointers to structures within function


I tried many combinations but really nothing worked. It's been long enough so I decided to write this issue.

I just want an array of pointers to structures so I could later easiely sort it by swaping the addresses. I have a function to get data from file and write to array. Unfortunately, it's impossible for me to read this data outside the function.

My last attempt (I deleted file operations as those are not the issue):

Header.h:

#pragma once

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int32_t year;
    uint16_t month;
    uint16_t day;
} Date;

typedef struct {
    char name[16];
    Date date;
    uint32_t number;
} Player;

size_t readData(Player** players);

Source.c:

#include "Header.h"

size_t readData(Player** players) {
    players = NULL;

    players = realloc(players, sizeof(Player*) * 1);
    players[0] = malloc(sizeof(Player));
    strcpy(players[0]->name, "asd");
    printf("$ %s\n", players[0]->name);//OK

    return 1;
}

int main() {
    Player **players = NULL;
    uint32_t elemCount, i;

    elemCount = readData(players);

    printf("> %s", players[0]->name);//BUM - ERROR!

    return 0;
}

I'm using Visual Studio Community 2015. I know it's not so much for coding in C but I managed to configure the solution and it doesn't seem to be the thing imo.

I will be very thankful for help. Yet, I'd like to see it as a remake of my code. I tried some other answers to questions on StackOverFlow like this but they didn't help.


Solution

  • If a parameter of a function is not only read and should be an output too, you have to pass a pointer to your data to the function. If your data type is Player** your paramter type has to be Player ***, so the list of players itselfe is able to be changed inside the function.

    size_t readData(char* fname, Player*** players) {
                                    // ^ players is a input and output parameter
        Player **tempPlayers = *players; // local list of players
        tempPlayers = realloc(tempPlayers, sizeof(Player*) * 1);
        tempPlayers[0] = malloc(sizeof(Player));
        strcpy(tempPlayers[0]->name, "asd");
        printf("$ %s\n", tempPlayers[0]->name);//OK
    
        *players = tempPlayers; // write back list of players to paramter
        return 1;
    }
    
    int main() {
        Player **players = NULL;
        uint32_t elemCount, i;
    
        char *fileName = NULL; 
        elemCount = readData(&players);
                          // ^
    
        printf("> %s", players[0]->name);//BUM - ERROR!
    
        return 0;
    }
    

    If you don't want to use *** you can do it like this:

    Player* *readData(char* fname, Player** players, size_t *size) {
        players = realloc(players, sizeof(Player*) * 1);
        players[0] = malloc(sizeof(Player));
        strcpy(players[0]->name, "asd");
        printf("$ %s\n", players[0]->name);//OK
    
        *size = 1;
        return players;
    }
    
    players = readData( fileName,  players, &elemCount );