strtok(区切り文字による文字列の切り分け)

STLのstringで,str="100 200 400"のような文字をスペースで切り分けて,a=100,b=200,c=400...のようにしたいことがある.
この場合,str.split(" "); のようにすれば適当に切り分けてvectorにでも出力してくれるんじゃないかと思っていたのだけど,調べたところsplitのようなものはどうも無いっぽく,代わりにCでstrtokという関数があるそうなのでこれを利用する.
(stringから使う場合は(char*)str.c_str();する)


strtokはstring.hの関数で,以下のような挙動をする.

http://www9.plala.or.jp/sgwr-t/lib/strtok.html

【書式】
#include
char *strtok(char *s1, const char *s2);

【説明】
分解対象文字列 s1 を、文字群 s2 中の文字を区切りに字句(トークン)に分解します。
次のような手順で strtok() を用いて文字列をトークンに分解することが出来ます。

1. 最初の呼び出しでは s1 には分解対象の文字列を指定します。トークンがあれば、strtok() はトークンへのポインタを返却します。
2. 2回目以降の呼び出しでは s1 に NULL を指定します。分解できるトークンがあるうちは、strtok() はトークンへのポインタを返却します。
3. トークンがなくなると strtok() は NULL を返却します。

strtok() はトークンへのポインタを返却しながら、分解対象文字列 s1 中の区切り文字に空文字('\0')を埋めていきます。ですから、s1 に文字列リテラルや変更されては困る文字列を指定してはいけません。


つまり,1回目の切り分けでは strtok(str, " "); のようにstrを指定して,2回目以降では strtok(NULL, " "); のようにNULLを指定する.
strtokによる戻り値はトークンへのポインタ(トークンが無くなるとNULL)が返る.
なので,たとえばstrを" "切り分けた結果を出力するコードは以下のようになる.

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

int main()
{
    char str[] = "100 200 400";
    char *tp;

    tp = strtok(str," ");
    puts(tp);
    while (tp!=NULL) {
        tp = strtok(NULL," ");
        if (tp!=NULL) puts(tp);
    }
}


ただ,これだと1回目と2回目以降で処理の記述が重複してあまり美しくないので,次のように書くといいんじゃないかと思った.

#include <cstdio>
#include <cstring>


int main() {
    char str[]="100 200 400";

    char *tp;
    for (int tc=0;;) {
        tp=strtok((tc++==0)?str:NULL, " ");
        if (tp!=NULL) puts(tp);
        else break;
    }
}


要するにループが初回なら引数をstrに,2回目以降ならNULLを引数に指定しているというだけ.
ネット上のサンプルを見てると初回と2回目以降で2度strtokを書いているものが多くて少し気になったのでメモ.