argamanza
argamanza

Reputation: 1142

Trying to create an array of Struct and load data from file

I have this struct i created called User which stores all kind of data, now i'm trying to create an array of it (User*) and get data from a file, this is what i do in the start of my main program:

int amount = 0;
User* users = NULL;

// read from file functions
loadUsers(&users,&amount);

And the function (the amount of users is the first line of my txt file):

void loadUsers(User** users,int* amount2){
    int amount, i = 0, j;
    char temp[STRING_SIZE], temp2[STRING_SIZE];
    FILE* f;

    f = fopen("input.txt", "r");

    if (!f){
        return;
    }

    if (fileEmpty(f)){
        return;
    }

    fscanf(f, "%d", &amount);
    *amount2 = amount;

    *users = malloc(sizeof(User)*amount);
    /**users = (User*)malloc(sizeof(User)*amount);*/

    while (!feof(f)){
        fscanf(f, "%s", temp);
        users[i]->ID = (char*)malloc(sizeof(char)*(strlen(temp) + 1));
        strcpy(users[i]->ID, temp);
        fscanf(f, "%s", temp);
        users[i]->f_name = (char*)malloc(sizeof(char)*(strlen(temp) + 1));
        strcpy(users[i]->f_name, temp);
        fscanf(f, "%s", temp);
        users[i]->l_name = (char*)malloc(sizeof(char)*(strlen(temp) + 1));
        strcpy(users[i]->l_name, temp);

        i++;
    }

For some reason i get an error and while debugging i see the allocation is wrong since i only have users[0] and not users[1], like an array of users should have, even when the amount is higher than 1.

My target is to have an array, which each cell of it is a User.

What could be the reason?

Edit: User struct:

struct User{
    char* ID;
    char* f_name;
    char* l_name;
    int age;
    char gender;
    char* username;
    char* password;
    char* description;
    char** hobbies;
}typedef User;

Upvotes: 0

Views: 70

Answers (2)

Weather Vane
Weather Vane

Reputation: 34583

Syntax error over the double pointer. Instead of this:

users[i]->ID = (char*)malloc(sizeof(char)*(strlen(temp) + 1));
strcpy(users[i]->ID, temp);

Try this:

(*users)[i].ID = malloc(strlen(temp) + 1);
strcpy ((*users)[i].ID, temp);

And so on for the other fields.

Upvotes: 0

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53036

You might be invoking undefined behavior because you don't check for i < amount in the while loop, you also don't check for fscanf() to see if it did succesfully read the data, if it fails, tha contents of the temp array would be uninitialized and trying to copy them to the malloced poitners is Undefined Behavior too.

So your problem is basically that your program is blindly assuming that everything is working as expected and potentially invoking Undefined Behavior, that mistake is very commong among new programmers.

You are allocating space for amount structs of User and yet you try to initialize amount pointers of User in the for loop, you should dereference the double pointer for it to work properly.

This is your own code with some checks that will prevent undefined behavior

void loadUsers(User** userlist, int* amount2)
{
    int  amount, i = 0;
    char id[100];
    char fname[100];
    char lname[100];
    FILE *file;
    User *users;

    file = fopen("input.txt", "r");

    if (!file) {
        return;
    }

    if (fileEmpty(file)) {
        fclose(file);
        return;
    }
    if (fscanf(file, "%d", &amount) != 1)
    {
        fclose(file);
        return;
    }

    *amount2  = amount;
    *userlist = malloc(sizeof(User) * amount);
    if (*userlist == NULL)
        return; /* malloc can fail, check that */

    /* point to the destination pointer to prevent the need of (*users)[i] */
    users = *userlist;
    /* if fscanf() returns 3 it means that all the arguments where read */
    while ((i < amount) && (fscanf(file, "%99s%99s%99s", id, fname, lname) == 3)) {
        size_t length;

        length      = strlen(id);
        users[i].ID = malloc(length + 1); /* sizeof(char) == 1 */
        if (users[i].ID != NULL)
            strcpy(users[i].ID, id);

        length          = strlen(fname);
        users[i].f_name = malloc(length + 1); /* sizeof(char) == 1 */
        if (users[i].f_name != NULL)
            strcpy(users[i].f_name, fname);

        length          = strlen(lname);
        users[i].l_name = malloc(length + 1); /* sizeof(char) == 1 */
        if (users[i].l_name != NULL)
            strcpy(users[i].l_name, lname);

        i++;
    }
    fclose(file);
}

Upvotes: 2

Related Questions