我无法在C中正确创建双向链表

时间:2013-04-28 18:05:32

标签: 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。

我做错了什么?

2 个答案:

答案 0 :(得分:3)

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

您可能希望将字符串缓冲区保留在main中作为普通数组(而不是在堆上分配它)并使用例如strdup复制节点的字符串。不要忘记稍后释放它们。


指针正是它听起来的样子,它是指向到内存中某个其他位置的变量。你可以有许多指针都指向同一个内存。

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

这意味着列表中的所有节点都会使data成员的值相同,并且它始终是word函数中读入main的最后一个字符串。

如果您使用strdup之类的功能,它将复制字符串。即它将为字符串分配全新的内存,并从旧区域复制到新分配的区域,并返回指向新分配的内存的指针。

答案 1 :(得分: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  );         
        }