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」であってはならないし、第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
earthcar(アースカー)