nested structures and initialization

S

Sheldon

Hi,

Can anyone help with this problem with setting up nested structures
and initializing them for use.
I have created several structs and placed them in a super struct that
I will then pass to some functions. I have defined them in the
following manner:

typedef struct trans Transient;
typedef struct sats Satellites;
typedef struct data Data;
typedef struct super Super;

struct data {
float table_10[ROW*COL];
float table_20[ROW*COL];
float table_30[ROW*COL];
float table_40[ROW*COL];
float table_50[ROW*COL];
float table_60[ROW*COL];
float procent_amsu;
};

struct trans {
char operationalfile[MAXSTR_LENGTH];
char tunedfile[MAXSTR_LENGTH];
char radarfile[MAXSTR_LENGTH];
float amsu_flag[ARRAYSIZE];
float radar[ARRAYSIZE];
float pcpn1[ARRAYSIZE];
float pcpn2[ARRAYSIZE];
float pcpn3[ARRAYSIZE];
};

struct sats {
Data *pN18;
Data *pN17;
Data *pN16;
Data *pN15;
Data *pM02;
};

struct super {
Transient *TR;
Satellites *Sp;
Satellites *Su;
Satellites *Au;
Satellites *Wi;
};

Super* InitStruct(void);

Now when I try to intialize the structure I get a bunch of errors. The
InitStruct functions looks like this:

int main() {

Super *sptr;
/* initializing the super structure */
sptr = InitStruct();
if (sptr == NULL) {
fprintf(stderr,"Failed to initialize nested structure!\n");
exit(EXIT_FAILURE);
} else {
printf("Structure now initialized!\n");
}
return 1;
}

Super *InitStruct(void) {

Super *sptr=NULL;

if(!(sptr=malloc(sizeof(Super)))) {
return NULL;
}
sptr->TR->operationalfile=NULL;
sptr->TR->tunedfile=NULL;
sptr->TR->radarfile=NULL;
sptr->TR->amsu_flag={0.0};
sptr->TR->radar={0.0};
sptr->TR->pcpn1={0.0};
sptr->TR->pcpn2={0.0};
sptr->TR->pcpn3={0.0};

sptr->Sp->N18->table_10={0.0};
sptr->Sp->N18->table_20={0.0};
sptr->Sp->N18->table_30={0.0};
sptr->Sp->N18->table_40={0.0};
sptr->Sp->N18->table_50={0.0};
sptr->Sp->N18->table_60={0.0};
sptr->Sp->N18->procent_amsu = 0.0;

sptr->Sp->N17->table_10={0.0};
sptr->Sp->N17->table_20={0.0};
sptr->Sp->N17->table_30={0.0};
sptr->Sp->N17->table_40={0.0};
sptr->Sp->N17->table_50={0.0};
sptr->Sp->N17->table_60={0.0};
sptr->Sp->N17->procent_amsu = 0.0;
.....

}

The errors begin with these:

error: incompatible types in assignment
error: incompatible types in assignment
error: incompatible types in assignment
error: parse error before '{' token
error: parse error before '{' token

and keeps on going.

Could some please render some help in doing this correctly?

Any help is truly appreciated.
/S
 
K

Keith Willis

Can anyone help with this problem with setting up nested structures
and initializing them for use.
I have created several structs and placed them in a super struct that
I will then pass to some functions. I have defined them in the
following manner:

typedef struct super Super;

struct super {
Transient *TR;
Satellites *Sp;
Satellites *Su;
Satellites *Au;
Satellites *Wi;
};

Super *InitStruct(void) {

Super *sptr=NULL;

if(!(sptr=malloc(sizeof(Super)))) {
return NULL;
}

<snip remainder>

Well the first thing that leaps out is that you've allocated space for
a "struct super", which is simply five pointers. Nowhere do you
allocate the memory that those pointers point at. I'm not even going
to try and see what else is wrong :)
 
S

Sheldon

<snip remainder>

Well the first thing that leaps out is that you've allocated space for
a "struct super", which is simply five pointers. Nowhere do you
allocate the memory that those pointers point at. I'm not even going
to try and see what else is wrong :)

Ok, fair enough. How would you do it then? Let's say a 3 tier struct?
Can you give an example that I can expland on?

/S
 
J

James Kuyper

Sheldon said:
Hi,

Can anyone help with this problem with setting up nested structures
and initializing them for use.
I have created several structs and placed them in a super struct that
I will then pass to some functions. I have defined them in the
following manner:

typedef struct trans Transient;
typedef struct sats Satellites;
typedef struct data Data;
typedef struct super Super;

