【问题标题】:Linked List Data All The Same链表数据都一样
【发布时间】:2013-04-06 05:03:08
【问题描述】:

我正在尝试从 .txt 文件中读取输入,并将其添加到单链表中。我遇到的问题是节点正在正确创建和连接(我得到正确的长度),但是在添加所有节点之后,每个数据字段都是相同的。我想知道问题是什么,以及如何解决它。一直在努力!

添加功能:

#include "linkedList.h"
#include <stdlib.h>
#include <string.h>

void addOrdered(Node ** Head,char * input)
{

        printf("\nInput: %s\n",input);

        Node * cur = (*Head);

        Node * newNode = malloc(sizeof(Node));
        newNode->Data = malloc(sizeof(Person));

        newNode->Data->FName = strtok(input," ");
        newNode->Data->LName = "test";
        newNode->Data->id = 5;
        newNode->Next = NULL;

        if(cur == NULL)
        {
            (*Head) = newNode;
        }
        else
        {

            for(;cur->Next != NULL;cur = cur->Next)
            {
                printf(" Cur->Next ");
            }

            cur->Next = newNode;
        }
}

处理文件:

void processFile(Node ** Head, FILE * fd)
{
    char * input = malloc(sizeof(char)*SIZE);

    while(fgets(input,SIZE,fd) != NULL)
    {
        addOrdered(Head,input);
    }


    free(input);
}

【问题讨论】:

    标签: c linked-list


    【解决方案1】:

    您的代码中的错误是:一旦您在 processFile() 函数中调用 free(input) 并访问空闲内存,分配给 newNode-&gt;Data-&gt;FName 的地址将变得无效,并在运行时导致“未定义行为”。

    更正您的代码:

    而不是简单的赋值:

    newNode->Data->FName = strtok(input," ");
    

    在单独的内存中分配和复制如下:

    char *ptr =  strtok(input," ");
    newNode->Data->FName = malloc(strlen(ptr)+1);
    strcpy(newNode->Data->FName, ptr);
    

    实际上,您在 addOrdered() 中从 input 地址空间分配内存地址,并在 processFile() 函数中创建 free()。

    我在下面详细解释你的代码:

    初读:char * strtok ( char * str, const char * delimiters );手册:

    在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,其第一个字符用作扫描标记的起始位置。在随后的调用中,该函数需要一个空指针,并使用最后一个标记结束后的位置作为新的扫描起始位置。

    返回值

    指向在字符串中找到的最后一个标记的指针。 如果没有要检索的令牌,则返回空指针。

    它不会发送新的内存,而是来自input 的内存,你最近释放了()。为了理解 strtok() 函数的工作,我编写了以下代码:

    int main (){
      char str[] ="- This, a sample string.";
      printf("str address: %p, ends on:  %p \n", str, str+strlen(str));
      printf ("Splitting string \"%s\" into tokens:\n",str);
      char * pch;
      pch = strtok (str," ,.-");
      while (pch != NULL){
        printf ("pch: %7s,  address: %p\n",pch, pch);
        pch = strtok (NULL, " ,.-");
      }
      return 0;
    }
    

    上述程序的执行(每次运行的地址可能不同):

    ~$ ./a.out 
    str address: 0x7fff96958d50, ends on:  0x7fff96958d68 
    Splitting string "- This, a sample string." into tokens:
    pch:    This,  address: 0x7fff96958d52
    pch:       a,  address: 0x7fff96958d58
    pch:  sample,  address: 0x7fff96958d5a
    pch:  string,  address: 0x7fff96958d61
    

    注意: pch 地址来自/在str 地址范围内。

    类似地,在您的代码中,在 addOrdered() 函数中分配给 newNode-&gt;Data-&gt;FName = strtok(input," ");。 newNode-&gt;Data-&gt;FName 处的内存地址值位于/来自 input,您后来在 processFile() 函数中释放所以 newNode-&gt;Data-&gt;FName 变为无效,您的代码以未定义行为运行

    void addOrdered(Node ** Head,char * input){
    
            printf("\nInput: %s\n",input);
            // some code here
                                                         step-2 
            newNode->Data->FName = strtok(input," "); <--"assign memory"  
                                                    ^
          //  Some code here                        |
    }                                               |   
                                                    |  
    void processFile(Node ** Head, FILE * fd){      |    step-1
        char * input = malloc(sizeof(char)*SIZE); <-|----"Allocate memory"
        while(fgets(input,SIZE,fd) != NULL){        |
            addOrdered(Head,input); -----------------
        }                                                step-3  
        free(input); <-----------------------------------"Free memory"
    }
    
    So, "What is assign to newNode->Data->FName becomes invalid"
    

    第二,你应该从缓冲区的文件中少读一个字符,为空\0保留空间。

    fgets(input, SIZE-1, fd)
    

    【讨论】:

    • 非常感谢!这是一个很大的帮助!
    【解决方案2】:

    strtok 返回一个指向在字符串中找到的最后一个标记的指针。 如果没有要检索的令牌,则返回空指针。 你需要做类似pch = strtok(input," ");

    【讨论】:

      猜你喜欢
      • 2013-11-21
      • 1970-01-01
      • 2016-04-23
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多