NEWBIE: malloc an array????

M

mike79

Hi all!

I am having problems properly malloc'ing an array. The problem is, I
have a structure called "array" which contains 2 elements, "int
arraySize" (how many elements are in the array) and "wordArray" (the
actual array itself).

The "word structure" consists of 2 elements, "int occurrence" (the
number of times that particular word occurs in say a sentence, and
"char *string" (the actual word itself).

So the two structures look like this:

typedef struct words
{
int occurrence;
char *string;
}word;

typedef struct arrays
{
int arraySize;
word *wordArray;
}array;

So what I am trying to do is create 1 structure of "array" to keep
track of the number of elements(words) contained in that array, and
the array itself.

The "array" structure contains an array of "word" structures. And the
"word" structure contains an array of "chars" i.e. a string.

So just say I wish to allocate memory for an array of 20 "word"
elements, each word element has a string of 30 chars. How would I do
this?

I tried the code below but i keep getting errors.. please help me!

array *array1;
int element, number;

array1 = malloc(1); // Allocating memory to the array

number = 20; // 20 word elements in the array
array1->wordArray = malloc(number * sizeof *array->wordArray);

element = 0;
while (element < number)
{
array1->wordArray[element].string = malloc(30);
element++;
}

Thank you all so much for your help!
mike79
 
B

Ben Pfaff

typedef struct words
{
int occurrence;
char *string;
}word;

typedef struct arrays
{
int arraySize;
word *wordArray;
}array;
[...]
array *array1;
int element, number;

array1 = malloc(1); // Allocating memory to the array

An `array' is bigger than 1 byte. You must allocate enough
space.
array1 = malloc (sizeof *array1);

Don't forget to check for a null pointer return from malloc().
number = 20; // 20 word elements in the array
array1->wordArray = malloc(number * sizeof *array->wordArray);
^^^^^ array1

You forgot to initialize array1->arraySize.
element = 0;
while (element < number)
{
array1->wordArray[element].string = malloc(30);

Don't forget to check for a null pointer return.
element++;
}

Looks okay, but why not use a `for' loop? And why pre-allocate
30 bytes for each word instead of just allocating however many
are needed when they are needed?

You forgot to initialize array1->wordArray[element].occurrence.
 
B

Barry Schwarz

Hi all!

I am having problems properly malloc'ing an array. The problem is, I
have a structure called "array" which contains 2 elements, "int
arraySize" (how many elements are in the array) and "wordArray" (the
actual array itself).

The "word structure" consists of 2 elements, "int occurrence" (the
number of times that particular word occurs in say a sentence, and
"char *string" (the actual word itself).

So the two structures look like this:

typedef struct words
{
int occurrence;
char *string;
}word;

typedef struct arrays
{
int arraySize;
word *wordArray;
}array;

So what I am trying to do is create 1 structure of "array" to keep
track of the number of elements(words) contained in that array, and
the array itself.

The "array" structure contains an array of "word" structures. And the

The "array" structure contains a pointer to a "word" structure. This
word structure can be the first of a sequence of such structures which
can be treated as an array.
"word" structure contains an array of "chars" i.e. a string.

The "word" structure contains a pointer to a char. This char can be
the first of a sequence of such char which can be treated as a string
(if the sequence is properly terminated).
So just say I wish to allocate memory for an array of 20 "word"
elements, each word element has a string of 30 chars. How would I do
this?

I tried the code below but i keep getting errors.. please help me!

array *array1;
int element, number;

array1 = malloc(1); // Allocating memory to the array

You have allocated space for one byte. This is inadequate to hold an
object of type array. To allocate enough space for one "array"
structure, try
array1 = malloc(sizeof *array1);

The real question is: since you only want one "array" structure, why
do you go through all the work of defining a pointer and allocating
space when it is much easier to simply define one instance of the
object
array array1;
and then use the . operator instead of the -> operator.
number = 20; // 20 word elements in the array
array1->wordArray = malloc(number * sizeof *array->wordArray);

I assume this is a typo and you meant
(number * sizeof *array1->wordArray)
element = 0;
while (element < number)

Think of a for loop which will do all the initializing, testing, and
incrementing for you
for (element = 0; element < number; element++)
{
array1->wordArray[element].string = malloc(30);
element++;
}

You should of course be testing every malloc call for success.


<<Remove the del for email>>
 
B

Bruno Desthuilliers

mike79 said:

Hi one !-)

<standard-disclaimer>
Everything I say here is to take with caution, since I don't use C so
frequently. Gurus please correct me if I say some stupidities.
I am having problems properly malloc'ing an array. The problem is, I
have a structure called "array" which contains 2 elements, "int
arraySize" (how many elements are in the array) and "wordArray" (the
actual array itself).