struct data {
float table_10[ROW*COL];
float table_20[ROW*COL];
float table_30[ROW*COL];
float table_40[ROW*COL];
float table_50[ROW*COL];
float table_60[ROW*COL];
float procent_amsu;
};

Why do you define 6 separate on-dimensional tables, rather than a single
table with a leading dimension of 6? I suspect it will simplify the code
that uses this structure.

I would also recommend combining those typedefs with the corresponding
struct declarations:

typedef struct data {....} Data;

I find that easier to understand; YMMV.
struct trans {
char operationalfile[MAXSTR_LENGTH];
char tunedfile[MAXSTR_LENGTH];
char radarfile[MAXSTR_LENGTH];
float amsu_flag[ARRAYSIZE];
float radar[ARRAYSIZE];
float pcpn1[ARRAYSIZE];
float pcpn2[ARRAYSIZE];
float pcpn3[ARRAYSIZE];
};

Same comment about the pcpn family.
struct sats {
Data *pN18;
Data *pN17;
Data *pN16;
Data *pN15;
Data *pM02;
};

struct super {
Transient *TR;
Satellites *Sp;
Satellites *Su;
Satellites *Au;
Satellites *Wi;
};

Super* InitStruct(void);

Now when I try to intialize the structure I get a bunch of errors. The
InitStruct functions looks like this:

int main() {

Super *sptr;
/* initializing the super structure */
sptr = InitStruct();
if (sptr == NULL) {
fprintf(stderr,"Failed to initialize nested structure!\n");
exit(EXIT_FAILURE);
} else {
printf("Structure now initialized!\n");
}
return 1;
}

