- 1. 概要
- 2. 使う場面
- 3. 使用例 ソース
- 4. 使用例 Makefile
- 5. 使用例 実行
1. 概要
「strok」、「strsep」は、文字列をトークンの列に分割します。
わたしのイメージでは、「perl5」の「split」に似た動作をします。
「perl」では、一発でいきなりリストできるところを、分割した文字列を一回一回取得しなければならないところが、「C」言語の悲しさです。
ほぼ同じ機能を持つ「strok」、「strok_r」がありますが。
「strtok」は、スレッドセーフではないので使わない方がよいかと思われます。
「FreeBSD」の「strok_r」のマニュアルで「このインタフェースは strsep(3) によって置き換えられました」と書いてあります。
なので、「strsep」の方がよいのかなと思うと・・・。
「GNU」のマニュアルには「strsep() 関数は、 strtok(3) 関数が空のフィールドを 扱えないために、その代替品として導入された。 しかしながら、 strtok(3) 関数は C89/C99 に準拠しており、より移植性がある。」と書いてあり、どちらを使うべきか迷うところです。
「strsep」はスレッドセーフです。
2. 使う場面
使う場面。
わたしが実際に使ったのは、「.csv」ファイルの読込の場面でした。
3. 使用例 ソース
#include <string.h>
char *strtok(char *str, const char *sep);
char *strtok_r(char *str, const char *sep, char **last);
冒頭で述べているように「strtok」は、スレッドセーフでないので「strtok_r」を使用します。
./strtok.c
を作成して以下のように記述。
#include <limits.h>
#include <stdio.h>
#include <string.h>
#define DELIMITER " \t" // デリミタ文字列
int main(int argc, char* argv[])
{
char buff[PATH_MAX] = {}; // 元の文字列
char *work; // トークン取得用ポインタ
char *token; // トークンのポインタ
char *saveptr; // 処理用ポインタ
snprintf(buff, sizeof(buff), "aaa bbb ccc");
work = buff;
token = strtok_r(work, DELIMITER, &saveptr);
if (token == NULL)
{
return 0;
}
printf("%s\n", token);
while(1)
{
token = strtok_r(NULL, DELIMITER, &saveptr);
if (token == NULL)
{
break;
}
printf("%s\n", token);
}
return 0;
}
トークンを取得する文字列は、「const」であってはならないし、第1引数に与えたポインタは、「strtok_r」で変更されますので、例のように定数値であっても「snprintf」のようにメモリに代入し、「strtok_r」に渡す引数は引数用のポインタを用意してあげるようにします。
初回の「strtok_r」呼出し時はトークンを取得する文字列のポインタを第1引数に設定します。
同じ文字列からトークンを取得する間は「NULL」を第1引数に設定します。
4. 使用例 Makefile
./Makefile
を作成して以下のように記述。
.PHONY = target
CC = clang
target : strtok.o Makefile
$(CC) -O0 -g -o strtok strtok.o
.c.o : Makefile
$(CC) -O0 -g -c $< -o $@
5. 使用例 実行
「make」して実行すると以下の結果が得られます。
./strtok
aaa
bbb
ccc
|
|