Массив структур не добавляется - PullRequest
0 голосов
/ 15 марта 2020

Эй, мы начали использовать C в университете в месяц go, и теперь у нас есть назначение, и нам нужно использовать динамическое распределение c для массива структур. Это мой код для создания репо: '' '

Repo* init() {
    Repo* repo = malloc(sizeof(Repo));
    repo->items = malloc(sizeof(Item) * 1);
    repo->allocatedSlots = 1;
    repo->numberOfItems = 0;
    return repo;
}

typedef struct {
    Item *items;
    int numberOfItems;// the index of the last item
    int allocatedSlots;
}Repo;

' ''. Вот те функции, которые я тестирую и получаю подтверждение: '' '

int grow(Repo* repo) {
    assert(repo != NULL);
    assert(repo->items != NULL);
    Item* new_repo = malloc((2 * repo->allocatedSlots)*sizeof(Item));
    if (new_repo == NULL)
        return 0; //allocation fail!
    memcpy(new_repo, repo->items, sizeof(Repo) * repo->numberOfItems);
    free(repo->items);
    repo->items = new_repo;
    repo->allocatedSlots *= 2;
    free(new_repo);
    return 1; //success
}

int addItem(Repo* repo, Item item) {
    for (int index = 0; index < repo->numberOfItems; index++)
        if (repo->items[index].ID == item.ID)
            return 0;// item already exists
    //printf("%d %d", item.ID, item.value);
    if (repo->numberOfItems < repo->allocatedSlots) {
        char* type = (char*)malloc(strlen(item.type)*sizeof(char)), *state = (char*)malloc(strlen(item.state) * sizeof(char));
        strcpy(type, item.type);
        strcpy(state, item.state);
        //repo->items[repo->numberOfItems + 1] = &item;
        repo->items[repo->numberOfItems + 1].ID = (int)item.ID;
        //printf("JSJSJSJS  %d", repo->items[repo->numberOfItems + 1].ID);
        repo->items[repo->numberOfItems + 1].value = item.value;
        strcpy(repo->items[repo->numberOfItems + 1].state, state);
        strcpy(repo->items[repo->numberOfItems + 1].type, type);
        repo->numberOfItems++;
    }
    else {
        grow(repo);
        repo->items[repo->numberOfItems + 1].ID = item.ID;
        repo->items[repo->numberOfItems + 1].value = item.value;
        strcpy(repo->items[repo->numberOfItems + 1].state, item.state);
        strcpy(repo->items[repo->numberOfItems + 1].type, item.type);
        repo->numberOfItems++;
    }
    return 1;//adding successfull!
}

void AddItem_ValidInput_AddedToList() {
    Repo* repo = init();

    Item item ;
    int id = 1, value = 100;
    char* state = "New";
    char* type = "Uglyo";
    item = createItem(id, value, state, type);
    addItem(repo, item);
    //printf("sdfsdfsdfs");
    //printf('%d\n', repo->items[0].ID);
    assert(repo->items[0].ID == item.ID);
    //printf('%d', item->ID);
    destroy(repo);

}

'' 'Последний тест - это тест, который я делаю первым.

1 Ответ

0 голосов
/ 15 марта 2020

Скорее всего, проблема здесь:

char* type = (char*)malloc(strlen(item.type)*sizeof(char)), *state = (char*)malloc(strlen(item.state) * sizeof(char));
strcpy(type, item.type);
strcpy(state, item.state);

Здесь вы забыли, что char строки в C действительно называются завершенными нулями байтовыми строками . строка в C - это последовательность символов, оканчивающаяся на ноль. Этот ноль равен , а не , считаемому strlen, но для него все еще требуется выделенное пространство.

Вам необходимо выделить strlen(...) + 1 байт для строк:

char* type = malloc(strlen(item.type) + 1);
char* state = malloc(strlen(item.state) + 1);
strcpy(type, item.type);
strcpy(state, item.state);

Или если ваша система имеет функцию strdup (очень вероятно)

char* type = strdup(item.type);
char* state = strdup(item.state);

У вас также есть очень серьезные проблемы с вашей функцией grow:

Item* new_repo = malloc((2 * repo->allocatedSlots)*sizeof(Item));
repo->items = new_repo;
free(new_repo);

Сначала вы выделяете память и new_repo указывает на эту память.

Затем вы repo->items указываете на ту же память . Теперь у вас есть два указателя, указывающие на одну и ту же память.

Затем вы освобождаете эту память, делая оба указателя new_repo и repo->items недействительными.

Вы не должны free(new_repo).

или использовать, например, realloc вместо этого (как я уже предложил в комментарии):

int grow(Repo* repo) {
    Item* new_repo = realloc(repo->items, 2 * repo->allocatedSlots * sizeof(Item));
    if (new_repo == NULL)
        return 0;  // Failure to allocate

    repo->items = new_repo;
    repo->allocatedSlots *= 2;
    return 1;
}
...