2013-02-08 2 views
1

Я делаю переход от Java к обучению C для класса. Текущее упражнение - реализовать методы removeAtFront(), searchNode() и freeList() для LinkedList. Я понимаю теоретически, как это работает - я бы быстро это сделал на Java, я просто пытался часами и не понимаю, почему приведенный ниже код не работает.C связанный список searchNode/freeList методы (seg fault)

Метод удаления работает, создавая правильный измененный список, пока метод поиска не будет вызван ПОСЛЕ удаления узла. Затем генерируется раздельная ошибка 11. Свободный метод также всегда вызывает ошибку seg.

Я не прошу людей делать домашнее задание, но если бы я мог быть направлен в правильном направлении, это было бы очень признательно!

Данный узел * структура является:

typedef struct Node 
{ 
    char *word; 
    struct Node *next; 
} Node; 

Методы снаружи от основной() читать, как это:

void insertAtFront(Node **head, char * key) 
{ 
    Node *new = malloc(sizeof(Node)); 
    if (!new) fatal("Malloc of new Node failed"); 
    new->word = key; 
    new->next = *head; 
    *head = new; 
} 

void insertAtTail(Node **head, char * word) 
{ 
    if (!(*head)) insertAtFront(head, word);  
    else insertAtTail(&(*head)->next, word); 
} 

void removeAtFront(Node ** head) 
{ 
    Node *tmp = *head; 
    if (!tmp) return; 

    *head = tmp->next; 
    free(tmp->word); 
    free (tmp); 
} 

void removeNode(Node ** head, char * key) 
{ 
    Node *tmp = searchNode(*head, key); 
    if (tmp) removeAtFront (&tmp); 
} 

Node * searchNode (Node * head, char * key) 
{ 
    if (!head || (strcmp(head->word, key) == 0)) return head; 
    return searchNode(head->next, key); 
} 

void freeList( Node ** head) 
{ 
    if (!head) return; 
if (&(*head)->next) freeList (&(*head)->next); 
    removeAtFront(head); 
} 

EDIT: Один из комментариев фиксированной моей проблемы с FreeList(), но другие запросили больше кода. Проблема с этим назначением заключается в том, что мне разрешено изменять методы insertAtTail(), removeAtFront(), remove(), search() и freeList(). Однако я опубликую основной метод. Я думаю, что значения слова правильно распределены внутри этого.

Node *searchNode(Node * head, char * key); 
void insertAtFront(Node **head, char * key); // ALREADY WRITTEN FOR YOU 
void insertAtTail(Node **head, char * key); 
void removeAtFront(Node ** head); 
void removeNode(Node **head, char * key); 
void freeList(Node **head); 
void printList(Node * head); // ALREADY WRITTEN FOR YOU 
void fatal(char * msg); // ALREADY WRITTEN FOR YOU 

#define BUFFER_CAP 20 

int main() 
{ 
    Node *head = NULL; 

    while (1) 
    { 
    char option; 
    printf("\nChoose 'H'ead Insert, 'T'ail insert, 'R'emove, 'S'earch, F'ree,  'Q'uit "); 
    fflush(stdout); 
    int result = scanf(" %c%*[^\n]", &option); getchar(); // MAGIC BULLET TO CORRECTLY READ A SINGLE CHAR FROM STDIN 
    if (result <1) fatal("failure reading from stdin\n"); 

    if (option == 'H') 
    { 
     char * word=malloc(BUFFER_CAP); // DONT ENTER ANY LONG WORDS! 
     printf("Enter a word to insertAtFront: "); 
     fflush(stdout); 
     char * result = fgets(word, BUFFER_CAP, stdin); 
     if (result==NULL) fatal("failure reading from stdin\n"); 
     strtok(word,"\n"); // overwrites '\n' with '\0' 
     insertAtFront(&head, word); /* shallow copy string into list */ 
     printList(head); 
    } 
    if (option == 'T') 
    { 
     char * word=malloc(BUFFER_CAP); // DONT ENTER ANY LONG WORDS! 
     printf("Enter a word to insertAtTail: "); 
     fflush(stdout); 
     char * result = fgets(word, BUFFER_CAP, stdin); 
     if (result==NULL) fatal("failure reading from stdin\n"); 
     strtok(word,"\n"); // overwrites '\n' with '\0' 
     insertAtTail(&head, word); /* shallow copy string into list */ 
     printList(head); 
    } 
     if (option == 'R') 
    { 
     char * word=malloc(BUFFER_CAP); // DONT ENTER ANY LONG WORDS! 
     printf("Enter a word to remove: "); 
     fflush(stdout); 
     char * result = fgets(word, BUFFER_CAP, stdin); 
     if (result==NULL) fatal("failure reading from stdin\n"); 
     strtok(word,"\n"); // overwrites '\n' with '\0' 
     removeNode(&head, word); 
     printList(head); 
     free(word); // we were just using it for matching 
    } 
    if (option == 'S') 
    { 
     char * word=malloc(BUFFER_CAP); // DONT ENTER ANY LONG WORDS! 
     printf("Enter a word to find: "); 
     fflush(stdout); 
     char * result = fgets(word, BUFFER_CAP, stdin); 
     if (result==NULL) fatal("failure reading from stdin\n"); 
     strtok(word,"\n"); // overwrites '\n' with '\0' 
     if (searchNode(head, word)) 
      fprintf(stderr, "%s FOUND\n",word); 
     else 
      fprintf(stderr, "%s NOT FOUND\n",word); 
     printList(head); 
     free(word); // we were just using it for matching 
    } 
    if (option == 'F') // free the entire list (remember to set head to NULL) 
    { 
     freeList(&head); 
     printList(head); 
    } 
    else if (option == 'Q') 
     exit(0); 
} // END WHILE 

return 0; 
} 
+0

Как отметили пару плакатов, у вас могут быть проблемы с распределением и освобождением Node :: word. Кто владеет этой памятью после создания узла? Кроме того, мне интересно об использовании. Можете ли вы показать нам тестовый код, который рушится? – SirPentor

+1

Другая подозрительная вещь: 'if (& (head) -> next)' где условие всегда верно. Вероятно, 'if ((* head) -> next)' предназначалось. –

+0

@ Антон Коваленко Да, я также считаю, что это должно быть '((* head) -> next)'. и '(& (* head) -> next)' is wrong –

ответ

2

при распределении памяти для узла с помощью Node *new = malloc(sizeof(Node));, вы выделение памяти для указателя, но не для данных. вы приехали делать выделение памяти для полукокса также как: (его просто идея)

new->word= malloc(sizeof(char)*(strlen(key) + 1)); 
strcpy(new->word, key) 

Другого мудрым вы должны быть использовать, что вы выделить память для key динамически. (, потому что вы делаете free(tmp->word);)

Я думаю, вам стоит добавить еще код. Как вы проходите key?

+0

Вам не нужно 'sizeof (char)'. 'new' как имя переменной сомнительно. А что такое 'maloca'? – netcoder

+0

@netcoder Да, я обычно использую 'sizeof()' и 'maloca' была ошибкой typo. теперь исправлено спасибо! –

+1

@netcoder OP поставил вопрос как 'C', поэтому я думаю, что' new' не должно быть сомнительным. –

0

Да, как указано в более раннем ответе, вы не выделяете память для слова в каждом узле, хотя вы выделили память для узла. Иногда это может сработать, не вызывая segfault, в то время вы используете «чьё-то» память, которое вы не утверждали, вызывая повреждение этих мест памяти.