NEWBIE: malloc an array????

Discussion in 'C Programming' started by mike79, Nov 5, 2003.

  1. mike79

    mike79 Guest

    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
     
    mike79, Nov 5, 2003
    #1
    1. Advertising

  2. mike79

    Ben Pfaff Guest

    (mike79) writes:

    > 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.
    --
    "I'm not here to convince idiots not to be stupid.
    They won't listen anyway."
    --Dann Corbit
     
    Ben Pfaff, Nov 5, 2003
    #2
    1. Advertising

  3. On 4 Nov 2003 16:37:46 -0800, (mike79) wrote:

    >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>>
     
    Barry Schwarz, Nov 5, 2003
    #3
  4. mike79 wrote:
    > Hi all!


    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.
    </standard-disclaimer>

    > 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 < array1->arraySize; element++)
    > {
    > 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
     
    Bruno Desthuilliers, Nov 5, 2003
    #4
  5. mike79

    CBFalconer Guest

    mike79 wrote:
    >
    > 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.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Nov 5, 2003
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John
    Replies:
    13
    Views:
    716
  2. ravi
    Replies:
    0
    Views:
    461
  3. Peter
    Replies:
    34
    Views:
    1,993
    Richard Tobin
    Oct 22, 2004
  4. porting non-malloc code to malloc

    , Feb 18, 2005, in forum: C Programming
    Replies:
    3
    Views:
    487
    Walter Roberson
    Feb 19, 2005
  5. Johs32

    to malloc or not to malloc??

    Johs32, Mar 30, 2006, in forum: C Programming
    Replies:
    4
    Views:
    333
    Captain Winston
    Mar 30, 2006
Loading...

Share This Page