strtokによるトークンの切り出し

はじめに

strtok() は与えられた文字列を指定した区切り文字で区切り、トークンを返す関数である。トークンとは最小単位の文字列を意味しており、例えば英語の文章を空白区切りでトークンを切り出す場合、個々のトークンが単語を表している。ここではstrtok()の詳細を見ていく。

strtok()

strtok は文字列と区切り文字を引数にとりトークンの先頭へのポインタを返す。

#include <string.h>
char *strtok(char *str, const char *delim);

ここでポイントになるのは

  • 第一引数の文字列は書き換えられる。具体的には見つけた区切り文字が\0 に置換されていく。
  • 最終的に返しているのは置換した'\0' を末尾とする文字列の先頭へのポインタ
  • 2回目以降 はNULL を引数に呼び出す。これはstrtok の関数内でどこまで切りだしたかが記憶されていることによる(static 変数として記録されている)

である。

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

int main(){
    char *a = "abc def ghi jkl";
	
    // 破壊されるのでコピーする
    char buf[20];
    strcpy(buf, a);
    
    // 最初にbuf がどうなっているのか整数でみてみる
    for (int i = 0 ; i < 20 ; i++){
        printf("%d\n", buf[i]);
    }
    
    // この時点での
    printf("%p\n", buf);
    
    // 初回呼び出しで区切りたい文字列を指定
    char *p;
    p = strtok(buf, " ");
    printf("%p: %s\n", p, p); // bufの先頭と一致する
    
    // 2回目以降はbufで最初に見つけた区切り文字のあとの有効文字列に
    // 関数内部でポインタが当たっており、NULL を指定することで
    // そこから読み出すことを関数に伝えている
    while ( (p = strtok(NULL, " ")) != NULL ){
        printf("%p: %s\n", p, p);
    }
    
    // 最後にbuf がどうなっているのか整数でみてみる
    for (int i = 0 ; i < 20 ; i++){
		printf("%d\n", buf[i]);
    }
    return 0;
}

上記の実行例より、strtokが区切り文字を見つけると\0で置換し、文字列として終端させるが、NULLを引数とすることでその先を引き続き読み出している ことが読み取れる。

参考文献