Pointers and nested structures

Discussion in 'C Programming' started by Computer Wizard, Nov 28, 2006.

  1. Hello,
    I am really scrwed up with the following stuff:

    struct employee
    {
    char* employee_name;
    };

    struct department
    {
    char* department_name;
    struct employee* emp; //Collection of all employees in a
    department
    };

    In main(), I wrote
    struct department* company;

    I want to first enter the name of department and
    then names of employees in that department. I tried with pointers but I
    must hv messed up somewhere n getting segmentation faults. Tried using
    array representation e.g. company.emp[j].employee_name . This also
    failed. I used new operator but it didn't help. Please tell me how to
    deal such thing in pointers.

    Thanks!!!
     
    Computer Wizard, Nov 28, 2006
    #1
    1. Advertising

  2. Computer Wizard

    Miles Davis Guest

    > struct employee
    > {
    > char* employee_name;
    > };


    employee_name is only a pointer and does not hold any memory. It may be
    better to use array instead of pointer here, or you must allocate
    memory for each employee and this operation can easily lead to memory
    leakage.

    char employee_name[MAX_LEN];
    and the struct is not complete cause you want to create a list. you
    should add a member
    struct employee * next;

    struct employee
    {
    char employee_name[MAX_LEN];
    struct employee * next;
    };

    > struct department
    > {
    > char* department_name;


    Here, the same as employee_name

    > struct employee* emp; //Collection of all employees in a
    > department
    > };
    >
    > In main(), I wrote
    > struct department* company;


    company is also a pointer. Follwing this, you should write
    company = (struct department *)malloc(sizeof(struct department));

    >
    > I want to first enter the name of department and
    > then names of employees in that department. I tried with pointers but I


    for each time you add a new employee, allocate memory using malloc,
    make its next point to emp and then make the next of emp point to the
    new memory.

    char temp_name[MAX_LEN];
    company->emp = NULL;
    while (scanf("%s", temp_name) != EOF)
    {
    struct employee * pe = (struct employee *)malloc(sizeof(struct
    employee));
    strcpy(pe->employee_name, temp_name);
    pe->next = company->emp;
    company->emp = pe;
    }

    > must hv messed up somewhere n getting segmentation faults. Tried using
    > array representation e.g. company.emp[j].employee_name . This also
    > failed. I used new operator but it didn't help. Please tell me how to
    > deal such thing in pointers.
    >
    > Thanks!!!


    do not free the memory you allocate at last.
    new is c++ operator and not supported by pure C.

    Sorry for my poor expression.
     
    Miles Davis, Nov 28, 2006
    #2
    1. Advertising

  3. Computer Wizard

    Miles Davis Guest


    > struct employee
    > {
    > char* employee_name;
    > };



    employee_name is only a pointer and does not hold any memory. It may be

    better to use array instead of pointer here, or you must allocate
    memory for each employee and this operation can easily lead to memory
    leakage.

    char employee_name[MAX_LEN];
    and the struct is not complete cause you want to create a list. you
    should add a member
    struct employee * next;


    struct employee
    {
    char employee_name[MAX_LEN];
    struct employee * next;



    };
    > struct department
    > {
    > char* department_name;



    Here, the same as employee_name


    > struct employee* emp; //Collection of all employees in a
    > department
    > };


    > In main(), I wrote
    > struct department* company;




    company is also a pointer. Follwing this, you should write
    company = (struct department *)malloc(sizeof(struct department));


    > I want to first enter the name of department and
    > then names of employees in that department. I tried with pointers but I




    for each time you add a new employee, allocate memory using malloc,
    make its next point to emp and then make the next of emp point to the
    new memory.

    char temp_name[MAX_LEN];
    company->emp = NULL;
    while (scanf("%s", temp_name) != EOF)
    {
    struct employee * pe = (struct employee *)malloc(sizeof(struct
    employee));
    strcpy(pe->employee_name, temp_name);
    pe->next = company->emp;
    company->emp = pe;



    }
    > must hv messed up somewhere n getting segmentation faults. Tried using
    > array representation e.g. company.emp[j].employee_name . This also
    > failed. I used new operator but it didn't help. Please tell me how to
    > deal such thing in pointers.


    > Thanks!!!




    do not forget to free the memory you allocate at last.
    new is c++ operator and not supported by pure C.

    Sorry for my poor expression.
     
    Miles Davis, Nov 28, 2006
    #3
  4. Computer Wizard

    santosh Guest

    Computer Wizard wrote:
    > Hello,
    > I am really scrwed up with the following stuff:
    >
    > struct employee
    > {
    > char* employee_name;
    > };
    >
    > struct department
    > {
    > char* department_name;
    > struct employee* emp; //Collection of all employees in a department
    > };


    As it is, employee is designed to hold the name of only one employee.
    However you indicate in your comments that you want it to hold the
    names of all the employees of a department. To do that, among other
    methods you can do:

    struct employee {
    char *employee_name;
    struct employee *next
    };

    You can use the above to maintain a linked list of employees embedded
    within department.

    An easier method is:

    struct department {
    char *department_name;
    char **employees;
    }

    Then during runtime you can set employees to point to an array of
    pointer of type char, each of which will point to an employee's name
    string.

    You can also use a static array within either employee or department if
    you know in advance the number of employees and that it wouldn't need
    to grow during runtime.

    The linked list method is more flexible since it also allows you to
    hold additional information about each employee along with the name.

    > In main(), I wrote
    > struct department* company;
    >
    > I want to first enter the name of department and
    > then names of employees in that department. I tried with pointers but I
    > must hv messed up somewhere n getting segmentation faults.

    <snip>

    You've simply allocated a pointer to struct of type department. Now
    you'll have to initialise the pointer to point to an actual instance of
    department. You'll have to use malloc() to do so:

    struct employee *tmp;
    company = malloc(sizeof *company);
    if(company != NULL) {
    company->department_name = malloc(SIZE_OF_DEP_NAME);
    if(company->department_name == NULL) DEAL_WITH_ERROR;
    company->emp = malloc(sizeof *emp);
    if(company->emp == NULL) DEAL_WITH_ERROR;
    tmp = company->emp;
    tmp->employee_name = malloc(SIZE_OF_EMP_NAME);
    if(tmp->employee_name == NULL) DEAL_WITH_ERROR;
    }
    else DEAL_WITH_ERROR;

    Now you can store values using the -> operator.

    PS. 'new' is C++. If you're using new then better post in comp.lang.c++
     
    santosh, Nov 28, 2006
    #4
  5. Computer Wizard

    Guest

    Computer Wizard (surely some mistake - if you ask these questions
    you're no Wizard) wrote:
    > Hello,
    > I am really scrwed up with the following stuff:
    >
    > struct employee
    > {
    > char* employee_name;
    > };


    OK - so employee_name points to some storage. How did you assign the
    storage?

    > struct department
    > {
    > char* department_name;
    > struct employee* emp; //Collection of all employees in a
    > department
    > };


    Please don't use "//" comments in usenet postings - they wrap and mess
    things up.
    They are also not supported in the C standards most commonly used.

    In your department structure, you have a pointer to an employee
    structure - where do you assign the space for the employee structure?
    (Alternatively you have a point to the first of an array of employee
    structures - where do you assign the space for them?)

    > In main(), I wrote
    > struct department* company;


    So company is a pointer to a department structure (is that really what
    you meant?). Where do you assign the space for the department
    structure. (Or again, where do you assign the space for the
    array of department structures?)
    >
    > I want to first enter the name of department and
    > then names of employees in that department. I tried with pointers but I
    > must hv messed up somewhere n getting segmentation faults.


    "hv" ? "n"? Please type in English. You are clearly capable of doing
    so.

    > Tried using
    > array representation e.g. company.emp[j].employee_name . This also
    > failed.


    If you haven't assigned space, then whether you express your operations
    directly as pointer operations or as array operations, they will still
    fail.

    > I used new operator but it didn't help.


    There is no "new" operator in C. If you want to ask about C++, go to an
    appropriate newsgroup. If you want to dynamically allocate space in C,
    look at using the malloc() family of functions.

    > Please tell me how to deal such thing in pointers.


    There's a lot to do here and much of it could be better done by reading
    some books or online tutorials.

    However if you really want us to help you, post a complete program
    showing what you have tried and describe what happened.
    >
    > Thanks!!!
     
    , Nov 28, 2006
    #5
  6. Computer Wizard

    Simon Biber Guest

    Computer Wizard wrote:
    > Hello,
    > I am really scrwed up with the following stuff:
    >
    > struct employee
    > {
    > char* employee_name;
    > };


    You'll need to allocate memory for each employee name. That's OK.

    > struct department
    > {
    > char* department_name;
    > struct employee* emp; /* Collection of all employees in a department */
    > };


    Your '//' comment wrapped to the next line. When posting code to Usenet
    groups like comp.lang.c you're better off using traditional /* */
    comments that will not prevent compilation if wrapped.

    You can allocate a block of memory for emp, like an array of employees.
    You then face the problem of how to know how many employees are in the
    array. If you don't want to add another entry to the department struct,
    you can use the employee_name pointer to determine the end of the array.
    If the employee_name is null, then that is the end of the array.

    > In main(), I wrote
    > struct department* company;


    Ok, similarly here you can allocate a block of memory for company, like
    an array of departments. Similarly you can use a null department_name to
    determine the end of the company array.

    > I want to first enter the name of department and
    > then names of employees in that department. I tried with pointers but I
    > must hv messed up somewhere n getting segmentation faults.


    It's pretty easy to mess up in C. Make sure you initialised each pointer
    properly, and that it is pointing to valid memory. Make sure there is
    enough memory allocated for each item you try to store into it. If you
    need to extend an allocated array to make room for more elements, you
    can use realloc().

    > Tried using
    > array representation e.g. company.emp[j].employee_name . This also
    > failed. I used new operator but it didn't help. Please tell me how to
    > deal such thing in pointers.


    company.emp[j].employee_name should work, so long as you allocated
    memory for company, emp and employee_name.

    company = malloc(sizeof *company);
    if(!company) exit(EXIT_FAILURE);

    company[0].emp = malloc(sizeof *company[0].emp);
    if(!company[0].emp) exit(EXIT_FAILURE);

    company[0].emp[0].employee_name
    = malloc(sizeof *company[0].emp[0].employee_name);
    if(!company[0].emp[0].employee_name) exit(EXIT_FAILURE);

    Others have suggested using a linked list. That is one option, but if
    you want to use the structs you have given above without any
    modification, then a realloc solution is a reasonable way to go.

    Here's some example code that I think does what you're trying to do.

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

    struct employee
    {
    char* employee_name;
    };

    struct department
    {
    char* department_name;
    struct employee* emp; /* Collection of all employees
    in a department */
    };

    void err_mem(void)
    {
    fprintf(stderr, "Error allocating memory\n");
    exit(EXIT_FAILURE);
    }

    /* mallocs a copy of the given string and removes
    a newline character if it is present */
    char *get_str(const char *buf)
    {
    char *p = malloc(strlen(buf) + 1), *q;
    if(!p) err_mem();
    strcpy(p, buf);
    q = strchr(p, '\n');
    if(q) *q = 0;
    return p;
    }

    void add_department(struct department *company)
    {
    char buf[128];
    size_t n = 0, alloc = 8; /* initial allocation */
    printf("Enter department name: ");
    fflush(stdout);
    fgets(buf, sizeof buf, stdin);
    company->department_name = get_str(buf);
    company->emp = malloc(alloc * sizeof *company->emp);
    if(!company->emp) err_mem();
    do
    {
    printf("Enter employee name or just hit Enter when done: ");
    fflush(stdout);
    fgets(buf, sizeof buf, stdin);
    if(buf[0] != '\n')
    {
    company->emp[n].employee_name = get_str(buf);
    n++;
    if(n == alloc)
    {
    void *p;
    alloc *= 2;
    p = realloc(company->emp, alloc * sizeof *company->emp);
    if(!p) err_mem();
    company->emp = p;
    }
    }
    } while(buf[0] != '\n');

    /* NULL employee name indicates the
    end of the array of employees */
    company->emp[n].employee_name = NULL;
    }

    struct department *new_company(void)
    {
    size_t n = 0, alloc = 8;
    char buf[128];
    struct department *company = malloc(alloc * sizeof *company);
    if(!company) err_mem();
    add_department(company + n);
    n++;
    do
    {
    printf("Do you want to add another department? (yes/no) ");
    fflush(stdout);
    fgets(buf, sizeof buf, stdin);
    if(!strcmp(buf, "yes\n"))
    {
    add_department(company + n);
    n++;
    if(n == alloc)
    {
    void *p;
    alloc *= 2;
    p = realloc(company, alloc * sizeof *company);
    if(!p) err_mem();
    company = p;
    }
    }
    } while(strcmp(buf, "no\n"));

    /* NULL department name indicates the
    end of the array of departments */
    company[n].department_name = NULL;

    return company;
    }

    void print_department(const struct department *department)
    {
    size_t i;
    printf("Department %s:\n", department->department_name);
    for(i = 0; department->emp.employee_name != NULL; i++)
    {
    printf("Employee %d: %s\n", i + 1,
    department->emp.employee_name);
    }
    }

    void print_company(const struct department *company)
    {
    size_t i;
    for(i = 0; company.department_name != NULL; i++)
    {
    print_department(company + i);
    }
    }

    int main(void)
    {
    struct department *company = new_company();
    print_company(company);
    return 0;
    }

    --
    Simon.
     
    Simon Biber, Nov 29, 2006
    #6
  7. Thank you everybody for all the help. I surely can handle such stuff
    now........ :)
     
    Computer Wizard, Dec 21, 2006
    #7
    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. Replies:
    7
    Views:
    426
  2. tweak
    Replies:
    14
    Views:
    2,800
    Eric Sosman
    Jun 11, 2004
  3. Alfonso Morra
    Replies:
    11
    Views:
    735
    Emmanuel Delahaye
    Sep 24, 2005
  4. Gabriele Modena

    ctypes: nested structures and pointers

    Gabriele Modena, Jan 18, 2010, in forum: Python
    Replies:
    0
    Views:
    511
    Gabriele Modena
    Jan 18, 2010
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    696
Loading...

Share This Page