P
Peter B. Steiger
The latest project in my ongoing quest to evolve my brain from Pascal to C
is a simple word game that involves stringing together random lists of
words. In the Pascal version the whole array was static; if the input
file contained more than [MAX_WORDS] entries, tough.
This time I want to do it right - use a dynamic array that increases in
size with each word read from the file. A few test programs that make use
of **List and realloc( List, blah blah blah) worked fine but when I get to
the actual program things start falling apart.
The problem is that there is not one list of words, but three. I know
from the start that there will always be three, so that part is static:
typedef struct _onelist
{
int wordcount;
char **Words;
} OneList;
....
OneList BigList[ 3 ];
At this point, BigList should contain three static copies of type OneList.
If I pass any one element of BigList to my read-from-file function, all
is well:
ReadFromFile( MyFile, &BigList[ 0 ] );
Over in function ReadFromFile, as long as I'm just receiving the pointer
to a single copy of type OneList, it works exactly as desired:
int ReadFromFile( FILE *MyFile, OneList *List )
{
char **newlistsize;
char *newword;
char buffer[ 100 ];
int lSuccess = 0;
fgets( buffer, sizeof( buffer ), MyFile );
newlistsize = realloc( List, (List->wordcount + 1) * sizeof( newword ) );
if (newlistsize != NULL )
{
if (newword = malloc( (char *) malloc( strlen( buffer ) + 1 ))
{
List = newlistsize;
List->wordcount++;
List->Words[ wordcount ] = newword;
}
}
}
So far, so good. But if, instead, I pass the whole 3-element BigList to
ReadFromFile, it loses track of where the address for each element begins:
// from main:
ReadFromFile( &BigList );
....
int ReadFromFile( OneList *BigList[] );
If I print out the address of BigList in main(), then print out the
address of BigList in ReadFromFile(), the latter shows an address about 4
bytes less than the one main() sent. The address of BigList[ 0 ] (within
the called function) is null, so any attempts to access BigList[ n
]->wordcount or BigList[ n ]->Words[ y ] results in a segfault or other
unpredictable behavior.
I can easily code this a different way so at any given time I only pass
a single OneList type element of the BigList array around, but the point
of this is not just to find something that works, but to learn the right
way of doing it. Is it simply not possible to pass a pointer to the
static three-element BigList array around and still be able to access
individual elements from it?
And to head off any advice about using linked lists instead... once the
five^H^H^H^Hthree word lists are built, my game randomly picks one word
from each list, so I need to be able to grab a single word [n] out of each
array as needed. I could walk through a linked list [n] times, but that
(to me) seems much slower and more tedious than simply referencing Word[n]
out of an array.
is a simple word game that involves stringing together random lists of
words. In the Pascal version the whole array was static; if the input
file contained more than [MAX_WORDS] entries, tough.
This time I want to do it right - use a dynamic array that increases in
size with each word read from the file. A few test programs that make use
of **List and realloc( List, blah blah blah) worked fine but when I get to
the actual program things start falling apart.
The problem is that there is not one list of words, but three. I know
from the start that there will always be three, so that part is static:
typedef struct _onelist
{
int wordcount;
char **Words;
} OneList;
....
OneList BigList[ 3 ];
At this point, BigList should contain three static copies of type OneList.
If I pass any one element of BigList to my read-from-file function, all
is well:
ReadFromFile( MyFile, &BigList[ 0 ] );
Over in function ReadFromFile, as long as I'm just receiving the pointer
to a single copy of type OneList, it works exactly as desired:
int ReadFromFile( FILE *MyFile, OneList *List )
{
char **newlistsize;
char *newword;
char buffer[ 100 ];
int lSuccess = 0;
fgets( buffer, sizeof( buffer ), MyFile );
newlistsize = realloc( List, (List->wordcount + 1) * sizeof( newword ) );
if (newlistsize != NULL )
{
if (newword = malloc( (char *) malloc( strlen( buffer ) + 1 ))
{
List = newlistsize;
List->wordcount++;
List->Words[ wordcount ] = newword;
}
}
}
So far, so good. But if, instead, I pass the whole 3-element BigList to
ReadFromFile, it loses track of where the address for each element begins:
// from main:
ReadFromFile( &BigList );
....
int ReadFromFile( OneList *BigList[] );
If I print out the address of BigList in main(), then print out the
address of BigList in ReadFromFile(), the latter shows an address about 4
bytes less than the one main() sent. The address of BigList[ 0 ] (within
the called function) is null, so any attempts to access BigList[ n
]->wordcount or BigList[ n ]->Words[ y ] results in a segfault or other
unpredictable behavior.
I can easily code this a different way so at any given time I only pass
a single OneList type element of the BigList array around, but the point
of this is not just to find something that works, but to learn the right
way of doing it. Is it simply not possible to pass a pointer to the
static three-element BigList array around and still be able to access
individual elements from it?
And to head off any advice about using linked lists instead... once the
five^H^H^H^Hthree word lists are built, my game randomly picks one word
from each list, so I need to be able to grab a single word [n] out of each
array as needed. I could walk through a linked list [n] times, but that
(to me) seems much slower and more tedious than simply referencing Word[n]
out of an array.