简体   繁体   中英

C How can I acces struct members of a struct that is part of a struct array in another struct?

If I have the 3 following structs:

/*Structures*/
typedef struct team
{
    char* name;
    int playedGames;
    int score;
}team;

typedef struct matchday
{
    char* date;
    team team1;
    team team2;
    team winner; 
    bool isPlayed;
}matchday;

typedef struct sportSeason
{
    matchday *calendar;
    team *ranking;
    int totalMatches;
    int matchesPlayed;
    int remainingMatches;
}sportSeason;

And the following code:

sportSeason *ptr = malloc(sizeof(sportSeason));

For example

ptr->ranking[0]->name = "Team A";

doesn't work.

Kind regards, AggonyAchilles

full code (for what it's worth):

#define _CRTDDBG_MAP_ALLOC
#define MAX_BUFFER_SIZE 81
#include <stdlib.h>
#include <crtdbg.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

/*Structures*/
typedef struct team
{
    char* name;
    int playedGames;
    int score;
}team;

typedef struct matchday
{
    char* date;
    team team1;
    team team2;
    team winner; 
    bool isPlayed;
}matchday;

typedef struct sportSeason
{
    matchday *calendar;
    team *ranking;
    int totalMatches;
    int matchesPlayed;
    int remainingMatches;
}sportSeason;

/*Function prototypes*/
void initSeason(sportSeason *obj, int n);
void newTeam(team **obj, int *n);
void bufferCheck(char string[]);

int main(void)
{
    char buffer[MAX_BUFFER_SIZE];
    int totalMatches, teams;
    sportSeason *footbalSeason = NULL;

    //Memory allocation
    footbalSeason = malloc(sizeof(sportSeason));

    printf("Welcome to a new season: \n");
    printf("Please enter the following information before registering the teams: \n");
    printf("How many teams are participating: \n");
    fgets(buffer, MAX_BUFFER_SIZE, stdin);
    teams = atoi(buffer);

    initSeason(footbalSeason, teams);


    _CrtDumpMemoryLeaks();
    return 0;
}

void initSeason(sportSeason *obj, int n)
{
    char buffer[MAX_BUFFER_SIZE];

    sportSeason *temp = obj;

    temp->totalMatches = (((n + 1) * n) / 2);
    temp->matchesPlayed = 0;
    temp->remainingMatches = 0;

    printf("Register teams: \n");

    /*Passing the adres of the pointer to the first element of the rank 
      array (team *) */
    newTeam(&(temp->ranking), &n);

}

void newTeam(team **obj, int *n)
{
    char buffer[MAX_BUFFER_SIZE];

    //Allocate memory for all the teams
    obj = malloc((*n) * sizeof(team));

    if (obj == NULL)
    {
        printf("Memory reallocation failed");
    }

    else
    {
        //Add information to struct members
        for (int i = 0; i < (*n); ++i)
        {
            obj[i]->playedGames = 0;
            obj[i]->score = 0;

            printf("\nEnter the team name: ");
            fgets(buffer, MAX_BUFFER_SIZE, stdin);
            bufferCheck(buffer);

            strcpy(obj[i]->name, buffer);

        }
    }
}

there're issues with allocation. when you send pointer to pointer you basicly gives the address of that pointer means if you sent:

  newTeam(&(temp->ranking), &n);

to actually allocate it you'll need: in newTeam to do:

  void newTeam(team **obj, int *n)
  {
    //blahblah
    (*obj) = (team*) malloc(sizeof(team)* (*n));

why? a) p2p is the address of that pointer means to actually refer to pointer we need obj , remember that malloc returns void it's safer this way. if we'll simplify it all to a code in main it will be something like:

int main(){
 sportSeason *ptr = (sportSeason*)malloc(sizeof(sportSeason));
 ptr->totalMatches = ptr->remainingMatches = ptr->remainingMatches = 0;
 ptr->calendar = (matchday*)malloc(4*sizeof(matchday));
 ptr->calendar[0].date = (char*)malloc(sizeof(char) * 4);
 strcpy_s(ptr->calendar[0].date,4,"hi");
 printf("%s", ptr->calendar[0].date);
 //...

it's more than correct to use functions for those actions (really nice that you implemented it in a modular fashion!

a code eg. would be:

  int main(void)
   {
      char buffer[MAX_BUFFER_SIZE];
      int teams;
      sportSeason *footbalSeason = NULL;

      //Memory allocation
      footbalSeason = (sportSeason*)malloc(sizeof(sportSeason));

      printf("Welcome to a new season: \n");
      printf("Please enter the following information before registering the teams: \n");
      printf("How many teams are participating: \n");
      fgets(buffer, MAX_BUFFER_SIZE, stdin);
      teams = atoi(buffer);

      initSeason(footbalSeason, teams);

... void initSeason(sportSeason *obj, int n) { char buffer[MAX_BUFFER_SIZE];

       sportSeason *temp = obj; //bit unnessery to have temp but w/e

       temp->totalMatches = (((n + 1) * n) / 2);
       temp->matchesPlayed = 0;
       temp->remainingMatches = 0;

       printf("Register teams: \n");

       /*Passing the adres of the pointer to the first element of the rank
      array (team *)<-INCORRECT you pass the address to the pointer it's basicly nothing more - you allocate it */
      newTeam(&(temp->ranking), &n);
      printf("%d\n",temp->ranking[0].playedGames); //will print it just fine

   }

   void newTeam(team **obj, int *n)
   {
      *obj = (team*)malloc(sizeof(team)*(*n));
     obj[0]->playedGames = 0; //for eg.

   }

btw we u do when you allocate memory you must actually free it don't be lazy and use the _crt directive since it's applying only in debug mode and not all compilers supports it

so in summary: to access pointer(*) from a p2p(**) you need to use: ptr and allocate that. when you're using malloc please use casting cause it returns void ALWAYS free crap by yourself and don't trust anything, zombies can eat you even if they're in the pc memory:P

tip: i don't know if you know c++ but here's an approach that will help you: think of your functions as constructors of the data you want so if you program in pure c, keep functions that build the object to the fullest and function that destroy the object and clear all the allocations and close files/pipes and what not. hope it helped you if not feel free to ask a follow up and i'll try to answer to the best of my abilities

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM