strtok、便利ですね。マニュアルには「Never use these functions」なんて脅し文句が書いてありますが、気にしない。
ところでstrtokはスタティックな変数にポインターを保存しているので、入れ子にできないんですね。代替にstrtok_rという関数がありますが、なんかMinGWに入っていないっぽい。
じゃあ仕方ないので作ってみるか、と作ってみることにしました。引数を変更したりはしないし、確かマルチスレッドではグローバル変数だけが共有されると思ったので*1、スレッドセーフだと思います。
#include <stdio.h> #include <string.h> int tokenizer(char *, int, char *, char); int main(int argc, char **argv){ int p1=0, p2=0, p3=0; char buf1[256], buf2[256], buf3[256]; while((p1=tokenizer(argv[1], p1, buf1, '?')) != -1){ printf("tokenize1: %s\n", buf1); p2=0; while((p2=tokenizer(buf1, p2, buf2, '&')) != -1){ printf(" tokenize2: %s\n", buf2); p3=0; while((p3=tokenizer(buf2, p3, buf3, '=')) != -1){ printf(" tokenize3: %s\n", buf3); } } } printf("argv: %s\n", argv[1]); } int tokenizer(char *str, int p, char *buf, char d) { int i=0; while((buf[i]=str[p+i]) != '\0'){ if(buf[i++] == d){ buf[i-1]='\0'; break; } } buf[i] = '\0'; return (i==0) ? -1 : p+i; }
$ ./tokenize.exe "aaaaaa?bb=ccc&dddd=ee&f=g" tokenize1: aaaaaa tokenize2: aaaaaa tokenize3: aaaaaa tokenize1: bb=ccc&dddd=ee&f=g tokenize2: bb=ccc tokenize3: bb tokenize3: ccc tokenize2: dddd=ee tokenize3: dddd tokenize3: ee tokenize2: f=g tokenize3: f tokenize3: g argv: aaaaaa?bb=ccc&dddd=ee&f=g
イメージとしてはURLの文字切り分けのような感じで。argvも変更されてないでしょ、と。
*1:pthreadではそう