Как инициализировать структуру в указанную структуру - PullRequest
0 голосов
/ 15 мая 2018

Намаст! Я хочу инициализировать мою позицию массива структуры 0 myList.items [0] с указателем на мою структуру элемента, но он выводит неровность на соответствующие позиции, когда я распечатываю ее из своей функции печати. Он изменяет то, что было предварительно инициализировано (для тестирования), поэтому я знаю, что оно работает частично, но что вызывает плохой вывод и что следует изменить?

До:

---- Мой список покупок ---------

1 - Шоколад 40 100 г

2 - Рыбный соус 9 л

После того, как:

---- Список покупок ---------

1 - c┴®¶²` 128565603 ■ lüIv

2 - Рыбный соус 9 л

typedef struct{
        char name[20];
        int amount;
        char amountType[10];
}item;

typedef struct{
        item *items[5];
        int length;
}list;

int addItemToList(list *myList);

main(void)
{
    list myList;
    myList.length = 0;
    for(int i; i<5;i++)
    {
        myList.items[i] = NULL;
    }
    addItemToList(&myList);
    return 0;
}


int addItemToList(list *myList)
{
    item newItem = {"Potatoes",2, "kg"};
    myList->items[myList->length]=&newItem; //Something wrong here?
    myList->length++;
    printf ("Added [%s %i %s] as #%i.", newItem.name, newItem.amount,newItem.amountType, myList->length);
return 0;
}

Ответы [ 3 ]

0 голосов
/ 15 мая 2018

Это:

int addItemToList(list *myList)
{
    item newItem = {"Potatoes",2, "kg"};

Это размещает newItem в стеке. Это означает, что память для него уйдет, когда addItemToList будет завершен, поэтому & newItem будет указывать на тарабарщину позже. Это будет нормально, пока еще выполняется код в addItemToList, но затем содержимое памяти будет заменено во всех последующих вызываемых функциях.

Вы можете либо использовать malloc для выделения некоторой памяти для newItem, либо вы можете выделить newItem в стеке вашей главной функции и передать указатель на newItem для любых других вызванных функций.

0 голосов
/ 15 мая 2018

Вы смешиваете стек и кучу памяти, я переписал это для вас, это должно дать вам некоторое представление о том, что пошло не так. Также всегда свободная выделенная память - это не Java:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
        char name[20];
        int amount;
        char amountType[10];
}item;

typedef struct{
        item *items[5];
        int length;
}list;

int addItemToList(list *myList);

int main(void)
{
    list myList;
    myList.length = 0;
    for(int i; i<5;i++)
    {
        myList.items[i] = 0;
    }

    addItemToList(&myList);

    for(int i; i<myList.length; i++)
    {
        free(myList.items[i]);
    }

    return 0;
}


int addItemToList(list *myList)
{
    item* newItem = malloc(sizeof(item));
    strcpy(newItem->name, "Potatoes");
    newItem->amount = 2;
    strcpy(newItem->amountType, "kg");
    myList->items[myList->length++] = newItem; //Something wrong here?
    printf ("Added [%s %i %s] as #%i.\n", newItem->name, newItem->amount, newItem->amountType, myList->length);
    return 0;
}
0 голосов
/ 15 мая 2018

Вы не можете инициализировать структуру в стеке, а затем передать указатель на эту структуру в другую структуру, которая живет дольше, чем открыт этот кадр стека. Как только функция вернется, кадр стека, в котором был выделен ваш item, закроется, и назначенные значения для полей исчезнут.

Вам нужна функция инициализатора с выделенной структурой кучи:

item* item_new(const char* name, int amount, const char* amountType);

Тогда ваша функция инициализации должна:

  1. вызовите Malloc для размера структуры,
  2. Скопируйте строки name и amountType в структуру.
  3. скопировать amount в структуру.

Затем вы можете сделать это: myList->items[myList->length]=newItem;, где newItem создается вашей функцией инициализации.

...