user3333134
user3333134

Reputation: 399

Pointer values changing and memory in C

I'm having a problem in my code where I am using a pointer that points to memory that I want to store in an array of things I call Holder. This program is reading data in from a txt file which is labelled as line.

Holder h; 
Holder anArray[numberOfValues];
char* entry = malloc(160*sizeof(char));
int i = 0;

While(Something) {
   If(x happens) {
     char* p = strtok(entry,".")   //Taking off part of a string based on a "."
     h.firstpart = p;
     p = strtok(NULL, " ");       //Grab second part of string.
     h.secondpart = p;
   }
   else {
     anArray[i] = h;
     i++;
   }

The problem I’m having is that h.firstpart and h.secondpart are both going to have the same value since they are just pointing to something and not an actual value themselves. When this reaches the last loop all of my values in the array are set to the thing that was on the last line.

Sorry if this is posted somewhere else, please link me if it is. I'm a C rookie and have been searching for a work around for a few hours now. I'm assuming I need to malloc more memory for this and somehow put the values that p points to into that memory? I'm confused on how I would go about doing that for this loop.

This is also homework, but they expect me to know C already so the context of this question does not solve the problem for me in anyway.

Upvotes: 0

Views: 109

Answers (2)

slim
slim

Reputation: 41223

Be wary of strtok. It modifies the string it's examining.

Let's say your entry is a chunk of memory starting at address 1000, and contains the string "abcdef"

1000 1001 1002 1003 1004 1005 1006
a    b    c    d    e    f    g

entry == 1000

If you do:

h.firstpart = strok(entry, "c");

Then strtok() will return the first token it finds using 'c' as a delimiter. But it does that by replacing the 'c' with a NULL!!

1000 1001 1002 1003 1004 1005 1006
a    b    NULL d    e    f    g

entry == 1000
h.firstpart == 1000 // "ab"

When you call strtok again, with NULL as the first argument, it returns the next token along, again replacing the delimiter with NULL.

h.secondpart = strtok(null, "f");

1000 1001 1002 1003 1004 1005 1006
a    b    NULL d    e    NULL g

entry == 1000
h.firstpart == 1000 // "ab"
h.secondpart == 1003 // "de"

So, h.firstpart and h.secondpart are pointers into your original chunk of memory. They are not equal to each other. But strtok() has written NULLS into your memory, which may not be what you want.

To get around this, either make a copy of the memory before letting strtok at it, or use something different from strtok.

Upvotes: 0

Klas Lindbäck
Klas Lindbäck

Reputation: 33273

Since the contents of entry get overwritten with each line, you need to copy the values to another location.

The easiest way would be to use strdup, which allocates memory for a nul-terminated string and copies it:

While(Something) {
   If(x happens) {
     char* p = strtok(entry,".")   //Taking off part of a string based on a "."
     h.firstpart = strdup(p);
     p = strtok(NULL, " ");       //Grab second part of string.
     h.secondpart = strdup(p);
   }
   else {
     anArray[i] = h;
     i++;
   }

strdup is declared in <string.h>

Upvotes: 1

Related Questions