cstrtok

C strtok() split string into tokens but keep old data unaltered


I have the following code:

#include <stdio.h>
#include <string.h>

int main (void) {
    char str[] = "John|Doe|Melbourne|6270|AU";

    char fname[32], lname[32], city[32], zip[32], country[32];
    char *oldstr = str;

    strcpy(fname, strtok(str, "|"));
    strcpy(lname, strtok(NULL, "|"));
    strcpy(city, strtok(NULL, "|"));
    strcpy(zip, strtok(NULL, "|"));
    strcpy(country, strtok(NULL, "|"));

    printf("Firstname: %s\n", fname);
    printf("Lastname: %s\n", lname);
    printf("City: %s\n", city);
    printf("Zip: %s\n", zip);
    printf("Country: %s\n", country);
    printf("STR: %s\n", str);
    printf("OLDSTR: %s\n", oldstr);

    return 0;
}

Execution output:

$ ./str
Firstname: John
Lastname: Doe
City: Melbourne
Zip: 6270
Country: AU
STR: John
OLDSTR: John

Why can't I keep the old data nor in the str or oldstr, what am I doing wrong and how can I not alter the data or keep it?


Solution

  • when you do strtok(NULL, "|") strtok() find token and put null on place (replace token with \0) and modify string.

    you str, becomes:

    char str[] = John0Doe0Melbourne062700AU;
                     
      Str array in memory 
    +------------------------------------------------------------------------------------------------+
    |'J'|'o'|'h'|'n'|0|'D'|'o'|'e'|0|'M'|'e'|'l'|'b'|'o'|'u'|'r'|'n'|'e'|0|'6'|'2'|'7'|'0'|0|'A'|'U'|0|
    +------------------------------------------------------------------------------------------------+
                     ^  replace | with \0  (ASCII value is 0)
    

    Consider the diagram is important because char '0' and 0 are diffident (in string 6270 are char in figure parenthesised by ' where for \0 0 is as number)

    when you print str using %s it print chars upto first \0 that is John

    To keep your original str unchanged you should fist copy str into some tempstr variable and then use that tempstr string in strtok():

    char str[] = "John|Doe|Melbourne|6270|AU";
    char* tempstr = calloc(strlen(str)+1, sizeof(char));
    strcpy(tempstr, str);
    

    Now use this tempstr string in place of str in your code.