У меня есть созданная мной структура под названием User, в которой хранятся все виды данных, теперь я пытаюсь создать массив (User *) и получить данные из файла, вот что я делаю в начале своей основной программы:

int amount = 0;
User* users = NULL;

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

И функция (количество пользователей - первая строка моего txt файла):

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++;
    }

По какой-то причине я получаю сообщение об ошибке, и во время отладки я вижу, что распределение неверно, поскольку у меня есть только users[0], а не users[1], как должно быть у массива пользователей, даже если сумма больше 1.

Моя цель - иметь массив, каждая ячейка которого является пользователем.

Что может быть причиной?

Изменить: структура пользователя:

struct User{
    char* ID;
    char* f_name;
    char* l_name;
    int age;
    char gender;
    char* username;
    char* password;
    char* description;
    char** hobbies;
}typedef User;
0
argamanza 27 Янв 2015 в 19:40

2 ответа

Лучший ответ

Возможно, вы вызываете неопределенное поведение, потому что вы не проверяете i < amount в цикле while, вы также не проверяете fscanf(), чтобы узнать, успешно ли он прочитал данные, если это не удается, то содержимое массива temp будет неинициализированным, и попытка скопировать его в редакторы malloc также является неопределенным поведением.

Итак, ваша проблема в основном в том, что ваша программа слепо предполагает, что все работает, как ожидалось, и потенциально вызывает неопределенное поведение, эта ошибка очень распространена среди новых программистов.

Вы выделяете место для amount структур User и все же пытаетесь инициализировать amount указатели User в цикле for, вам следует разыменовать двойной указатель, чтобы он работал правильно.

Это ваш собственный код с некоторыми проверками, которые предотвратят неопределенное поведение

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);
}
2
Iharob Al Asimi 27 Янв 2015 в 17:44

Синтаксическая ошибка двойного указателя. Вместо этого:

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

Попробуй это:

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

И так далее для других полей.

0
Weather Vane 27 Янв 2015 в 18:04