The "word structure" consists of 2 elements, "int occurrence" (the
number of times that particular word occurs in say a sentence,

Unless you have a need for this to be negative, you'd better make
'occurrences' a size_t IMHO.
and
"char *string" (the actual word itself).

So the two structures look like this:

typedef struct words
{
int occurrence;
char *string;
}word;

typedef struct arrays
{
int arraySize;

idem, this would probably be better as a size_t.
word *wordArray;
}array;

So what I am trying to do is create 1 structure of "array" to keep
track of the number of elements(words) contained in that array, and
the array itself.

The "array" structure contains an array of "word" structures. And the
"word" structure contains an array of "chars" i.e. a string.

So just say I wish to allocate memory for an array of 20 "word"
elements, each word element has a string of 30 chars. How would I do
this?

Why do you want to pre-allocate anything ? You're using dynamic memory,
so why not just create or modify elements when needed ?
I tried the code below but i keep getting errors.. please help me!

array *array1;
/*int element, number;*/
size_t element;

You don't need 'number', since you have the wordArray.arraySize
array1 = malloc(1); // Allocating memory to the array

As Ben Pfaff already pointed, you'll need more than byte !-)
You also want to check the return of malloc(), since it may fail.
array1 = malloc(sizeof *array1);
if (array1 == NULL)
{
/* handle the case, probably exit */
}
/* number = 20; // 20 word elements in the array */
array1->arraySize = 20;
array1->wordArray = malloc(number * sizeof *array->wordArray);
I'm not sure you are dereferencing the right thing (any guru around ?)
so to be sure :

array1->wordArray = malloc(array1->arraySize
* sizeof *(array1->wordArray)
);

here again, you want to check the return of malloc()
if (array1->wordArray == NULL)
{
/* handle the case, probably exit */
}

/* element = 0; */
/*while (element < number)*/
for (element = 0; element said:
{
array1->wordArray[element].string = malloc(30);

here again, you want to check the return of malloc().
/* element++; the for loop takes care of this */
}

Thank you all so much for your help!

(this is more about conception and code organization than pure coding
but...)


The (I think) usual way to handle this kind of problem is to write
specialized code for operations on both structs. So this would give you
a word.h // word.c pair and a wordarray.h // wordarray.c pair.

The 'word' module would handle all operations on words, like creation,
destruction, 'occurrences' increase and/or decrease, etc.

The 'wordarray' module would handle all operations on word arrays, like
creation, destruction, adding a word, removing a word, finding a word[1]
etc.

This allow to :
- test, debug etc the word and wordarray modules by themselves
- get rid of word and wordarray internal mechanisms in the main code.
- eventually modify the implementation of word and wordarray without
changing the calling code (wordarray could as well be implemented as a
linked list or whatsoever).
- eventually reuse word and wordarray in other programs.

Then the main code just have to worry about logical operations, not
about implementation.

[1] as an exemple - I guess that your concern here is to count
occurrences of words in a text - you could have (in the wordarray
module) an operation on wordarray that search if a word is already in
the array, increase it's 'occurrences' count if yes, add it to the array
and set it's occurrence count to 1 if not :

/*
* WARNING : Q&D code, just a sketch, not even tested
* could probably be made far better, etc...
*/
int wordarray_countWord(wordArray *the_array, const char *what)
{
size_t i = 0;
int found = 0;
int err = 0;

/*
* look for 'what' in the array,
* increase its occurences count if found
*/
for (i = 0; i < the_array.size; i++)
{
if (strcmp(the_array, what) == 0)
{
/*
* we suppose that wordArray stores
* an array of word*, not an array of word
*/
the_array->occurrences += 1;
found = 1;
break;
}
}

/*
* 'what' has not been found, so we had it
* with an occurence count at 1.
* NB : the wordarray_addWord() function takes
* care of creating the 'word' object from the
* string and occurrence count.
*/
if (! found)
{
err = wordarray_addWord(what, 1);
}

return err;
}


So in the main program module, you'd just need this :

int countWords(wordarray *the_array, wordParser *parser)
{
char *what;
int err = 0;

while ( (what = wordparser_getNextWord(parser, 0)) != NULL)
{
err = wordarray_countWord(what);
free(what);
what = NULL;

if (err != 0)
{
/* handle the error */
}
}

return err;
}

My 2 cents...
Bruno
 
C

CBFalconer

mike79 said:
I am having problems properly malloc'ing an array. The problem is,
I have a structure called "array" which contains 2 elements, "int
arraySize" (how many elements are in the array) and "wordArray"
(the actual array itself).

The "word structure" consists of 2 elements, "int occurrence"
(the number of times that particular word occurs in say a sentence,
and "char *string" (the actual word itself).

So the two structures look like this:

typedef struct words
{
int occurrence;
char *string;
}word;

typedef struct arrays
{
int arraySize;
word *wordArray;
}array;

So what I am trying to do is create 1 structure of "array" to keep
track of the number of elements(words) contained in that array, and
the array itself.

The "array" structure contains an array of "word" structures. And the
"word" structure contains an array of "chars" i.e. a string.

STOP right here. The word structure, as you have defined it,
contains an int, and A POINTER TO a char. It DOES NOT contain an
array of chars.

Similarly, your array contains an int and a POINTER TO a word.

In neither case has the pointer been initialized, and it cannot be
initialized until the storage that holds it has been allocated.
After that memory for it to point to must be allocated, and the
pointer set to point to that space. Also remember that malloc()
can fail, and each call must be checked for success.

Now start over designing your code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top