0Pricing
C Academy · レッスン

strtok とトークン化

文字列を分割します。

「strtok とトークン化」はCoddyKit上の無料C Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。

トークン化とは

トークン化とは、区切り文字で分けられた文字列を、より小さな部分(トークン)に分割することです。

たとえば、"a,b,c"をカンマで分割すると、トークンa、b、cが得られます。Cでは、この処理にstrtokを使用できます。

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

int main(void) {
    char text[] = "a,b,c";
    char *token = strtok(text, ",");
    printf("First token: %s\n", token);
    return 0;
}

strtokのシグネチャ

char *strtok(char *str, const char *delim);

最初の呼び出しでは文字列を渡します。後続の呼び出しではNULLを渡すと、前回の続きから処理されます。次のトークンを返し、処理が完了するとNULLを返します。

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

int main(void) {
    char text[] = "red green blue";
    char *tok = strtok(text, " ");
    while (tok != NULL) {
        printf("%s\n", tok);
        tok = strtok(NULL, " ");
    }
    return 0;
}

strtokは文字列を変更する

重要:strtokは元の文字列を変更します。各区切り文字を'\0'に置き換え、同じバッファー内を指すポインターを返します。

そのため、読み取り専用の文字列リテラルである"a,b"をトークン化することはできません。

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

int main(void) {
    char data[] = "x:y:z";
    strtok(data, ":");
    printf("data[1] is now: %d (the null byte)\n", data[1]);
    return 0;
}

書き込み可能なコピーを作る

strtokは入力を破壊するため、後で元の文字列が必要な場合は先にコピーしてください。

ローカルのchar配列を使うか、strcpyでバッファーにコピーしてください。

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

int main(void) {
    const char *original = "one-two-three";
    char copy[64];
    strcpy(copy, original);
    char *tok = strtok(copy, "-");
    while (tok) {
        printf("%s\n", tok);
        tok = strtok(NULL, "-");
    }
    printf("Original intact: %s\n", original);
    return 0;
}

複数の区切り文字

delim引数は文字の集合であり、文字の並びではありません。集合内の任意の文字が区切り文字として扱われます。

そのため、" ,;"を指定すると、空白、カンマ、セミコロンのすべてで同時に分割されます。

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

int main(void) {
    char text[] = "a,b;c d";
    char *tok = strtok(text, ",; ");
    while (tok) {
        printf("[%s]\n", tok);
        tok = strtok(NULL, ",; ");
    }
    return 0;
}

連続する区切り文字

strtokは、連続する区切り文字を1つの区切りとして扱い、空のトークンをスキップします。

したがって、"a,,b"から得られるのはaとbだけで、間に空のトークンはありません。空のフィールドが重要なCSV解析では、この点に注意してください。

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

int main(void) {
    char text[] = "a,,b";
    char *tok = strtok(text, ",");
    while (tok) {
        printf("token: %s\n", tok);
        tok = strtok(NULL, ",");
    }
    return 0;
}

トークン数を数える

よくある処理として、文字列に含まれるトークンの数を数えることがあります。ループ内でカウンターを増やしてください。

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

int main(void) {
    char sentence[] = "the quick brown fox";
    int count = 0;
    char *tok = strtok(sentence, " ");
    while (tok) {
        count++;
        tok = strtok(NULL, " ");
    }
    printf("Word count: %d\n", count);
    return 0;
}

strtokは隠れた状態を保持する

strtokは位置を静的な内部変数に保存します。そのため、NULLを渡すと前の文字列の続きから処理できます。

一方で、これは再入可能ではなく、スレッドセーフでもありません。2つの文字列を同時にトークン化することはできません。

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

int main(void) {
    char a[] = "1 2";
    char *t = strtok(a, " ");
    printf("%s\n", t);
    t = strtok(NULL, " ");
    printf("%s\n", t);
    return 0;
}

トークンの保存

分割後もトークンを使うには、返されたポインターを配列に保存します。これらは変更後のソースバッファー内を指しているため、バッファーは有効な状態を保つ必要があります。

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

int main(void) {
    char csv[] = "name,age,city";
    char *fields[10];
    int n = 0;
    char *tok = strtok(csv, ",");
    while (tok && n < 10) {
        fields[n++] = tok;
        tok = strtok(NULL, ",");
    }
    for (int i = 0; i < n; i++)
        printf("Field %d: %s\n", i, fields[i]);
    return 0;
}

再入可能な代替手段

POSIXにはstrtok_rがあり、隠れた状態の代わりに明示的なchar **saveptrを受け取ります。これにより、入れ子にしたり複数のスレッドで使ったりしても安全です。

移植性のある標準Cでは、1回の解析処理に限れば通常のstrtokで問題ありません。

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

int main(void) {
    char text[] = "p:q:r";
    char *save;
    char *tok = strtok_r(text, ":", &save);
    while (tok) {
        printf("%s\n", tok);
        tok = strtok_r(NULL, ":", &save);
    }
    return 0;
}

実践:パスを分割する

トークン化は、ファイルパスのような構造化テキストの解析で特に役立ちます。/で分割すると、各パス要素を取り出せます。

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

int main(void) {
    char path[] = "usr/local/bin";
    char *part = strtok(path, "/");
    while (part) {
        printf("-> %s\n", part);
        part = strtok(NULL, "/");
    }
    return 0;
}

クイックチェック

strtokの仕組みについての理解度を確認しましょう。

まとめ

strtokで文字列を分割する方法について学びました。

  • 最初の呼び出しでは文字列を渡し、後続の呼び出しではNULLを渡します。
  • 入力を変更し、区切り文字を'\0'に置き換えます。読み取り専用の文字列は先にコピーしてください。
  • 区切り文字の引数は集合であり、連続する区切り文字はまとめて扱われます。
  • 静的な状態を使用するためスレッドセーフではありません。必要に応じてstrtok_rを使用してください。

よくある質問

「strtok とトークン化」レッスンは無料ですか?

はい。「strtok とトークン化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。

「strtok とトークン化」で何を学びますか?

文字列を分割します。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「strtok とトークン化」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC Academyレッスンでコードを書いて実行できますか?

はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. strlen、strcpy、strcat
  2. strcmp と比較
  3. strtok とトークン化
  4. memcpy と memset
← C Academyに戻る