2013-02-08 109 views
1

我一直在从Java过渡到学习C的课堂。目前的练习是为LinkedList实现removeAtFront(),searchNode()和freeList()方法。我从理论上理解这是如何工作的 - 我会尽快用Java完成它,我刚刚尝试了几个小时,但不明白为什么下面的代码不起作用。C链表searchNode/freeList方法(seg故障)

remove方法似乎能够工作,生成正确的修改列表,直到在删除节点后调用搜索方法。然后总是产生分段故障11。免费的方法也总是产生一个seg故障。

我不是要求人们做我的功课,但如果我能指出正确的方向,将非常感激!

给定节点*结构是:

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); 
} 

编辑:一个评论的固定我的问题与空闲列表

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

的main()这样写的之外的方法()方法,但其他人要求更多的代码。这个任务的问题是我只能修改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 2013-02-08 18:00:51

+1

另一个可疑的事情是'if(&(* head) - > next)'在哪里条件总是为真。可能是'if((* head) - > next)'是有意的。 – 2013-02-08 18:01:55

+0

@AntonKovalenko是的,我也相信它应该是'((* head) - > next)'。和'(&(* head) - > next)'是错误的 – 2013-02-08 18:21:02

回答

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 2013-02-08 18:05:26

+0

@netcoder是的,我通常使用'sizeof()'和'maloca'是拼写错误。现在更正了谢谢! – 2013-02-08 18:09:12

+1

@netcoder OP将问题定义为'C',所以我认为'new'不应该是可疑的。 – 2013-02-08 18:13:22

0

是的,正如在前面的答案中所指出的那样,虽然您已为节点分配内存,但您并未在每个节点中为单词分配内存。有时候它可能会工作,而不会导致段错误,那时你正在使用“某人的”内存,而你并没有声称这会导致内存位置被破坏。