2013-04-28 58 views
0

我的列表头始终指向尾部。有什么问题?我无法在C中正确创建双向链接列表

linked_list.h我:

#ifndef LINKED_LIST 
#define LINKED_LIST 

struct node 
{ 
    char *data; 
    struct node *nextElement; 
    struct node *prevElement; 
}; 

void createList(struct node **head, struct node **tail); 
void fill_list (char *word, struct node **head, struct node **tail); 

#endif 

main.c

#include <stdio.h> 
#include <stdlib.h> 
#include "linked_list.h" 
#include <string.h> 

int main() 
{ 
    FILE *dataFile; 
    char *word = (char *) calloc (255, sizeof(char)); 

/* Create empty list */ 
    struct node *head, *tail;  
    createList (&head, &tail); 
/*------------------------*/ 

/* Data file open*/ 
    dataFile = fopen("data.txt" ,"r"); 
    if(dataFile == NULL) 
    { 
     perror("Error while opening the file.\n"); 
     exit(EXIT_FAILURE); 
    } 

/* Data reading */ 
    while ((fscanf(dataFile, "%s", word)) != EOF) 
    { 
     int i   = 0; 
     int wordsCount = 0; 

     for (i = 0; i <= strlen(word); i++) 
     { 
     if ((word[i] >= 'a') && (word[i] <= 'z')) 
      wordsCount = wordsCount + 1; 
     } 

     if (wordsCount == strlen(word)) 
     { 
     fill_list (word, &head, &tail); 
     }  
    } 

    fclose(dataFile); 
    return 0; 
}; 

linked_list.c

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

void createList(struct node **head, struct node **tail) 
{ 
    *head = NULL; 
    *tail = NULL; 
} 

void fill_list (char *word,  struct node **head,  struct node **tail) 
{ 
    struct node *elem, *temp; 

    if ((*head) == NULL) 
    { 
    // printf("HEAD = NULL\n"); 

     elem = (struct node *) malloc (sizeof (struct node)); 
     elem -> data = word; 
     elem -> nextElement = NULL; 
     elem -> prevElement = NULL; 
     (*head) = elem; 
     *tail = elem; 
    // printf("%s\n", (*head) -> data );   
    } 
    else 
    { 
    // printf("HEAD != NULL\n"); 
     elem = (struct node *) malloc (sizeof (struct node)); 
     elem -> data = word; 
     elem -> nextElement = NULL; 
     elem -> prevElement = *tail; 
     *tail = elem; 
    // printf("%s\n", (*head) -> data );   
    } 
} 

我的数据文件:QW erty B CC。 首先,head == NULL,所以head -> data = 'qw'它应该始终保持领先,但它会变为erty,然后在每个循环步骤后变为b和cc。

我在做什么错了?

+0

你是不是要确保旧的最后一个元素指向新的最后一个元素,当你的元素添加到列表中。 – 2013-04-28 18:09:35

回答

3

问题是,您对所有输入使用相同的字符串,并将其用于所有节点。这意味着所有的节点将其data成员指向相同的字符串。这个字符串当然只包含你上次读入的内容。

您可能希望将main中的字符串缓冲区保存为普通数组(而不是将其分配到堆中)并使用strdup复制节点的字符串。不要忘记以后再解放他们。


指针正是这听起来像,这是一个变量,它在内存其他一些地方。你可以有许多指针指向同一个内存。

在您的情况下,您将功能main中的指针word传递给fill_list的所有调用。这意味着您在fill_list中创建的所有节点将使用完全相同的指针,并且它们都指向完全相同的内存。

这意味着,在列表中的所有节点都将有data成员似乎是相同的值,它总是会在main函数读入word最后一个字符串。

如果您使用的功能如strdup那么会重复这个字符串。即它会为该字符串分配全新的内存并从旧区域复制到新分配的区域,并返回一个指向新分配的内存的指针。

+0

你能详细解释一下吗? 我不明白你的意思。 – Pauliuks 2013-04-28 18:21:59

+0

@Pauliuks详细阐述了一下。 – 2013-04-28 18:37:00

+0

好吧,现在主要的问题是如何使用strdup。 我应该在哪里以及如何使用它?对于愚蠢的问题抱歉,但也许它不需要很多时间给你。 – Pauliuks 2013-04-28 18:59:58

1

试试这个

void fill_list (char *word,  struct node **head,  struct node **tail) 
    { 
     struct node *elem, *temp; 

     /* you need to create node first ! */ 
     elem = (struct node *) malloc (sizeof (struct node)); 
     elem -> data = NULL ; 
     elem -> data = (char*) malloc(sizeof(char)*255)); 
     if (elem -> data == NULL) 
      { 
      perror("alloc data failed "); 

      } 

     if ((*head) == NULL) 
     { 
     // printf("HEAD = NULL\n"); 
    /* call memcpy() function need to #include <string.h> */ 

      elem -> data = memcpy((void*)elem -> data,(void*)word,strlen(word)); 
      elem -> nextElement = NULL; 
      elem -> prevElement = NULL; 
      (*head) = elem; 
      *tail = elem; 
     // printf("%s\n", (*head) -> data );   
     } 
     else 
     { 
     // printf("HEAD != NULL\n"); 

      elem -> data = memcpy((void*)elem -> data,(void*)word,strlen(word)); 
      elem -> nextElement = NULL; 
      elem -> prevElement = *tail; 
      *tail = elem; 
     // printf("%s\n", (*head) -> data );   
     } 
+0

程序崩溃后: /*为每个节点分配*/ elem - > data =(char *)malloc(sizeof(char)* 255); – Pauliuks 2013-04-28 18:40:34