о неправильном заказе товара
Ваша логика для slist_impl_insertl()
неверна.
давайте следовать вашему коду:
stringlist_t* slist_impl_insertl(stringlist_t* list, const char* str, unsigned int len)
{
stringlist_t* newnode;
if(list == NULL) // if the list is empty
{
newnode = slist_createl(str, len); // create a new item
list = newnode; // insert the new item at the start of the list
return list;
}
else // if the list is not empty
{
if(list->next == NULL) // if it contains only one item
{
list = slist_insertb(list, str, len); // insert a new item at the front of the list
return list;
}
else // if it contains more than one item
{
newnode = slist_createl(str, len); // create a new node
newnode->next = (struct stringlist_t*)list->next; // insert the new node just after the first item !?!.
list->next = (struct stringlist_t*)newnode;
return list;
}
}
return list; /* not reached */
}
Итак, ваша процедура вставки не всегда вставляет новый узел в одно и то же место. иногда его вставляют в начале, иногда вставляют на втором месте. это объясняет, почему предметы приведены в неправильном порядке.
тривиальное исправление - всегда вставлять новый узел в начало списка, тогда элементы будут возвращаться в обратном порядке. или вы можете перебирать список до конца (list->next == NULL
) и вставлять новый элемент после этого последнего элемента:
stringlist_t* slist_impl_insertl(stringlist_t* list, const char* str, unsigned int len)
{
stringlist_t *iter;
if(list == NULL)
{
list = slist_createl(str, len);
}
else
{
// find the last ist item
iter = list;
while(iter->next!=NULL)
iter = iter->next;
// insert the new item at the end of the list
iter->next = slist_createl(str,len);
}
return list;
}
об использовании макросов
если список пуст (list == NULL
), процедура вставки изменит список, чтобы сделать его первым элементом. макрос заботится о переназначении измененного списка. если вы не хотите использовать макросы, тогда вы должны передать аргумент списка в качестве указателя, чтобы вы могли изменить его непосредственно в процедуре вставки.
(парень, который написал код в первую очередь, сделал его таким образом, чтобы он мог вставить элемент в любое место в середине списка без необходимости писать специальные процедуры для этого)
вот вариант реализации slist_insert()
без использования макроса:
void slist_insert(stringlist_t** list, const char* str)
{
*list = slist_impl_insertl(*list, str);
}
используя эту реализацию, вы должны изменить способ вставки элементов в список:
slist_insert(&list, "red"); // note the use of '&'
об утечке памяти
процедура уничтожения освобождает строки, хранящиеся в каждом элементе, это нормально. но каждый элемент также распределяется динамически, поэтому его также нужно освобождать! Вы должны временно сохранить указатель списка, перейти к следующему элементу, а затем освободить сохраненный указатель, пока не достигнете конца списка.
void slist_destroy(stringlist_t* list)
{
stringlist_t *temp;
while(list != NULL)
{
// free the data contained in the current list item
free(list->data);
// save the pointer to the next item
temp = slist_next(list);
// free the current item
free(list);
// continue with the next item
list = temp;
}
}