1

Say the structure for the file I want to read looks like this:

typedef struct {
    char length;
    char* text;
} name;
typedef struct {
    long n_names;
    name* names;
} file;

In the file there is first the number of names, followed by the list of names with dynamic lengths. So I need to allocate memory for the names array, but before I can do that I first need to know the lengths of all the names.

How can I work this out?

5 Answers 5

2

1) You could use a dynamically growing data structure (e.g., a list) and add the names you find on the go. If for some reason you don't want that, you could 2) Run through the whole file twice and determine the respective size on the first run, thereafter allocate memory you need, and finally get strings out.

Note that in the example above, though, sizeof(struct name) is fixed as text is only a pointer to some other location.

Sign up to request clarification or add additional context in comments.

Comments

1

Once you've read the number of names (n_names), you can malloc enough memory to hold the structures (e.g. my_file.names = malloc(sizeof(*my_file.names) * my_file.n_names);).

You can then iterate through your file, malloc-ing memory for each string in turn, along the lines of:

for (i = 0; i < my_file.n_names; i++)
{
    int len;
    fread(&len, sizeof(len), 1, fid);
    my_file.names[i].text = malloc(len+1);
    ...
}

5 Comments

Thanks, that works. But I don't really understand why it works? What exactly does sizeof(*my_file.names) mean?
If my_file is of type struct {} file, then my_file.names is of type struct {} name. sizeof(*my_file.names) then returns the size of the dereferenced names member which is sizeof(struct {} name).
Ok but how can you know the size of my_file.names because the struct {} name has a text variable with dynamic size. Shouldn't there first be allocated memory for all the text variables before calling sizeof(*my_file.names)?
@Midas: No, because name has a fixed size (it is given by sizeof(name), which is a constant). It has a pointer, which will the address of some dynamically-allocated piece of memory. You can allocate the memory for each object one-at-a-time.
Thanks. Now I also understand why I often see a data type specified for malloc, e.g. char* var = (char*) malloc(n).
1

It would be just like when counting the size of a string in memory manually. You iterate until you reach null terminator which will tell you that you reached the end of the name. And then you do this until you have reached EOF.

Comments

1

If you have memory to spare, just allocate the file's size; otherwise process the file twice: first for summing up the lengthes (?), then reading the names.

Comments

0
void readname(struct name* name,FILE* f)
    {
    fread(&name->length,1,1,f);
    name->text = malloc(name->length);
    fread(name->text,name->length,1,f);
    }

readfile is similar, but the second fread(...); becomes for(...) readname(...);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.