thisdesuのブログ

C言語はじめました

にほんブログ村 IT技術ブログ C/C++へ

文字区切りstrtok

文字列を特定の文字ごとに区切りたい時など便利か関数=strtokです。例えば"123-456-78-9-0A"の文字列が在った時に、-で区切って簡単に取得したいときに便利です。
が、、、、この関数には2つの悪魔が住んでるので要注意。後から説明します

■サンプル

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

int main() {
  char       string[]    ="123-456-78-9-0A";
  char       *p;

  p = strtok(string,"-");
  while( p != 0x00 ) {
       printf("[%s]\n",p);
     p = strtok(0x00,"-");
  }
}


■結果

$ gcc main.c
$ ./a.out
[123]
[456]
[78]
[9]
[0A]


さて1つ目の悪魔。サンプルで2回目以降の取得する時の関数の引数にnull(0x00)を指定していて、あれ?アドレス指定してないのに?って思うでしょう。
そう、この関数はステータスを保持しちゃう関数で、同時に2つは使えないんです。途中で使うと情報を上書きして消えてしまうんです。超要注意

■サンプル

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

int main() {
  char       string[]    ="123-456-78-9-0A";
  char       *p;
  char       string2[]    ="XXX-yyy-z-xyz-xyz";
  char       *p2;

  p = strtok(string,"-");
  printf("[%s]\n",p);

  p = strtok(0x00,"-");
  printf("[%s]\n",p);

  p2 = strtok(string2,"-");
  printf("[%s]\n",p);

  p = strtok(0x00,"-");
  printf("[%s]\n",p);
}


■結果

$ gcc main.c
$ ./a.out
[123]
[456]
[456]
[yyy]


そして2つ目の悪魔。またまたサンプルで2回目以降の取得する時の関数の引数にnull(0x00)を指定していたの覚えているでしょうか?なぜ0x00?って思ったしょう。それってstringの終端じゃね?そうです。strtokで取得した文字列はstringになってましたね。はい。お気付きですね。この関数。最初に指定した文字列の値を変更してるんです。区切り文字の箇所の0x00を入れ込んでるんです。次に探す頭が0x00から続けているんです。
この関数を”探す”って利用すると危険です。元の値を変更するって事を覚えておいてください。さらに変更不可の領域(const)t)を設定すると例により落ちます。

■サンプル

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

int main() {
  char       string[]    ="123-456-78-9-0A";
  char       *p;

  printf("[%s]\n",string);
  p = strtok(string,"-");
  printf("[%s]\n",p);
  printf("[%s]\n",string);

  p = strtok(0x00,"-");
  printf("[%s]\n",p);
  printf("[%s]\n",string);
}


■結果

$ gcc main.c
/a.out
[123-456-78-9-0A]
[123]
[123]
[456]
[123]