Reputation: 3
I read integer values from a file, parsing them by the space character, then insert them into a int** that is in my structure called game. Using print statements, I have confirm the correct values are being placed in the int** in the correct position, but once I leave the while loop or return the struct, the values being printed are wrong.
My structure:
typedef struct Map_s{
char * defender;
char * attacker;
int missles;
int ** layout;
size_t capacity;
size_t size;
}map;
Initialization of the struct:
map * newGame(){
map * game = malloc(sizeof(map));
game->layout = (int**)malloc(_DEFAULT_MAP_SIZE * sizeof(int*));
game->defender = NULL;
game->attacker = NULL;
game->missles = 0;
game->capacity = _DEFAULT_MAP_SIZE;
game->size = 0;
return game;
}
File parsing:
map * game = newGame();
char * token;
char * dup;
char * ptr;
int ret;
const char delim[2] = " ";
char * buf = NULL;
char * temp = NULL;
size_t size = _MAX_SIZE;
int lineNum = 1;
while( getline(&temp, &size, fp) > 1 ){
buf = strtok(temp, "\n");
dup = strdup(buf);
if( buf[0] != '#' ){
if( lineNum == 1){
if( game->defender == NULL ){
game->defender = dup;
}
}
else if( lineNum == 2 ){
if( game->attacker == NULL )
game->attacker = dup;
}
else if( lineNum == 3 ){
game->missles = atoi(dup);
}
else if( lineNum > 3 ){
token = strtok(dup, delim);
while( token != NULL ){
if( game->size >= game->capacity ){
game->layout = (int**)realloc(game->layout, \
game->capacity*2 * sizeof(int*));
game->capacity = game->capacity * 2;
}
ret = (int)strtol(token, &ptr, 10);
game->layout[game->size] = &ret;
game->size = game->size + 1;
token = strtok(NULL, delim);
//printf("%s ", token);
}
}**
lineNum++;
}
}
return game;
I'm almost positive that my code is messing up somewhere in the second while loop. I am trying to convert the string into an integer and then save it into the correct spot in the int**.
How I am printing from main:
for( size_t i = 0; i < thisgame->size; i++ ){
printf("%d ", *thisgame->layout[i]);
if( i == 0)
continue;
else if( (i+1) % 10 == 0 )
printf("\n");
}
Output from main function after returning struct:
0 0 0 0 0 0 0 0 0 0
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
What output should look like (what's in the file):
2 2 2 2 2 2 2 2 2 2
2 2 6 6 7 7 7 5 5 2
2 2 7 7 7 2 2 17 17 17 2
2 2 2 2 2 2 2 2 2 2
8 8 8 6 6 6 9 9 9 2
2 2 2 2 2 2 2 2 2 2
10 10 10 4 4 9 9 9 2
2 2 2 2 2 2 2 2 2 2
3 3 3 6 6 6 9 9 9 2
3 3 3 6 6 6 9 9 9 2
2 2 2 2 2 2 2 2 2 2
Upvotes: 0
Views: 41
Reputation: 171
The problem is that you are using an array of int* when what you really want is an array of int. Each time you store ret
, you're storing the same address. When you check the value in the loop, it will be correct because ret
contains the value you want... until the next iteration.
Upvotes: 0
Reputation: 1619
There are a couple issues I see.
First is the line **token = strtok(dup, delim);
. At the first run of this line, token
has no valid value, and thus dereferencing it not once, but twice, will also cause issues. I believe this should just be token = strtok(dup, delim);
This will cause the first iteration of the while loop in that if block to return bad values (all those 0s seem to fit this guess, at least).
Second is what D Go pointed out, in that you are giving the address of ret
(which address does not change), so that every element of game->layout
has the same address, and thus looks at the same int (fitting all those 10s).
I think the fix for that would just be to make layout
an array of int *
(tweaking the allocation code to fit), and assign ret
directly to each element.
Upvotes: 0