C言語 - 標準ライブラリ - string.h - トークン取得 strok strsep

 
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 であってはならないし、第Ⅰ引数に与えたポインタは strtok_r で変更されますので、例のように定数値であっても snprintf のようにメモリに代入し、strtok_r に渡す引数は引数用のポインタを用意してあげるようにします。  初回の strtok_r 呼出し時はトークンを取得する文字列のポインタを第Ⅰ引数に設定します。  同じ文字列からトークンを取得する間は NULL を第Ⅰ引数に設定します。

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
 
 
カウンタバックグラウンド