问题
I'm trying to read in input from a .txt file, and add it into a singly linkedlist. The problem I'm having is the Nodes are being created and connected correctly (I'm getting the correct length), but after adding all the Node, each Data field is the same. I was wondering what the problem is, and how to fix it. Been going at it for awhile!
Add Function:
#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;
}
}
Processing File:
void processFile(Node ** Head, FILE * fd)
{
char * input = malloc(sizeof(char)*SIZE);
while(fgets(input,SIZE,fd) != NULL)
{
addOrdered(Head,input);
}
free(input);
}
回答1:
The Bug in your code is: Address assign to newNode->Data->FName becomes invalid once you call free(input) in processFile() function and access the free memory causes an 'Undefined Behavior' at run time.
To correct your code:
instead of simple assignment like:
newNode->Data->FName = strtok(input," ");
Allocate and Copy in separate memory as below:
char *ptr = strtok(input," ");
newNode->Data->FName = malloc(strlen(ptr)+1);
strcpy(newNode->Data->FName, ptr);
Actually you were assigning memory address from input address space in addOrdered() and makes free() in processFile() function.
I explain your code elaborate way below:
First read: char * strtok ( char * str, const char * delimiters ); manual:
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Return Value
A pointer to the last token found in string. A null pointer is returned if there are no tokens left to retrieve.
It doesn't sends a new memory but memory from input that you lately free(). To understand strtok() function work I written following code:
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;
}
An execution of above program (address can be different at each run):
~$ ./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
Notice: pch address are from/within str address scape.
Similarly in your code, assign to newNode->Data->FName = strtok(input," "); in addOrdered() function. memory address value at newNode->Data->FName is in/from input that you latterly free in processFile() function So newNode->Data->FName become invalid and your code runs as undefined behavior
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"
Second, you should read one less char from file in buffer, keep space for null \0.
fgets(input, SIZE-1, fd)
回答2:
strtok returns A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
You need to do something like pch = strtok(input," ");
来源:https://stackoverflow.com/questions/15847194/linked-list-data-all-the-same