I'm trying to write a code for a Conway's Game of Life in C. I have some problems with 2D array which contain my universe. I will show you a parts of code that cause me a problems. Actually there a two problems that I can't handle.
#include <stdio.h>
#include <stdlib.h>
#include "file2ppm.h"
typedef enum { false, true } bool;
void *allocateMemoryFor2DArray(int x, int y); //allocate memory for 2D array
void initializeUniverseFromFile(char* path, int x, int y, int array[x][y]); //set values of cells from a file
void initializeUniverseRandomly(int x, int y, int array[x][y]); //set random values
int getNumberOfColumns (FILE *file); //get number of columns in file (yDim of Universe)
int getNumberOfLines (FILE *file); //get number of lines in file (xDim of Universe)
void print2DArray (int x, int y, int array[x][y]); //print 2D array
void setDimensionsFromFile(char* path,int* xDim, int* yDim, int* xDimB, int* yDimB);//set dimensions of Universe
int main(int argc, char * argv[])
{
int i, j, n; //loop indexes
int nsteps; //Number of generations
int im, ip, jm, jp; //neighbour boundaries
int yDim, xDim; //Universe boundarier defined by user (Living area);
int xDimB, yDimB; //Universe boundaries expanded to each side by 1
int nsum, isum; //sum of neighbours, sum of alive cells after iteration
//int **old, **new; //Universe
int (*old)[xDimB]; //Universe
int (*new)[xDimB]; //Universe
float x; //to randomize first population
char *inputPath; //Path to file with ixDimBtial uxDimBverse
char *outputPath; //Path to output ppm files
//temporary copy
int yDim_copy, xDim_copy;
printf("argc: %d\n", argc);
switch (argc){
case 4: //Read the initial Universe from file
//Take arguments
nsteps = atoi(argv[1]); //Get number of iterations
outputPath = argv[2]; //Get path for outputimages
inputPath = argv[3]; //File with initialize uxDimBverse;
setDimensionsFromFile(inputPath, &xDim, &yDim, &xDimB, &yDimB);
old = allocateMemoryFor2DArray(xDimB, yDimB); //Alocate memory for expanded Universes
new = allocateMemoryFor2DArray(xDimB, yDimB);
printf("Before initialize: yDim: %d, xDim: %d\n", yDim, xDim); //Here the values are good
//tmp copy
yDim_copy = yDim;
xDim_copy = xDim;
initializeUniverseFromFile(inputPath, xDim, yDim, old);
printf("After initialize: yDim: %d, xDim: %d\n", yDim, xDim); //And here one dim is changed
yDim = yDim_copy; //I took a copy to avoid this problem for now
xDim = xDim_copy;
printf("After taking from copy: yDim: %d, xDim: %d\n", yDim, xDim);//Here dimensions are good again
memcpy (new, old, xDimB*yDimB*sizeof(old[xDimB][yDimB])); //Copy old to new
break;
default:
printf("Usage: %s iter_number, output_name, yDim, xDim\n", argv[0]);
printf("or\n");
printf("Usage: %s iter_number, output_name, ixDimBtial_input_name\n", argv[0]);
printf("Note: Initial file have to be in ./data/\n");
return 1;
}
print2DArray(xDim, yDim, old); //this works fine
printf("In main: yDim: %d, xDim: %d\n", yDim, xDim);
printf("%d\n", old[0][0]); //this works fine
printf("%d\n", old[2][2]); //Segmentation failure
return 0;
}
void *allocateMemoryFor2DArray(int x, int y){
int (*array)[y] = malloc( sizeof(int[x][y]) ); //Allocate memory
if (array == NULL) { /* always check the return of malloc */
perror("malloc");
exit(EXIT_FAILURE);
}
return array;
}
int getNumberOfColumns (FILE *file){
int yDim = 0;
char ch;
do
{
ch = getc(file); //Get 1 char from file
if (ch == '\n') //If ch is new line
{
rewind(file); //Move file pointer to beginxDimBng of file
return yDim; //Found number of columns
}
else
++yDim;
}while (ch != EOF);
}
int getNumberOfLines (FILE *file){
int xDim = 0;
char ch;
do
{
ch = getc(file); //Get 1 char from file
if(ch == '\n') //If new line
{
++xDim; //Increase xDim (another row)
}
}while(ch != EOF);
rewind(file); //Move file pointer to beginxDimBng of file
return xDim;
}
void print2DArray (int x, int y, int array[x][y])
{
int i, j;
printf("x: %d, y: %d\n", x, y);
for (i = 1; i <= x; ++i)
{
for (j = 1; j <= y; ++j)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
}
void setDimensionsFromFile(char* path, int* xDim, int* yDim, int* xDimB, int* yDimB)
{
FILE *file;
int i,j;
file = fopen(path, "r"); //open file
if (file)
{
*yDim = getNumberOfColumns (file);
*xDim = getNumberOfLines (file);
*xDimB = *xDim + 2; // add 2 for left and right torus topology
*yDimB = *yDim + 2;
if (*xDim > 0 && *yDim > 0)
{
printf("UxDimBverse dimension %d x %d\n", *xDim , *yDim);
}
else
{
perror("Wrong initialize file");
exit(EXIT_FAILURE);
}
fclose(file); //Close file
}
else
{
perror("Open initialize file error");
exit(EXIT_FAILURE);
}
}
void initializeUniverseFromFile(char* path, int x, int y, int array[x][y])
{
FILE *file;
int i,j;
file = fopen(path, "r"); //open file
if (file)
{
//IxDimBtialize array
char *ch;
for (i = 1; i <= x; i++)
{
//printf("i: %d ", i);
for (j = 1; j <= y; j++)
{
//printf("j: %d ", j);
if (fscanf(file, "%c", ch) != 1)
{
perror("Read error\n");
}
else if (isdigit((unsigned char)*ch))
{
printf("%d", atoi(ch));
array[i][j] = atoi(ch);
}
else
{
//printf("Numer znaku: %d ", ch);
j--;
}
}
printf("\n");
}
printf("Done reading\n");
fclose(file); //Close file
}
else
{ //File open error
perror("Open initialize file error");
exit (EXIT_FAILURE);
}
printf("In initialize yDim: %d, xDim: %d\n", x, y);
}
void initializeUniverseRandomly(int x, int y, int array[x][y])
{
int i, j;
float r;
for (i = 1; i <= x; i++) {
for (j = 1; j <= y; j++) {
r = rand() / ((float)RAND_MAX + 1);
if (r<0.5) {
array[i][j] = i*x+j;
}
else {
array[i][j] = i*x+j;
}
}
}
}
Problem 1:
I set the dimensions of universe (variables xDim and yDim). I print them in line 45 (check comment //Here the values are good). Then I call initializeUniverseFromFile(inputPath, xDim, yDim, old);
And one of the dimensions values is changed. I have no idea why. That's why I make temporary copy of this variables, because I've spent 2 hours looking for that error. I even print out this variables at the end of that initializeUniverseFromFile
function, and they are fine. But when I'm back in main again (line 50), the value is changed. This is minor problem. The worse is:
Problem 2 I have a pointer int (*old)[xDimB];
xDimB is xDim+2 so it is always bigger than xDim
I initialize the array with function
allocateMemoryFor2DArray(xDimB, yDimB)
Then I do this:
print2DArray(xDim, yDim, old); //this works fine
printf("In main: yDim: %d, xDim: %d\n", yDim, xDim); //Dimensions are fine
printf("%d\n", old[0][0]); //this works fine
for (i=0; i<=xDim; ++i)
printf("%d ", old[0][i]; //this works fine too
printf("%d\n", old[2][2]); //Segmentation failure
Printing whole array with function is fine Printing values from first row are fine Printing value from middle of array create error.