You have stumbled onto the challenge where you must simulate a 2d array from a simple 1d array. If you look at the function declaration you are given, you have GW *gw_build(...) which tells you gw_build will return an array of struct GW. Now ideally, you could make things easier by creating an array of pointers to struct GW, but obviously part of the assignment is to have you work with a simple array of struct.
This simplifies the allocation, but complicates the indexing. Meaning, your declaration of gw_build can simply be:
GW *gw_build(int nrows, int ncols, int pop, int rnd){
GW *list = calloc (nrows * ncols, sizeof *list);
if (!list) {
fprintf (stderr, "gw_build() error: virtual memory exhausted.\n");
return NULL;
}
return list;
}
But the challenge then comes in filling and referencing each, especially if you want a pseudo-2d representation. The assignment is really an exercise in understanding pointers as well as index manipulation. The best way to talk about this is by example. (note: below, I've included the declaration of gw_struct in gw.h, but if you can't do that, just put the declaration in each source file)
#ifndef _gw_header_
#define _gw_header_ 1
typedef struct gw_struct GW;
struct gw_struct {
int Alive;
int row;
int column;
int id;
};
extern GW *gw_build(int nrows, int ncols, int pop, int rnd);
#endif
The #ifdef _gw_header_ is just an example of controlling header file inclusion. It insures gw.h is only included once. You can scrap it if you can't add to the header file.
The source file gw.c simply needs to allocate nrows * ncols structs, so it can be as simple as:
#include <stdio.h>
#include <stdlib.h>
#include "gw.h"
GW *gw_build(int nrows, int ncols, int pop, int rnd){
GW *list = calloc (nrows * ncols, sizeof *list);
if (!list) {
fprintf (stderr, "gw_build() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
return list;
}
Both standard and not much to discuss. The real work comes in your source file containing main() where you will fill and use the array returned by gw_build.
#include <stdio.h>
#include "gw.h"
#define ROWS 10
#define COLS 10
int main (void) {
GW *world = gw_build (ROWS, COLS, 34, 1);
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
(world + i * ROWS + j)->Alive = (i*ROWS + j) % 3;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
printf (" world[%2d][%2d] : %d\n", i, j, (world + i*ROWS + j)->Alive);
return 0;
}
(for example purposes, I've just filled Alive with values between 0-2 depending on the index value)
When you receive the allocated array back from gw_build you must manage filling and use by offset from the beginning of the array. You can simply use (0 < index < (nrows*ncols)), but that will defeat using the pseudo 2D indexing. The trick is simply finding a way to calculate and reference each offset using 2D array syntax. If you note above, the offset of each struct is accessed by i * ROWS + j. That allows the psuedo-2D reference of array[i][j] where behind the scene i represents i * nrows and j just the additional offset from that address.
You also have the choice of using the -> operator to reference the cells as shown above, or you can write an equivalent form that uses the . operator for struct member reference. The alternative is shown below:
#include <stdio.h>
#include "gw.h"
#define ROWS 10
#define COLS 10
int main (void) {
GW *world = gw_build (ROWS, COLS, 34, 1);
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
world[i * ROWS + j].Alive = (i * ROWS + j) % 3;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
printf (" world[%2d][%2d] : %d\n", i, j, world[i * ROWS + j].Alive);
return 0;
}
Look over both and let me know if you have questions. I've used two #define statements to fix nrows and ncols for the example. Compiling and running the code, you will see the output:
$ ./bin/gwtest
world[ 0][ 0] : 0
world[ 0][ 1] : 1
world[ 0][ 2] : 2
world[ 0][ 3] : 0
world[ 0][ 4] : 1
world[ 0][ 5] : 2
world[ 0][ 6] : 0
world[ 0][ 7] : 1
world[ 0][ 8] : 2
world[ 0][ 9] : 0
world[ 1][ 0] : 1
world[ 1][ 1] : 2
world[ 1][ 2] : 0
world[ 1][ 3] : 1
world[ 1][ 4] : 2
world[ 1][ 5] : 0
world[ 1][ 6] : 1
world[ 1][ 7] : 2
world[ 1][ 8] : 0
world[ 1][ 9] : 1
world[ 2][ 0] : 2
...
world[ 8][ 8] : 1
world[ 8][ 9] : 2
world[ 9][ 0] : 0
world[ 9][ 1] : 1
world[ 9][ 2] : 2
world[ 9][ 3] : 0
world[ 9][ 4] : 1
world[ 9][ 5] : 2
world[ 9][ 6] : 0
world[ 9][ 7] : 1
world[ 9][ 8] : 2
world[ 9][ 9] : 0