Thinkers'Studio
JavaとC言語の自習ツール
文字列を分割する split関数の自作例

 Java には split というメソッドがあり、指定した区分文字列で分割したリストを簡単に取得できます。
 C言語には、split関数がありません。 そこで今回は、strtok関数を活用した split関数の自作例を紹介します。

strtok関数を活用したsplit関数の自作例

split 関数の自作サンプルプログラム 】
 だらだらと書いたメモ (memostr) があります。
 それをsplit関数に渡し、カンマなどの区切りで分割して買い物リスト(shoppinglst)にその結果を入れるよう指示します。
 split関数は指示通りに分割して、その数を戻り値で返します。 main関数で、分割した結果を表示します。
#include <stdio.h>
#include <string.h>
#define MAXITEM 20

int split( char *str, const char *delim, char *outlist[] ) {
    char    *tk;
    int     cnt = 0;

    tk = strtok( str, delim );
    while( tk != NULL && cnt < MAXITEM ) {
        outlist[cnt++] = tk;
        tk = strtok( NULL, delim );
    }
    return cnt;
}

main()
{
    char    memostr[] = "Milk, Eggs:Bread, Apple, Cheese";
    char    *shoppinglst[MAXITEM];
    int     i, cnt;

    cnt = split( memostr, ", :" , shoppinglst );
    printf( "memostr = '%s'\n", memostr );
    for( i = 0; i < cnt; i++ ) {
        printf( "%d:%s\n", i+1, shoppinglst[i] );
    }
}
 このプログラムを実行すると、次のように表示されます。
memostr = 'Milk'
1:Milk
2:Eggs
3:Bread
4:Apple
5:Cheese

 実行結果の1行目は、split で処理した後、main 関数で memostr をプリントしたものですが、内容が変わっていますね。 このように、strtok は引数で渡された文字列を壊すような仕組みで分解していきます。変えられては困る文字列をそのまま渡さないよう注意が必要です。
 区切り文字には複数の文字を指定できます。上の例では、「カンマか空白か : のいずれか」を区切り文字に指定しました。  

【 strtok の形式 】 char *strtok( char *s, const char *ct )

ct が指す文字列で区切られるトークンを、文字列 s 中で探します。
複数回の呼出しにより分解することができます。2回目以降は第1引数を NULL にして呼び出します。
戻り値は、区切られたトークンへのポインタです。トークンがなくなると NULL を返します。

(今回のクイズです)
 上のプログラムで、memostr に書いたアイテム数が MAXITEM の 20 を超えるとどうなるでしょうか?
   (答えは、次回のC言語の Tips で ・・・)

前回のクイズの答え: (前回の問題を見る
*(p + 1) は「次の文字の値」でしたが、*p + 1 と書くと、「 p が指す文字に1を足したコードの文字」となります。たとえば *p が 'C' なら、'D'のことを意味します。 そのため、判定が上手くいかず、大文字の前に空白が入りません。
試しに、大文字の最後の文字 'Z' に変えてやってみると、1を足した文字は大文字ではないので実行結果は、
「W eZanW orkI tO ut」となります。