Reputation: 19
When I iterate through the 2D array elements to display each int, I get a string of digits. I have tried a number of different things to fix it but I figure it is something small I am overlooking which will bring it all together.
Anyway, in header.h we create
typedef struct gol{
int **board;
size_t size;
}gol;
and in Main.c
void GOL_Opton1(){
printf(" This is running Game Of Life on a default board\n");
gol* mainGOL = (gol*)malloc(sizeof(gol));
mainGOL = create_default_gol();
print_gol(mainGOL);
}
gol* create_default_gol()
{
gol* defaultGol = (gol*)malloc(sizeof(gol));
int defaultArray[20][20];
defaultGol->board = defaultArray;
for (i = 0; i<20; i++){
for (j = 0; j<20; j++){
defaultGol->board[i,j] = 0;
}
}
return defaultGol;
}
void print_gol(gol* g){
printf(" ------------------------------------------------\n");
for (i = 0; i<20; i++){
for (j = 0; j<20; j++){
printf("%d \t",g->board[i,j] );
}printf("\n");
}
}
Option 1, is called from a menu, then the board array in the gol is populated with a set of 0's for a starting point.
Upvotes: 0
Views: 74
Reputation: 40145
#include <stdio.h>
#include <stdlib.h>
typedef struct gol{
int **board;
size_t size;
}gol;
gol *create_gol(size_t size){
size_t i, j;
gol *aGol = (gol*)malloc(sizeof(gol));
aGol->board = malloc(size * sizeof(int*));
aGol->size = size;
for (i = 0; i < size; i++){
aGol->board[i] = malloc(size * sizeof(int));
for (j = 0; j < size; j++){
aGol->board[i][j] = 0;
}
}
return aGol;
}
gol *create_default_gol(void){
return create_gol(20);
}
void print_gol(gol *g){
size_t i, j;
printf("------------------------------------------------\n");
for (i = 0; i < g->size; i++){
for (j = 0; j < g->size; j++){
printf("%d ", g->board[i][j] );
}
printf("\n");
}
}
void GOL_Opton1(void){
printf("This is running Game Of Life on a default board\n");
gol *mainGOL = create_default_gol();
print_gol(mainGOL);
}
int main(void){
GOL_Opton1();
//deallocate
return 0;
}
Upvotes: 0
Reputation: 2731
The specific problem you're facing is in create_default_gol()
.
int defaultArray[20][20];
defaultGol->board = defaultArray;
[...]
return defaultGol;
defaultArray
is alloc'ed in stack, then it's pointer escapes the function. The data you've written to defaultArray
(or ->board
for that matter) will be long gone by the time you access it.
You can correct this by alloc'ing your ->board
on the heap, with malloc
s: one for the entire board (malloc(20 * sizeof( int* ))
), then 20 more for each row (malloc(20 * sizeof( int ))
).
Upvotes: 1
Reputation: 435
There's a few things to improve there. First off, in your header, an easier way to deal with a two-dimensional array would be to store a pointer to the first array element as well as the size. (Your code assumes all boards are square. We'll go with that for now.)
typedef struct { /* No need to name the struct if you typedef it */
int *board; /* We point to the first int, then calculate offsets manually */
size_t size;
} gol;
We can then calculate the position in the array manually. Let's assume we store the numbers in this order:
012
345
678
Now, let's assume we want the element in the 1st row, 2nd column - starting from zero, so really the middle row and last column - we know that there are three columns per row, so rows * columns_per_row + columns
will be the element to look up.
void GOL_Opton1(){
printf(" This is running Game Of Life on a default board\n");
create_default_gol()
already calls malloc
for you. If you assign mainGOL
the return of a malloc
first, you ask for that memory but never use it as you immediately store another address in mainGOL
. That would result in a memory leak.
gol* mainGOL = create_default_gol();
print_gol(mainGOL);
}
To avoid "magic numbers", I'd use a #define
. The default board size is easily adjustable this way, too.
#define DEFAULT_GOL_SIZE 20
gol* create_default_gol()
{
gol* defaultGol = (gol*)malloc(sizeof(gol));
Declaring an array normally allocates it on the stack. However, you want create_default_gol
to return a gol
that can be used by outside functions, so you need to allocate it on the heap. This might result in all kinds of strange behaviour otherwise.
defaultGol->board = malloc(sizeof(int) * DEFAULT_GOL_SIZE * DEFAULT_GOL_SIZE);
defaultGol->size = DEFAULT_GOL_SIZE; /* and store the size */
Here, the memset
function is a common way of quickly setting the entire board to 0.
/* memset avoids an ugly for loop here */
memset(defaultGol->board, defaultGol->size * defaultGol->size, 0);
return defaultGol;
}
void print_gol(gol* g){
size_t row, col;
printf(" ------------------------------------------------\n");
You'll want your print_gol
function to be able to handle boards of a different size than 20, so generalize this to use the size
member.
for (row = 0; row < g->size; row++) {
for (col = 0; col < g->size; col++) {
This is where the offsets discussed above come into play. Your original code had [i, j]
, which wouldn't do what you meant; with an ordinary two-dimensional array, you'd want [i][j]
, but in this case, we are doing the offset calculations manually to allow for arbitrary sizes.
printf("%d \t", g->board[col + row*g->size] );
}
printf("\n");
}
}
Upvotes: 4