1

I've been trying to wrap my head around this the whole day...

The code that I have so far works as planed, the idea is that I'll have to change tCell * cells[3][5]; to take a size that's given at runtime. What changes do I need to make to retain the functionality?

typedef struct {
  int active;

} tCell;

typedef struct {
  tCell * cells[3][5];

} tGrid;

// creates a grid and initialize all the cells to NULL
tGrid *init_grid()
{
  tGrid *grid= malloc(sizeof(tGrid));

  if(grid == NULL)
      exit(127); // failed to malloc

  int i, j;
  for(i=0; i < 3; i++)
    for(j=0; j < 5; j++)
      grid->cells[i][j]= NULL;

  return grid;
}

// adds a cell to the grid
void add_cell(tGrid *grid)
{
    tCell cell;

    int y = rand() % 4;

    if(grid->cells[0][y] != NULL)
        exit(127); // cell is taken

    cell.active = 1;
    grid->cells[0][y] = &cell;
}

void remove_cell(tGrid *grid, int x, int y)
{
    if(x < 0 || x > 3 || y < 0 || y > 5)
        exit(127); // out of bounds

    grid->cells[x][y]= NULL;
}

Basically, init_grid will have to take x and y as parameters:

tGrid *init_grid(int x, int y);

But then, how do I change tGrid struct definition? Whatever I've tried so far yielded a compiler error (e.g. tCell * cells[][];)

On a slightly related note, how do you read "tCell * cells[3][5];" outloud?

Note:

  • this is a C question
  • I'm using gcc 4.1 to compile the code
littleadv
  • 20,100
  • 2
  • 36
  • 50
apann
  • 397
  • 1
  • 2
  • 8

1 Answers1

3

Easy.

typedef struct {
  int rows;
  int columns;
  tCell **cells;
} tGrid;

And allocating:

tGrid *pGrid = (pGrid*)malloc(sizeof(tGrid));
/* check results etc */
pGrid->rows = rows;
pGrid->columns = columns;
pGrid->cells = (tCell**)malloc(sizeof(tCell*)*rows);
/* check results */
do{
    pGrid->cells[rows-1] = (tCell*)malloc(sizeof(tCell)*columns);
    /* check results */
} while (--rows);

Done.

Or, you can also do:

typedef struct {
  int rows;
  int columns;
  tCell *cells;
} tGrid;
/*****whatever in the middle ***********/
pGrid->cells = (tCell*)malloc(sizeof(tCell)*rows*columns);

instead of the do-while loop. The difference is that in the first case, each row will be a separate array in the memory, which may be useful when handling the thing.

Of course, in the end, for each malloc there has to be a free.

littleadv
  • 20,100
  • 2
  • 36
  • 50
  • should I assume that remove_cell will just need to free the cell at x/y? – apann Sep 29 '11 at 06:59
  • on a second thought, this is not exactly the same: my *cells[][] is an array of pointes to tCell struct initialized with null pointer, not an array of tCells (initialized with 0'ed values). – apann Sep 30 '11 at 09:41
  • @apann, just add another level of indirection. – littleadv Sep 30 '11 at 09:46