Pointers and nested structures

C

Computer Wizard

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!!!
 
M

Miles Davis

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.
 
M

Miles Davis

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.
 
S

santosh

Computer said:
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++
 
M

mark_bluemel

Computer Wizard (surely some mistake - if you ask these questions
you're no Wizard) said:
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.
 
S

Simon Biber

Computer said:
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;
}
 
C

Computer Wizard

Thank you everybody for all the help. I surely can handle such stuff
now........ :)
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top