tokenize - Tokenizing a String - C -


i'm trying tokenize string in c based upon \r\n delimiters, , want print out each string after subsequent calls strtok(). in while loop have, there processing done each token.

when include processing code, output receive first token, when take processing code out, receive every token. doesn't make sense me, , wondering doing wrong.

here's code:

#include <stdio.h> #include <time.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h>  int main() {         int c = 0, c2 = 0;         char *tk, *tk2, *tk3, *tk4;         char buf[1024], buf2[1024], buf3[1024];         char host[1024], path[1024], file[1024];          strcpy(buf, "get /~yourloginid/index.htm http/1.1\r\nhost: remote.cba.csuohio.edu\r\n\r\n");          tk = strtok(buf, "\r\n");         while(tk != null)         {                 printf("%s\n", tk);                 /*                 if(c == 0)                 {                         strcpy(buf2, tk);                         tk2 = strtok(buf2, "/");                         while(tk2 != null)                         {                                 if(c2 == 1)                                         strcpy(path, tk2);                                 else if(c2 == 2)                                 {                                         tk3 = strtok(tk2, " ");                                         strcpy(file, tk3);                                 }                                 ++c2;                                 tk2 = strtok(null, "/");                         }                 }                 else if(c == 1)                 {                         tk3 = strtok(tk, " ");                         while(tk3 != null)                         {                                 if(c2 == 1)                                 {                                         printf("%s\n", tk3);                                 //      strcpy(host, tk2);                                 //      printf("%s\n", host);                                 }                                 ++c2;                                 tk3 = strtok(null, " ");                         }                 }                 */                 ++c;                 tk = strtok(null, "\r\n");         }          return 0; } 

without if else statements, receive following output...

get /~yourloginid/index.htm http/1.1 host: remote.cba.csuohio.edu 

...however, if else statements, receive this...

get /~yourloginid/index.htm http/1.1 

i'm not sure why can't see other token, because program ends, means loop must occur until end of entire string, right?

strtok stores "the point last token found" :

"the point last token found kept internally function used on next call (particular library implementations not required avoid data races)." -- reference

that's why can call null second time.

so calling again different pointer inside loop makes loose state of initial call (meaning tk = strtok(null, "\r\n") null end of while, because using state of inner loops).

so solution change last line of while from:

tk = strtok(null, "\r\n"); 

to (please check bounds first, should not go after buf + strlen(buf)):

tk = strtok(tk + strlen(tk) + 1, "\r\n"); 

or use strtok_r, stores state externally (like in answer).

// first call char *saveptr1; tk = strtok_r(buf, "\r\n", &saveptr1); while(tk != null) {    //...    tk = strtok_r(null, "\r\n", &saveptr1); }