Super *InitStruct(void) {

That's a bad naming choice. InitSuper would be better. In general, you
might have quite a lot of different structures to initialize. In this
particular case, you have two of them, which is enough to justify not
naming either function "InitStruct".
Super *sptr=NULL;

if(!(sptr=malloc(sizeof(Super)))) {
return NULL;
}

At this point, none of the pointer members of *sptr have been
initialized. Any use of the value of those pointers has undefined
behavior. You need to allocate memory for each of the pointed at
objects. Note: with this data structure you're going to have to make
LOTS of separate memory allocations. If any one of those fails, then all
of the allocations that succeeded should be free()d. This can get very
complicated very fast. I avoid building structures like this, for
precisely that reason. Therefore, the solution I use below is not the
result of lots of experience with this kind of thing, but it's a lot
better than other techniques I've seen used:

bool successful = true;
// Initialize to make sure that we can free() them without worrying
// about whether they have been allocated:
sptr->TR = NULL;
sptr->Sp = NULL;
// Similarly for other pointer members


if(!(sptr->TR = malloc(sizeof Transient)) ||
!(sptr->Sp = malloc(sizeof Satellites)) ||
// Similarly for other pointer members
){
successful = false;
}

....
sptr->TR->amsu_flag={0.0};

The curly brackets are a syntax error in this context. I think you are
thinking of initialization syntax, but that doesn't apply to dynamically
allocated memory. You'll have to write a loop to initialize that array.
You'll be doing a lot of this, so I'd recommend creating a subroutine
analogous to memset() which works on floats rather than unsigned char.

If you use calloc() instead of malloc(), or use memset() after malloc(),
on many implementations the floats will be properly initialized. That's
because floating point formats which use a representation for 0.0 that
has all of its bits set to 0 are fairly common. However, that's not
guaranteed by the C standard, so you should not use that approach in
code that needs to be portable.

At this point, none of the pointer members of sptr->Sp have been
initialized. Any attempt to use their current value has undefined
behavior. You need to allocate memory for each one, just as I described
above for the pointer members of sptr itself. You'll need to do this
many times, so I recommend writing as subroutine to handle it. Later on,
you'll need to deallocate all of that memory; again, you should use a
subroutine. I'll need to refer to those routines down below, so I'll
call them InitSatellite() and FreeSatellite(). Note: if the argument
passed to FreeSatellite is null, it should return without doing
anything, the same way that free() itself does.

Remember to set successful = false if any of the InitSatellite() calls
fails.

This code should (with appropriate re-writes) be part of InitSatellite():

....
sptr->Sp->N18->table_10={0.0};
....

if(!successful)
{ // Free everything, regardless of whether it's been allocated.
free(sptr->TR);
FreeSatellite(sptr->Sp);
free(sptr->Sp);
// Similarly for other Satellites* members.
free(sptr);
return NULL;
}

return sptr;
// Your original did not appear to include a return statement?
 
M

Mark Bluemel

Sheldon said:
Hi,

Can anyone help with this problem with setting up nested structures
and initializing them for use.
I have created several structs and placed them in a super struct that
I will then pass to some functions. I have defined them in the
following manner:

typedef struct trans Transient;
typedef struct sats Satellites;
typedef struct data Data;
typedef struct super Super;

struct data {
float table_10[ROW*COL];
float table_20[ROW*COL];
float table_30[ROW*COL];
float table_40[ROW*COL];
float table_50[ROW*COL];
float table_60[ROW*COL];
float procent_amsu;
};

struct trans {
char operationalfile[MAXSTR_LENGTH];
char tunedfile[MAXSTR_LENGTH];
char radarfile[MAXSTR_LENGTH];
float amsu_flag[ARRAYSIZE];
float radar[ARRAYSIZE];
float pcpn1[ARRAYSIZE];
float pcpn2[ARRAYSIZE];
float pcpn3[ARRAYSIZE];
};

struct sats {
Data *pN18;
Data *pN17;
Data *pN16;
Data *pN15;
Data *pM02;
};

struct super {
Transient *TR;
Satellites *Sp;
Satellites *Su;
Satellites *Au;
Satellites *Wi;
};

Super* InitStruct(void);

Now when I try to intialize the structure I get a bunch of errors. The
InitStruct functions looks like this:

int main() {

Super *sptr;
/* initializing the super structure */
sptr = InitStruct();
if (sptr == NULL) {
fprintf(stderr,"Failed to initialize nested structure!\n");
exit(EXIT_FAILURE);
} else {
printf("Structure now initialized!\n");
}
return 1;
}

Super *InitStruct(void) {

Super *sptr=NULL;

if(!(sptr=malloc(sizeof(Super)))) {
return NULL;
}

if (!(sptr->TR = malloc(sizeof(Transient))) {
return NULL;
} /* and for the rest of the substructures */
sptr->TR->operationalfile=NULL;
sptr->TR->tunedfile=NULL;
sptr->TR->radarfile=NULL;
sptr->TR->amsu_flag={0.0};

You can't in general assign arrays - this syntax is allowed in
initializers only, I think.

This should work though (I think) :-

sptr->TR->amsu_flag=0;

repeat as needed...

Personally I'd have been inclined to go encapsulated and have functions
to return initialized substructures, I think. (Too much exposure to OO?)
 
J

James Kuyper

Mark Bluemel wrote:
....
This should work though (I think) :-

sptr->TR->amsu_flag=0;

amsu_flag is an array of floats. Therefore it's not a modifiable lvalue
(6.3.2.1p1), so it can't be the left operand of an assignment operator
(6.5.16p2).
 
M

Mark Bluemel

James said:
Mark Bluemel wrote:
...

amsu_flag is an array of floats. Therefore it's not a modifiable lvalue
(6.3.2.1p1), so it can't be the left operand of an assignment operator
(6.5.16p2).

I did wonder, but it compiled (gcc) even with strict options...
 
S

Sheldon

Sheldon said:
Can anyone help with this problem with setting up nested structures
and initializing them for use.
I have created several structs and placed them in a super struct that
I will then pass to some functions. I have defined them in the
following manner:
typedef struct trans Transient;
typedef struct sats Satellites;
typedef struct data Data;
typedef struct super Super;
struct data {
float table_10[ROW*COL];
float table_20[ROW*COL];
float table_30[ROW*COL];
float table_40[ROW*COL];
float table_50[ROW*COL];
float table_60[ROW*COL];
float procent_amsu;
};
struct trans {
char operationalfile[MAXSTR_LENGTH];
char tunedfile[MAXSTR_LENGTH];
char radarfile[MAXSTR_LENGTH];
float amsu_flag[ARRAYSIZE];
float radar[ARRAYSIZE];
float pcpn1[ARRAYSIZE];
float pcpn2[ARRAYSIZE];
float pcpn3[ARRAYSIZE];
};
struct sats {
Data *pN18;
Data *pN17;
Data *pN16;
Data *pN15;
Data *pM02;
};
struct super {
Transient *TR;
Satellites *Sp;
Satellites *Su;
Satellites *Au;
Satellites *Wi;
};
Super* InitStruct(void);
Now when I try to intialize the structure I get a bunch of errors. The
InitStruct functions looks like this:
int main() {
Super *sptr;
/* initializing the super structure */
sptr = InitStruct();
if (sptr == NULL) {
fprintf(stderr,"Failed to initialize nested structure!\n");
exit(EXIT_FAILURE);
} else {
printf("Structure now initialized!\n");
}
return 1;
}
Super *InitStruct(void) {
Super *sptr=NULL;
if(!(sptr=malloc(sizeof(Super)))) {
return NULL;
}

if (!(sptr->TR = malloc(sizeof(Transient))) {
return NULL;
} /* and for the rest of the substructures */
sptr->TR->operationalfile=NULL;
sptr->TR->tunedfile=NULL;
sptr->TR->radarfile=NULL;
sptr->TR->amsu_flag={0.0};

You can't in general assign arrays - this syntax is allowed in
initializers only, I think.

This should work though (I think) :-

sptr->TR->amsu_flag=0;

repeat as needed...

Personally I'd have been inclined to go encapsulated and have functions
to return initialized substructures, I think. (Too much exposure to OO?)- Dölj citerad text -

- Visa citerad text -


Hi,

Thanks for your input. I took your advice and redesigned the script.
Now things are done in smaller steps. But I still get a persistent
error. Here are the new header and source files:
<snip>

typedef struct {
float thres_tables[THRESHOLDS][ROW*COL];
float procent_amsu;
} Data;

typedef struct {
char operationalfile[MAXSTR_LENGTH];
char tunedfile[MAXSTR_LENGTH];
char radarfile[MAXSTR_LENGTH];
float amsu_flag[ARRAYSIZE];
double variables[COMP_VAR][ARRAYSIZE];
Data* satid;
} SUPER;

SUPER* NewSatellite(void);

/* pointers for sub strings */
char *p;
int counter;
SUPER *retv=NULL;

/* initializing the super structure */
retv = NewSatellite();
if (retv == NULL) {
fprintf(stderr,"Failed to initialize nested structure!\n");
exit(EXIT_FAILURE);
} else {
printf("Structure now initialized!\n");
}
/* read the file list one at a time */
file = fopen(datafile,"r");
if (file == NULL) {
fprintf(stderr,"Error: can't open file %s\n", datafile);
exit(EXIT_FAILURE);
} else {
printf("File successfully opened. Reading line by line...\n");
j = 0;
while (fgets(line,MAXLINE_LENGTH,file) != NULL) {
printf("Line %d\t%s\n",++j,line);
/* cutting the strings using delimiter ' ' */
p = strtok(line," ");
counter = 0;
while (p != NULL) {
if (counter == 0) strcpy(retv->tunedfile,p);
p = strtok(NULL," ");
printf("Sub string: %s\n",retv->tunedfile);
counter++;
}
} /* end while */
printf("EOF reached. Closing the file...\n");
fclose(file);
} /* else section if file is open without problem */
return 1;
} /* end main */

/* Initialize the structure */
SUPER* NewSatellite(void) {

int i,j;
SUPER *retv = NULL;

if ((retv = malloc(sizeof(SUPER))) == NULL) {
fprintf(stderr,"Failed to allocate memory for structure!\n");
exit(EXIT_FAILURE);
}

retv->operationalfile = NULL;
retv->tunedfile = NULL;
retv->radarfile = NULL;
retv->satid->procent_amsu = 0.0;
for (i=0; i < COMP_VAR; i++) {
for (j = 0; j < ARRAYSIZE; j++) {
retv->variables[j] = 0.0;
retv->amsu_flag[j] = 0.0;
}
}
for (i=0; i < THRESHOLDS; i++) {
for (j = 0; j < ROW*COL; j++) {
retv->satid->thres_tables[j] = 0.0;
}
}
return retv;
};

but the error remains:
c: In function `main':
c:20: warning: unused variable `i'
c: In function `NewSatellite':
c:73: error: incompatible types in assignment
c:74: error: incompatible types in assignment
c:75: error: incompatible types in assignment
c:76: warning: statement with no effect


What I am missing here?

/S
 
K

Keith Willis

retv->operationalfile = NULL;
retv->tunedfile = NULL;
retv->radarfile = NULL;
c: In function `NewSatellite':
c:73: error: incompatible types in assignment
c:74: error: incompatible types in assignment
c:75: error: incompatible types in assignment
c:76: warning: statement with no effect

I told you in the email I sent you that your initialisation of these
strings was nonsense. You are trying to assign the value NULL to a
variable of type array-of-char. You need to set the first character
of the array-of-char to the value '\0', thus:

retv->operationalfile[0] = '\0';

Alternatively, initialise the entire string to zeros (overkill):

memset(retv->operationalfile, 0, sizeof retv->operationalfile);
What I am missing here?

Clues?
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top