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); }