how to iterate through all members in a struct

J

jaso

Hi,

If have a structure of a database record like this:
struct record {
char id[ID_LENGTH];
char title[TITLE_LENGTH];
...
};
Is there some way to find out how many member variables there is
in the struct and then iterate through them?
I want to have a function that takes the struct as argument and
then prompts the user for input for all the members. And instead
of coding the input for every member variable, I want the function
to automatically update each member. That will make it easier to
update the struct with more members.
The function also needs to know the length of every string in the
struct, so maybe I should add a length variable to each string
in the struct.

Is that feasible? Or can you recommend an other way?
 
J

Jolting

In C you can't just add something to a struct without recompiling.
One thing you can do is create a stack.
struct record_entry{
char field_name[20];
char field_data[MAXSIZE];
struct record_entry *next;
}
then each time you want to add something.
you put the next thing on the end of the stack.

record->record_entry->record_entry->record_entry->NULL
The trick to interating through something like this is to set the last
entry as NULL.
It will only be NULL if it gets to the end.

int main(){
struct record_entry record, *new;
new = (struct record_entry*)malloc(sizeof(record));
record.next = new;
new->next = NULL;
}
 
G

Gordon Burditt

If have a structure of a database record like this:
struct record {
char id[ID_LENGTH];
char title[TITLE_LENGTH];
...
};
Is there some way to find out how many member variables there is
in the struct and then iterate through them?

No. And iterating through variables of unknown type is of questionable
usefulness.
I want to have a function that takes the struct as argument and
then prompts the user for input for all the members. And instead
of coding the input for every member variable, I want the function
to automatically update each member.

With very rare exceptions (like deallocation of auto variables), C
doesn't "automatically" anything. You have to write code for that.
That will make it easier to
update the struct with more members.
The function also needs to know the length of every string in the
struct, so maybe I should add a length variable to each string
in the struct.
Is that feasible? Or can you recommend an other way?

It *is* possible to create a description of the structure,
giving the prompt, size limit, offset (using the offsetof() macro),
allowed character set, etc. of each field, and have your function
use that. Of course, you have to remember to update it.

Gordon L. Burditt
 
J

jaso

jaso said:
Hi,

If have a structure of a database record like this:
struct record {
char id[ID_LENGTH];
char title[TITLE_LENGTH];
...
};
Is there some way to find out how many member variables there is
in the struct and then iterate through them?
I want to have a function that takes the struct as argument and
then prompts the user for input for all the members. And instead
of coding the input for every member variable, I want the function
to automatically update each member. That will make it easier to
update the struct with more members.
The function also needs to know the length of every string in the
struct, so maybe I should add a length variable to each string
in the struct.

Is that feasible? Or can you recommend an other way?

This is one way I come up with, what do you think about it?

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

#define NOT_NULL 1
#define NUMERIC 2
#define MULTI_LINE 4

struct field_desc {
char *name;
int length;
int type;
};

struct field_desc movies_desc[] = {
{ "id", 1, NOT_NULL | NUMERIC },
{ "test", 34, 0 },
{ "title", 50, NOT_NULL },
{ "genre", 15, NOT_NULL },
{ "length", 3, NOT_NULL | NUMERIC },
{ "description", 65535, MULTI_LINE },
{ "owner", 10, NOT_NULL } };

#define MOVIES_LENGTH (sizeof(movies_desc)/sizeof(movies_desc[0]))

/* fills record with input data from user */
int fill_record(char *entries[], struct field_desc desc[], int length)
{
int i;
for (i = 0; i < length; i++) {
if (fill_string(desc.name, &entries,
desc.length, desc.type) != 0)
return -1;
}
return 0;
}

int fill_string(char *prompt, char **str, int length, int type)
{
size_t len;
*str = malloc(length + 1);
if (*str == NULL)
return -1;

printf("%s: ", prompt);
fflush(stdout);
fgets(*str, length + 1, stdin);

if (!(type & MULTI_LINE)) {
len = strlen(*str);

if ((*str)[len - 1] == '\n')
(*str)[len - 1] = '\0';
}

return 0;
}

int main(void)
{
char *movies_record[MOVIES_LENGTH];

/* connect to database */
/* snipped */

fill_record(movies_record, movies_desc, MOVIES_LENGTH);

/* database stuff */

return EXIT_SUCCESS;
}

I know its not bug free, but thats not the point now.
This way I can just add one element to the field_desc array
and nothing more needs to be modified. But at the call
to fill_record I need to pass the array containing the
fields, the description and the length.
Maybe it would be cleaner if this data could be
stored in one struct.

struct movies_record {
char *entries[MOVIES_LENGTH];
struct field_desc *desc;
int length;
};

But here the desc and length variables can point to anything,
but I want it to just point to movies_desc and length set to
MOVIES_LENGTH;
i.e I would want something like this
struct movies_record {
char *entries[MOVIES_LENGTH];
struct field_desc *desc = movies_desc;
int length = MOVIES_LENGTH;
};
which is illegal..
So I really don't know how to do it. Any opinions?
 
M

Malcolm

jaso said:
If have a structure of a database record like this:
struct record {
char id[ID_LENGTH];
char title[TITLE_LENGTH];
...
};
Is there some way to find out how many member variables there is
in the struct and then iterate through them?
I want to have a function that takes the struct as argument and
then prompts the user for input for all the members. And instead
of coding the input for every member variable, I want the function
to automatically update each member. That will make it easier to
update the struct with more members.
The function also needs to know the length of every string in the
struct, so maybe I should add a length variable to each string
in the struct.

Is that feasible? Or can you recommend an other way?
No.
If we've got a database of employees, we can hardcode something like

struct employee
{
char name[64];
int serialnumber;
double salary;
};

Unfortunately in a real application we probably want the user to be able to
add and delete fields, without recompiling the program.

There is no easy way of achieving this. If you look at SQL you will see that
there are a limited number of atomic data types. You can write an SQL-type
server by defining a record signature string. Then you query the fields by
name and extract the values.

So we've got something like

"id: char[32]
title: varchar
... other members
"
In our record format descriptor

Then we have

struct record
{
int Nfields;
char **fieldname;
int *fieldtype;
int *fieldlength;
void **data;
};

for the general record, and we can build the structure from the record
descriptor
then we have an

int extractcharfield(struct record *rec, char *fieldname, char *out)

to access the data.

It is quite complicated to build from the ground up.
 
R

Richard Heathfield

[Gordon's been snipping attribs again, so I can't tell to whom he is
replying. Oh well.]

Gordon Burditt said:
If have a structure of a database record like this:
struct record {
char id[ID_LENGTH];
char title[TITLE_LENGTH];
...
};
Is there some way to find out how many member variables there is
in the struct and then iterate through them?

No.

Yes, if you have access to the source for the struct.
And iterating through variables of unknown type is of questionable
usefulness.

I can think of a few times when it would have been handy to be able to
iterate programmatically through the members of a struct, especially if one
had access to their names and types as well.

<snip>
 

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,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top