Отладка кода указателей на связанный список: ошибка сегментации - PullRequest
2 голосов
/ 24 апреля 2020

Итак, следующий код:

/*
 * For your reference:
 *
 * SinglyLinkedListNode {
 *     int data;
 *     SinglyLinkedListNode* next;
 * };
 *
 */
SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
  SinglyLinkedListNode* temp = head;
  while (temp != NULL) {
    temp = temp->next;
  }
  SinglyLinkedListNode* temp1;
  temp1->data = data;
  temp1->next = NULL;
  temp->next = temp1;
  return temp;
}

Итак, в основном я хочу добавить «данные» в конец связанного списка «заголовок» и вернуть обновленный список. Так в чем же ошибка?

Правка: Хорошо, я получил первую ошибку. Но даже если я заменим temp! = NULL на temp-> next! = NULL в условном выражении l oop, эта ошибка все еще есть

Ответы [ 3 ]

2 голосов
/ 24 апреля 2020

Вы должны выделить память для узла. Не забудьте очистить выделенную память. Для каждого звонка на new вам нужен звонок delete. Поэтому я предпочитаю умные указатели.

После того, как ваш l oop temp содержит NULL. Вы не можете разыменовать нулевой указатель.

SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
    SinglyLinkedListNode* temp1 = new SinglyLinkedListNode;
    temp1->data = data;
    temp1->next = nullptr;
    if (!head) {
        head = temp1;
        return head;
    }
    SinglyLinkedListNode* temp = head;
    while(temp->next){
        temp = temp->next;
    }
    temp->next = temp1;
    return temp;
}
1 голос
/ 24 апреля 2020

Эта функция

SinglyLinkedListNode* insertNodeAtTail(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* temp=head;
while(temp!=NULL){
    temp=temp->next;
}
SinglyLinkedListNode* temp1;
temp1->data=data;
temp1->next=NULL;
temp->next=temp1;
return temp;
}

не имеет смысла. После этого l oop

while(temp!=NULL){
    temp=temp->next;
}

указатель temp равен NULL. Таким образом, этот оператор

temp->next=temp1;

вызывает неопределенное поведение.

Указатель temp1 не был инициализирован. Итак, снова эти операторы

temp1->data=data;
temp1->next=NULL;

вызывают неопределенное поведение.

Пользователь функции не знает, является ли возвращаемый указатель указателем заголовка или последним указателем списка. Поэтому неясно, назначать ли возвращаемый указатель указателю на заголовок или просто игнорировать возвращаемое значение.

Функция может выглядеть следующим образом.

void insertNodeAtTail( SinglyLinkedListNode * &head, int data ) 
{
    SinglyLinkedListNode **current = &head;

    while ( *current != nullptr ) current = &( *current )->next;

    *current = new SinglyLinkedListNode { data, nullptr };
}

Если в main вы определили указатель на головной узел, такой как

SinglyLinkedListNode *head = nullptr;

, тогда вызов функции будет выглядеть как

insertNodeAtTail( head, some_data );

Другое определение функции может выглядеть следующим образом

SinglyLinkedListNode* insertNodeAtTail( SinglyLinkedListNode *head, int data ) 
{
    SinglyLinkedListNode *new_node = new SinglyLinkedListNode { data, nullptr };

    if ( head == nullptr )
    {
        head = new_node;
    }
    else
    {
        SinglyLinkedListNode *current = head;

        while ( current->next != nullptr ) current = current->next;

        current->next = new_node;
    }

    return head;
}

В этом случае, если в main вы определили указатель на головной узел как

SinglyLinkedListNode *head = nullptr;

, то вызов функции будет выглядеть как

head = insertNodeAtTail( head, some_data );

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

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

class SinglyLinkedList
{
private:
    struct Node
    {
        int data,
        Node *next;
    } *head = nullptr, *tail = nullptr;

public:

    SinglyLinkedList() = default;
    void insertNodeAtHead( int data );
    void insertNodeAtTail( int data );
    // other member functions;
};
0 голосов
/ 24 апреля 2020

Здесь также происходит сбой:

SinglyLinkedListNode* temp1;
temp1->data=data;

при достижении конца l oop while(temp!=NULL){, здесь temp равно NULL. ниже вы используете выражение вроде этого temp->next=temp1; это вызывает cra sh

...