jaso wrote:
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[i].name, &entries[i],
desc[i].length, desc[i].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?