链接列表 - 以前节点中的数据被覆盖

时间:2017-09-10 19:28:50

标签: c data-structures linked-list

我有一个程序将目录放在链表中并打印出来。链表被搞砸了具有相同数据的所有节点。例如,我有一个文件夹"测试'它有3个子文件夹" Good One"," Jump"," Sunday"。输出是 - >周日周日周日。

在调试时,插入函数的第一次迭代,第一个节点中的变量数据被设置为" Good One"。根节点指针的地址被传递回main。 最初,startptr-> data =" Good One"。执行readdir后,dir-> d_name是" Jump"。但是startptr->数据变为" Jump"。同样的情况发生在第3天和周日#34;并且列表中的所有节点都有data =" Sunday"。

不确定为什么会这样。感谢任何帮助。 这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>

/* self-referential structure */
struct listNode {
    char *data; /* each listNode contains a character */
    struct listNode *nextPtr; /* pointer to next node */
}; /* end structure listNode */

typedef struct listNode ListNode; /* synonym for struct listNode */
typedef ListNode *ListNodePtr; /* synonym for ListNode* */

/* prototypes */
void insert( ListNodePtr *sPtr, char *value );
void printList( ListNodePtr currentPtr );

int main( void )
{
    ListNodePtr startPtr = NULL; /* initially there are no nodes */

    DIR *d = NULL;
    struct dirent *dir = NULL;

    d = opendir ("/Users/Satish/Documents/Test");
    if (d != NULL)
    {
        while ((dir = readdir (d)) != NULL)
        {
            /*printf("%s\n", dir->d_name);*/
            if ( (strcmp(dir->d_name, ".")  == 0) || (strcmp(dir->d_name, "..")  == 0) ) 
            {
            }
            else
                insert( &startPtr, dir->d_name ); /* insert item in list */
        }
        closedir (d);
    }
    else
        printf("%s/n", "Couldn't open the directory");

    printList( startPtr );
    printf( "End of run.\n" );
    return 0; /* indicates successful termination */
} /* end main */

/* Insert a new value into the list in sorted order */
void insert( ListNodePtr *sPtr, char *value )
{
    ListNodePtr newPtr = NULL; /* pointer to new node */
    ListNodePtr previousPtr = NULL; /*pointer to previous node in list */
    ListNodePtr currentPtr = NULL; /* pointer to current node in list */

    printf("%s\n", value);
    newPtr = malloc( sizeof( ListNode ) ); /* create node */

    if ( newPtr != NULL )  /* is space available */
    {
        newPtr->data = value; /* place value in node */
        newPtr->nextPtr = NULL; /* node does not link to another node */

        previousPtr = NULL;
        currentPtr = *sPtr;

        if (currentPtr == NULL)
            *sPtr = newPtr;
        else
        {
            while ( currentPtr != NULL ) 
            {
                previousPtr = currentPtr;
                currentPtr = currentPtr->nextPtr;
            }
            previousPtr->nextPtr = newPtr;
            newPtr->nextPtr = NULL;
        }
    }   
    else
    {
        printf( "%c not inserted. No memory available.\n", value );
    } /* end else */

} /* end function insert */


/* Print the list */
void printList( ListNodePtr currentPtr )
{
    /* if list is empty */
    if ( currentPtr == NULL ) {
        printf( "List is empty.\n\n" );
    } /* end if */
    else {
        printf( "The list is:\n" );

        /* while not the end of the list */
        while ( currentPtr != NULL ) {
            printf( "%s\n", currentPtr->data );
            currentPtr = currentPtr->nextPtr;
        } /* end while */

        printf( "NULL\n\n" );
    } /* end else */
} /* end function printList */

输出为:

列表是: 星期日 星期日 周日

2 个答案:

答案 0 :(得分:3)

insert函数中,您指向所有元素的相同地址,您必须分配内存来存储名称。请参阅代码第57行并添加:

    newPtr = malloc( sizeof( ListNode ) ); /* create node */
   if ( newPtr != NULL )  /* is space available */
   {
    char *val=malloc((strlen(value)+1)*1);
    strcpy(val,value);
    newPtr->data = val; /* place value in node */
    newPtr->nextPtr = NULL;
    .
    .
    .

答案 1 :(得分:0)

insert中,您可以像这样分配字符串:

newPtr->data = value;

这将存储dirent结构中字符串的引用。这将始终是指向同一缓冲区的指针,但每次创建链接时缓冲区将具有不同的内容。当你打印它时,该缓冲区当然会有最后一个条目的内容。 (当dirent结构超出范围时,指针变为陈旧:它将指向无效数据。但是在代码中并非如此。)

要存储实际值,您必须创建副本。 Thzat副本需要存储,您必须分配:

newPtr->data = malloc(strlen(value) + 1);
strcpy(newPtr->data, value);

每个malloc都需要相应的free,因此在销毁列表时不要忘记释放字符串的内存。