C语言 链表数据都一样



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

添加功能:

#include "linkedList.h"
#include <stdlib.h>
#include <string.h>
void addOrdered(Node ** Head,char * input)
{
        printf("nInput: %sn",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);
}

代码中的错误是:分配给newNode->Data->FName的地址一旦您在processFile((函数中调用free(input)并访问可用内存就会变得无效,从而导致运行时出现"未定义的行为"。

要更正代码,请执行以下操作:

而不是简单的分配,例如:

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 (; manual:

在第一次调用时,该函数需要一个 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: %pn",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内。

同样,在代码中,在函数中分配给newNode->Data->FName = strtok(input," "); addOrdered()newNode->Data->FName处的内存地址值在/来自您后来在processFile()函数中释放的input 因此newNode->Data->FName变得无效,并且您的代码作为未定义的行为运行

void addOrdered(Node ** Head,char * input){
        printf("nInput: %sn",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"

其次,您应该从缓冲区中的文件中少读取一个字符,为空保留空间。

fgets(input, SIZE-1, fd)

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

相关内容

  • 没有找到相关文章