Array of Structures

Discussion in 'C Programming' started by Sam, May 2, 2006.

  1. Sam

    Sam Guest

    Hello I have a structure called Company.

    struct Company
    {
    char *employee;
    char *employee_address;
    };

    I want to build an array of this structure but the number of employees
    will change thorughout the course the programs use so it will need to
    be dynamic.

    I know I need to first allocate the structure and then allocate the
    array of structures but I am confussed on how to do this.

    In my program I am doing the following

    Also for right now I am using

    #Define count = 100; until I get the count function setup properly to
    get the exact count in the future

    void u_setup_company_array(int employee_number)
    {
    int q;
    struct Company CompArray;

    /*Allocate the array structure */
    CompArray= (struct Company ) malloc(count* sizeof(struct Company
    *));

    /*if bad allocation then return */
    if(!CompArray)
    {
    return;
    }

    /*allocate the array and set the variables to Null */
    for(q = 0; q<= count ; h++)
    {
    CompArray[q] = (struct Company ) malloc(sizeof(CompArray));
    CompArray[q]->employee= NULL;
    CompArray[q]->employee_address= NULL;
    }


    /*Once the array is allocated then I pass it and the employee
    number to the other function */
    status = build_company_array(employe_number, CompArray);
    <----Should this be &ComArray instead?


    In another module I would have the function build_company_array


    long build_company_array(int employee_number, structure CompArray)
    {
    /* Read the database and find a match on the employee number */
    int counter = 0;
    while (database_emp#)
    {

    if (database_emp# == employee_number)
    {
    CompArray[count]employee = getName(employee_number);
    CompArray[count]employee_address =
    getAddress(employee_number);
    counter++;
    }
    }
    return 0;
    }

    I guess my questions pertain to proper allocation of the structure and
    the array. It's a simple straight forward structure so I don't think I
    need to make it a pointer to a structure do I?

    Anyway

    1) Am I defining my structure properly in my initial function? Should
    it be struct Company CompArray; or struct Company *CompArray;

    2) Am I allocating the structure properly?
    3) Am I allocating the array properly?
    4) Am I passing the array properly so that when it returns it will be
    populated with the right values that it built in the called function?

    What I want to do is setup the array in the first u_setup_company_array
    function pass the allocated array to the build_company_array function
    in the other module. Once in the other module I populate it. When it
    comes returns to the u_setup_company_array function then it will be
    populated and ready for use in the next step of the
    u_setup_company_array function

    Once done with everything in the array then I would get rid of it which
    i understand what to do there.

    can you guys help?

    Thanks
    Sam

    BTW I am using using c modules compiled in Visual Studios.Net
     
    Sam, May 2, 2006
    #1
    1. Advertising

  2. Sam

    liorm Guest

    You have implemented CompArray as an array of pointers to Company
    (struct type), so CompArray should be declared as struct Company
    **CompArray. Pointer to pointer is actually array of pointers. I don't
    see any other issues with your code except for that.

    LM
     
    liorm, May 2, 2006
    #2
    1. Advertising

  3. Sam

    pete Guest

    Sam wrote:
    >
    > Hello I have a structure called Company.
    >
    > struct Company
    > {
    > char *employee;
    > char *employee_address;
    > };


    > It's a simple straight forward structure so I don't think I
    > need to make it a pointer to a structure do I?


    I don't know what you mean.

    /* BEGIN new.c output */

    Fred
    11 Maiden Lane

    /* END new.c output */


    /* BEGIN new.c */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define COUNT 100

    struct Company {
    char *employee;
    char *employee_address;
    };

    void free_CompArray(struct Company *CompArray, size_t index);

    int main(void)
    {
    struct Company *CompArray;
    size_t index;
    int random;

    CompArray = malloc(COUNT * sizeof *CompArray);
    if (CompArray == NULL) {
    puts("CompArray == NULL");
    exit(EXIT_FAILURE);
    }
    for (index = 0; index != COUNT; ++index) {
    CompArray[index].employee = NULL;
    CompArray[index].employee_address = NULL;
    }
    random = rand() % COUNT;
    CompArray[random].employee = malloc(sizeof "Fred");
    if (CompArray[random].employee == NULL) {
    puts("CompArray[random].employee == NULL");
    exit(EXIT_FAILURE);
    }
    CompArray[random].employee_address
    = malloc(sizeof "11 Maiden Lane");
    if (CompArray[random].employee_address == NULL) {
    puts("CompArray[random].employee_address == NULL");
    exit(EXIT_FAILURE);
    }
    strcpy(CompArray[random].employee, "Fred");
    strcpy(CompArray[random].employee_address, "11 Maiden Lane");
    puts("/* BEGIN new.c output */\n");
    puts(CompArray[random].employee);
    puts(CompArray[random].employee_address);
    free_CompArray(CompArray, COUNT);
    puts("\n/* END new.c output */");
    return 0;
    }

    void free_CompArray(struct Company *CompArray, size_t index)
    {
    const size_t count = index;

    for (index = 0; index != count; ++index) {
    free(CompArray[index].employee);
    free(CompArray[index].employee_address);
    }
    free(CompArray);
    }

    /* END new.c */


    --
    pete
     
    pete, May 3, 2006
    #3
  4. "liorm" <> writes:
    > You have implemented CompArray as an array of pointers to Company
    > (struct type), so CompArray should be declared as struct Company
    > **CompArray. Pointer to pointer is actually array of pointers. I don't
    > see any other issues with your code except for that.


    Pleaes provide context. Read <http://cfaj.freeshell.org/google/> to
    see how and why.

    No, a pointer to pointer is not actually an array of pointers. Arrays
    are not pointers; pointers are not arrays. Please read section 6 of
    the comp.lang.c FAQ, <http://www.c-faq.com/>.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, May 3, 2006
    #4
  5. Sam

    CBFalconer Guest

    Sam wrote:
    >
    > Hello I have a structure called Company.
    >
    > struct Company
    > {
    > char *employee;
    > char *employee_address;
    > };
    >
    > I want to build an array of this structure but the number of
    > employees will change thorughout the course the programs use so
    > it will need to be dynamic.


    The structure would be better labelled "anemployee". At any rate,
    the important thing is what sort of operations do you need to
    perform on these things? Which have to be fast? Which just have
    to be feasible? What items are you likely to add or remove? You
    will probably find that an array is not the right thing to hold the
    collection.

    I suspect you will find that a hash table will do all you want.
    There is one available under GPL at:

    <http://cbfalconer.home.att.net/download/hashlib.zip>

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
     
    CBFalconer, May 3, 2006
    #5
  6. Sam

    Sam Guest

    Hello everybody base upon the information that I got from you guys I
    made the following changes

    struct EmpInfo
    {
    char *employee;
    char *employee_address;
    };

    void u_setup_empinfo_array(int employee_number)
    {
    int q;
    struct EmpInfo *EmpArray;


    count = u_emp_count(employee_number); <--- Counter comes back with
    500
    employees from a read on the database count where the
    employee numbers
    match
    if(!count)
    {
    return;
    }

    /*Allocate the array structure */
    EmpArray= malloc(count * sizeof *EmpArray);

    if(!EmpArray)
    {
    return;
    }

    for(q = 0; h< count ; q++)
    {
    EmpArray[q]->employee= NULL;
    EmpArray[q]->employee_address= NULL;
    }

    /*Get the array of employee info*/
    status = build_empinfo_array(employee_number, EmpArray)

    if(status)
    {
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee);
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);
    return;
    }
    else
    {
    .......do something with it the array
    }

    /*Clean up the array - no longer need it */
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee);
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);
    return
    }

    long build_empinfo_array(int employee_number, EmpInfo *EmpArray)
    {
    int count = 0;
    while (database_emp#)
    {

    if (database_emp# == employee_number)
    {
    EmpArray[count]employee = (char
    *)malloc(sizeof(getName(employee_number)));
    EmpArray[count]employee = getName(employee_number);
    EmpArray[count]employee_address = (char
    *)malloc(sizeof(getAddress

    (employee_number)));
    EmpArray[count]employee_address =
    getAddress(employee_number);
    count++;
    }
    }
    return 0;
    }



    u_emp_count(int employee_number)
    {
    int count = 0;
    while (database_emp#)
    {

    if (database_emp# == employee_number)
    {
    count++;
    }
    }
    return count;
    }
    The arrary comes back to the calling function and the array appears to
    be built correctly with the name and the address of the employee

    The problem that when I am done with the array I want to clear it and
    free it but it crashes on the first line of the clean

    /*Clean up the array - no longer need it */
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee); <-------------------- crashes
    here
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);

    Ass I said the array looks to have been built correctly and you can see
    that prior to the data being placed in the employee variable it is
    malloc'ed with the size of what it gets back from the call. Then I do
    the same call to just get the data into the variable. Something tells
    me that I am still not allocating something properly but what - Advice?

    Thanks
    Sam





    pete wrote:
    > Sam wrote:
    > >
    > > Hello I have a structure called Company.
    > >
    > > struct Company
    > > {
    > > char *employee;
    > > char *employee_address;
    > > };

    >
    > > It's a simple straight forward structure so I don't think I
    > > need to make it a pointer to a structure do I?

    >
    > I don't know what you mean.
    >
    > /* BEGIN new.c output */
    >
    > Fred
    > 11 Maiden Lane
    >
    > /* END new.c output */
    >
    >
    > /* BEGIN new.c */
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > #define COUNT 100
    >
    > struct Company {
    > char *employee;
    > char *employee_address;
    > };
    >
    > void free_CompArray(struct Company *CompArray, size_t index);
    >
    > int main(void)
    > {
    > struct Company *CompArray;
    > size_t index;
    > int random;
    >
    > CompArray = malloc(COUNT * sizeof *CompArray);
    > if (CompArray == NULL) {
    > puts("CompArray == NULL");
    > exit(EXIT_FAILURE);
    > }
    > for (index = 0; index != COUNT; ++index) {
    > CompArray[index].employee = NULL;
    > CompArray[index].employee_address = NULL;
    > }
    > random = rand() % COUNT;
    > CompArray[random].employee = malloc(sizeof "Fred");
    > if (CompArray[random].employee == NULL) {
    > puts("CompArray[random].employee == NULL");
    > exit(EXIT_FAILURE);
    > }
    > CompArray[random].employee_address
    > = malloc(sizeof "11 Maiden Lane");
    > if (CompArray[random].employee_address == NULL) {
    > puts("CompArray[random].employee_address == NULL");
    > exit(EXIT_FAILURE);
    > }
    > strcpy(CompArray[random].employee, "Fred");
    > strcpy(CompArray[random].employee_address, "11 Maiden Lane");
    > puts("/* BEGIN new.c output */\n");
    > puts(CompArray[random].employee);
    > puts(CompArray[random].employee_address);
    > free_CompArray(CompArray, COUNT);
    > puts("\n/* END new.c output */");
    > return 0;
    > }
    >
    > void free_CompArray(struct Company *CompArray, size_t index)
    > {
    > const size_t count = index;
    >
    > for (index = 0; index != count; ++index) {
    > free(CompArray[index].employee);
    > free(CompArray[index].employee_address);
    > }
    > free(CompArray);
    > }
    >
    > /* END new.c */
    >
    >
    > --
    > pete
     
    Sam, May 3, 2006
    #6
  7. Sam

    Sam Guest

    Hello everybody base upon the information that I got from you guys I
    made the following changes

    struct EmpInfo
    {
    char *employee;
    char *employee_address;
    };

    void u_setup_empinfo_array(int employee_number)
    {
    int q;
    struct EmpInfo *EmpArray;


    count = u_emp_count(employee_number); <--- Counter comes back with
    500
    employees from a read on the database count where the
    employee numbers
    match
    if(!count)
    {
    return;
    }

    /*Allocate the array structure */
    EmpArray= malloc(count * sizeof *EmpArray);

    if(!EmpArray)
    {
    return;
    }

    for(q = 0; h< count ; q++)
    {
    EmpArray[q]->employee= NULL;
    EmpArray[q]->employee_address= NULL;
    }

    /*Get the array of employee info*/
    status = build_empinfo_array(employee_number, EmpArray)

    if(status)
    {
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee);
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);
    return;
    }
    else
    {
    .......do something with it the array
    }

    /*Clean up the array - no longer need it */
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee);
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);
    return
    }

    long build_empinfo_array(int employee_number, EmpInfo *EmpArray)
    {
    int count = 0;
    while (database_emp#)
    {

    if (database_emp# == employee_number)
    {
    EmpArray[count]employee = (char
    *)malloc(sizeof(getName(employee_number)));
    EmpArray[count]employee = getName(employee_number);
    EmpArray[count]employee_address = (char
    *)malloc(sizeof(getAddress

    (employee_number)));
    EmpArray[count]employee_address =
    getAddress(employee_number);
    count++;
    }
    }
    return 0;
    }



    u_emp_count(int employee_number)
    {
    int count = 0;
    while (database_emp#)
    {

    if (database_emp# == employee_number)
    {
    count++;
    }
    }
    return count;
    }
    The arrary comes back to the calling function and the array appears to
    be built correctly with the name and the address of the employee

    The problem that when I am done with the array I want to clear it and
    free it but it crashes on the first line of the clean

    /*Clean up the array - no longer need it */
    for(h = 0; h< count ; h++)
    {
    free(EmpArray[q]->employee); <-------------------- crashes
    here
    free(EmpArray[q]->employee_address);
    }
    free(cm8tablename);

    Ass I said the array looks to have been built correctly and you can see
    that prior to the data being placed in the employee variable it is
    malloc'ed with the size of what it gets back from the call. Then I do
    the same call to just get the data into the variable. Something tells
    me that I am still not allocating something properly but what - Advice?

    Thanks
    Sam

    pete wrote:
    > Sam wrote:
    > >
    > > Hello I have a structure called Company.
    > >
    > > struct Company
    > > {
    > > char *employee;
    > > char *employee_address;
    > > };

    >
    > > It's a simple straight forward structure so I don't think I
    > > need to make it a pointer to a structure do I?

    >
    > I don't know what you mean.
    >
    > /* BEGIN new.c output */
    >
    > Fred
    > 11 Maiden Lane
    >
    > /* END new.c output */
    >
    >
    > /* BEGIN new.c */
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > #define COUNT 100
    >
    > struct Company {
    > char *employee;
    > char *employee_address;
    > };
    >
    > void free_CompArray(struct Company *CompArray, size_t index);
    >
    > int main(void)
    > {
    > struct Company *CompArray;
    > size_t index;
    > int random;
    >
    > CompArray = malloc(COUNT * sizeof *CompArray);
    > if (CompArray == NULL) {
    > puts("CompArray == NULL");
    > exit(EXIT_FAILURE);
    > }
    > for (index = 0; index != COUNT; ++index) {
    > CompArray[index].employee = NULL;
    > CompArray[index].employee_address = NULL;
    > }
    > random = rand() % COUNT;
    > CompArray[random].employee = malloc(sizeof "Fred");
    > if (CompArray[random].employee == NULL) {
    > puts("CompArray[random].employee == NULL");
    > exit(EXIT_FAILURE);
    > }
    > CompArray[random].employee_address
    > = malloc(sizeof "11 Maiden Lane");
    > if (CompArray[random].employee_address == NULL) {
    > puts("CompArray[random].employee_address == NULL");
    > exit(EXIT_FAILURE);
    > }
    > strcpy(CompArray[random].employee, "Fred");
    > strcpy(CompArray[random].employee_address, "11 Maiden Lane");
    > puts("/* BEGIN new.c output */\n");
    > puts(CompArray[random].employee);
    > puts(CompArray[random].employee_address);
    > free_CompArray(CompArray, COUNT);
    > puts("\n/* END new.c output */");
    > return 0;
    > }
    >
    > void free_CompArray(struct Company *CompArray, size_t index)
    > {
    > const size_t count = index;
    >
    > for (index = 0; index != count; ++index) {
    > free(CompArray[index].employee);
    > free(CompArray[index].employee_address);
    > }
    > free(CompArray);
    > }
    >
    > /* END new.c */
    >
    >
    > --
    > pete
     
    Sam, May 3, 2006
    #7
  8. Sam

    Thad Smith Guest

    Sam wrote:
    > Hello I have a structure called Company.
    >
    > struct Company
    > {
    > char *employee;
    > char *employee_address;
    > };


    As Charles Falconer suggests, your structure name is misleading. Consider

    struct employee
    {
    char *name;
    char *address;
    };

    The point is that your nomenclature should not be misleading to the code
    reader.

    > I want to build an array of this structure but the number of employees
    > will change thorughout the course the programs use so it will need to
    > be dynamic.


    Here are some choices:
    1. array declared with fixed size (simplest)
    2. array allocated at run time with size which doesn't change after
    allocation (malloc/calloc)
    3. array allocated at run time that can vary during execution (malloc +
    realloc)
    4. dynamic list or tree structure (dynamic allocation with pointers
    linking elements)

    > I know I need to first allocate the structure and then allocate the
    > array of structures but I am confussed on how to do this.


    No. If you allocate an array of structures, you don't need to allocate
    individual structures.

    > In my program I am doing the following
    >
    > Also for right now I am using
    >
    > #Define count = 100; until I get the count function setup properly to
    > get the exact count in the future


    That's
    #define count 100


    > void u_setup_company_array(int employee_number)
    > {
    > int q;
    > struct Company CompArray;
    >
    > /*Allocate the array structure */
    > CompArray= (struct Company ) malloc(count* sizeof(struct Company
    > *));


    If you want to allocate the array at run time, you need to declare a
    pointer to the structure:
    struct employee *CompArray;

    Your allocation will work. The canonical form recommended in this forum is
    CompArray = malloc (count * sizeof (*CompArray));

    Using a pointer to the destination pointer as the sizeof operand helps
    to ensure (an be obvious) that you are using the correct type. Also,
    casting the results of malloc is recommended against in C to allow
    errors to be reported (if, for example, a prototype for malloc has not
    be seen).

    > /*if bad allocation then return */
    > if(!CompArray)
    > {
    > return;
    > }


    It's wise to check, but consider the affect on the function caller.
    There is no indication to either the calling code or the user (via
    stderr or stdout) that an error occurred or what it was.

    > /*allocate the array and set the variables to Null */
    > for(q = 0; q<= count ; h++)

    q?
    > {
    > CompArray[q] = (struct Company ) malloc(sizeof(CompArray));


    No. The space for the struct has already been allocated with the array.
    You should eliminate this.

    > CompArray[q]->employee= NULL;

    ^^ should be .

    >
    > /*Once the array is allocated then I pass it and the employee
    > number to the other function */
    > status = build_company_array(employe_number, CompArray);
    > <----Should this be &ComArray instead?


    No, unless the function will possibly reallocate the array and set the
    new array address. If so, you would declare it differently and specify
    a different functionality.

    >
    >
    > In another module I would have the function build_company_array
    >
    >
    > long build_company_array(int employee_number, structure CompArray)

    This should be struct employee *CompArray ^^^^^^^^^^^^
    > {
    > /* Read the database and find a match on the employee number */
    > int counter = 0;
    > while (database_emp#)


    You cannot use "#" as part of a variable name in C.

    > {
    >
    > if (database_emp# == employee_number)
    > {
    > CompArray[count]employee = getName(employee_number);
    > CompArray[count]employee_address =
    > getAddress(employee_number);
    > counter++;
    > }
    > }
    > return 0;
    > }
    >
    > I guess my questions pertain to proper allocation of the structure and
    > the array. It's a simple straight forward structure so I don't think I
    > need to make it a pointer to a structure do I?


    That depends on what you want to do. You can declare a structure or an
    array of structures without declaring a pointer. If you want to
    dynamically allocate an array, you either need to declare a pointer or
    use a C99 variable size array.

    > 1) Am I defining my structure properly in my initial function? Should
    > it be struct Company CompArray; or struct Company *CompArray;


    Since you are dynamically allocating the array (which is not required
    for the fixed size), you must declare a pointer to the struct.

    > 2) Am I allocating the structure properly?


    > 3) Am I allocating the array properly?


    The structure array is allocated properly. The individual element
    allocation is not.

    > 4) Am I passing the array properly so that when it returns it will be
    > populated with the right values that it built in the called function?


    You are calling properly, but not declaring the function properly.

    > can you guys help?


    We try. ;=)

    --
    Thad
     
    Thad Smith, May 4, 2006
    #8
    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. michi

    Array of structures

    michi, Nov 18, 2004, in forum: C++
    Replies:
    8
    Views:
    521
    Andrey Tarasevich
    Nov 19, 2004
  2. tweak
    Replies:
    14
    Views:
    2,788
    Eric Sosman
    Jun 11, 2004
  3. Alfonso Morra
    Replies:
    11
    Views:
    721
    Emmanuel Delahaye
    Sep 24, 2005
  4. valerio
    Replies:
    3
    Views:
    373
  5. Amit  Limaye
    Replies:
    4
    Views:
    458
    Phlip
    Apr 10, 2006
Loading...

Share This Page