Не могу понять, почему я получаю ошибку сегментации, когда пытаюсь добавить в конец связанного списка - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь попрактиковаться и освоиться со связанными списками, поэтому я сделал эту программу, чтобы попытаться создать узлы и добавить их в конец связанного списка по мере поступления данных.

Все работает до попадает в функцию add_node(). Я переделывал его миллион раз и не могу понять, где что-то не так. Компилируется нормально, но выдает ошибку сегментации.

Вот программа:

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

struct node
{
  char *card;
  struct node *next;
};
typedef struct node node_t;

//print
void printlist(node_t *head)
{
  node_t *temp = head;

  while (temp != NULL)
  {
    printf("%s\n", temp->card);
    temp = temp->next;
  }
}



node_t *create_new_node(char *card)
{
  node_t *result = malloc(sizeof(node_t));
  result->card = card;
  result->next = NULL;

  return result;
}

node_t *insert_at_head(node_t **head, node_t *node_to_insert)
{
  // have node_to_insert point to the head
  node_to_insert->next = *head;
  // now have the head point to the node_to_insert
  *head = node_to_insert; // having this pointer requires the **head parameter
  return node_to_insert;
}

// add new node at the end of the list
void add_node(node_t *head, node_t *new_node)
{
    node_t *tmp = head;

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



int main(void)
{
  char *card_list[5] = {"counterspell", "black lotus", "giant growth", "mountain", "forest"};
  int len = sizeof(card_list)/sizeof(card_list[0]);

  node_t *head = NULL;
  node_t *temporary;


  for (int i = 0; i < len; i++)
  {
    temporary = create_new_node(card_list[i]);
    if ( i == 0)
    {
      head = insert_at_head(&head, temporary);
    }
    else
    {
      add_node(head, temporary);
    }
  }

  printlist(head);

  return 0;
}

1 Ответ

1 голос
/ 07 мая 2020

Используемый вами подход неверен.

В список следует добавлять данные, а не указатели на узлы.

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

node_t * create_new_node( char *card )
{
    node_t *result = malloc( sizeof( node_t ) );

    if ( result != NULL )
    {
        result->card = card;
        result->next = NULL;
    }

    return result;
}

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

int insert_at_head( node_t **head, char *card )
{
    node_t *node_to_insert = create_new_node( card );
    int success = node_to_insert != NULL;

    if ( success )
    {
        node_to_insert->next = *head;
        *head = node_to_insert;
    }

    return success;
}

// add new node at the end of the list
int add_node( node_t **head, char *card )
{
    while ( *head != NULL )
    {
        head = &( *head )->next;
    }

    *head = create_new_node( card );

    return *head != NULL;
}

И в основном вы можете написать

char *card_list[] = 
{
    "counterspell", "black lotus", "giant growth", "mountain", "forest"
};
size_t len = sizeof( card_list ) / sizeof( card_list[0] );

node_t *head = NULL;

for ( size_t i = 0; i < len; i++ )
{
    add_node( &head, card_list[i] );
}

Обратите внимание на то, что в целом вы должны делать копию переданной строки в каждом узле.

...