#c #data-structures #linked-list #append #doubly-linked-list
Вопрос:
Моя реализация двусвязного списка заключается в следующем: каждый узел содержит массив из четырех значений
#define EMPTYNODE 0
struct node {
short data[4]; // pay attention
struct node* next;
struct node* prev;
};
typedef struct node nodeQ_t;
typedef enum{
LIST_FALSE = 0,
LIST_TRUE = 1,
} status_t;
nodeQ_t* createNode(short values[4]){
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));
for(int i=0; i < 4; i ){
node->data[i] = values[i];
}
node->next = EMPTYNODE;
node->prev = EMPTYNODE;
return node;
}
теперь я пытаюсь написать функцию добавления таким образом, чтобы я предоставил ей заголовок и узел, созданный в функции createNode, чтобы она добавила его в список…. но это создает ошибку сегментации…
status_t appendNode(nodeQ_t* head, nodeQ_t* newNode){
if(head == EMPTYNODE || newNode == EMPTYNODE){
return LIST_FALSE;
};
nodeQ_t* currentNode = head;
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
}
currentNode = currentNode->next;
}
return LIST_TRUE;
}
пожалуйста, дайте мне знать, в чем причина этого…
для вашей справки моя основная функция заключается в
int main(){
short array[4] = {1,2,3,4};
nodeQ_t* head = createNode(array);
printList(head);
short array2[4] = {5,6,7,8};
nodeQ_t* newNode = createNode(array2);
appendNode(head, newNode);
printList(head);
return 0;
}
если вам нужна какая-либо дополнительная информация или объяснение чего-либо, пожалуйста, дайте мне знать
Комментарии:
1.
break
выйдите изwhile
цикла, как только вставка завершится успешно.2. Я думаю, что ваша проблема здесь:
(nodeQ_t*)malloc(sizeof(node))
. Так и должно бытьsizeof(*node)
.node
это указатель, поэтому вы выделяете байты для размера указателя, а не для размера структурыnode
, на которую указывает.3. @500-InternalServerError: Я не говорю, что возврат из
malloc
не является указателем. Я говорюsizeof(node)
о выделении всего 4 или 8 байтов (независимо от размера указателя), когда правильнее всего выделить*node
байты, размер структуры. Смотрите ответ @Johnny Mopp ниже.4. @sj95126: Извините, неоднозначное использование идентификатора
node
здесь.
Ответ №1:
Как упоминалось в комментариях, вам нужно break
выйти из цикла, как только вы дойдете до конца:
while(currentNode != EMPTYNODE) {
if (currentNode->next == EMPTYNODE) {
currentNode->next = newNode;
newNode->prev = currentNode;
// need a break here
}
currentNode = currentNode->next;
// When at the end of the list the 1st time through,
// currentNode is the newly created node because you have
// currentNode->next = newNode
// then
// currentNode = currentNode->next
// On the next iteration, the new node next ends up getting pointed to itself
// since on that iteration newNode and currentNode are the same.
// and you end up with an infinite loop.
}
Другой вариант-зациклиться на currentNode->next
:
while (currentNode->next) {
currentNode = currentNode->next;
}
currentNode->next = newNode;
newNode->prev = currentNode;
Я должен отметить, что это работает, потому что вы ранее гарантировали, что currentNode
это не NULL
так .
Кроме того, ваше распределение здесь неверно:
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));
Потому node
что это указатель и sizeof(node)
размер указателя, а не размер struct node
. Должно быть
nodeQ_t* node = (nodeQ_t*)malloc(sizeof(*node));
Ответ №2:
Вы попадаете в бесконечный цикл:
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
}
currentNode
всегда будет отличаться от EMPTYNODE
.
Добавить разрыв или возврат после добавления нового элемента:
while(currentNode != EMPTYNODE){
if(currentNode->next == EMPTYNODE){ //it means that current node is tail
currentNode->next = newNode; //segmenttion fault arises at exactly this line
newNode->prev = currentNode;
return LIST_TRUE;
}