このように使っているとしましょうstrtok()
。
char *token = strtok(input, ";-/");
どのトークンが実際に使用されているかを把握する方法はありますか?たとえば、入力が次のようなものだった場合:
こんにちは; 元気ですか?/私は元気です-終わり
各トークンに使用された区切り文字を特定できますか?トークンに続く区切り文字に応じて、特定のメッセージを出力できるようにする必要があります。
Important: strtok
is not re-entrant, you should use strtok_r
instead of it.
You can do it by saving a copy of the original string, and looking into offsets of the current token into that copy:
char str[] = "Hello there; How are you? / I'm good - End";
char *copy = strdup(str);
char *delim = ";-/";
char *res = strtok( str, delim );
while (res) {
printf("%c\n", copy[res-str+strlen(res)]);
res = strtok( NULL, delim );
}
free(copy);
This prints
;
/
-
EDIT: Handling multiple delimiters
If you need to handle multiple delimiters, determining the length of the current sequence of delimiters becomes slightly harder: now you need to find the next token before deciding how long is the sequence of delimiters. The math is not complicated, as long as you remember that NULL
requires special treatment:
char str[] = "(20*(5+(7*2)))+((2+8)*(3+6*9))";
char *copy = strdup(str);
char *delim = "*+()";
char *res = strtok( str, delim );
while (res) {
int from = res-str+strlen(res);
res = strtok( NULL, delim );
int to = res != NULL ? res-str : strlen(copy);
printf("%.*s\n", to-from, copy+from);
}
free(copy);
できません。strtok
次の区切り文字をヌル文字で上書きし(今回返されるトークンを終了するため)、上書きした前の値は格納されません。strtok
サンプル文字列を初めて呼び出すと、;
は永久に消えてしまいます。
変更している文字列の変更されていないコピーを保持している場合は、何かを行うことができますstrtok
-現在のトークンのnulターミネータのインデックス(文字列の先頭に対する)を指定すると、コピー内の同じインデックスを見ることができますそこに何があったか見てみましょう。
もちろん、文字列を区切るために独自のコードを書くよりも悪いかもしれません。結果のトークンがnulで終了しない状態で生きることができる場合は、strpbrk
またはを使用できます。strcspn
男3strtok
strtok()およびstrtok_r()関数は、トークン自体をNUL文字に置き換えた後、文字列内の後続の各トークンの先頭へのポインタを返します。トークンがなくなると、nullポインタが返されます。
しかし、少しのポインタ演算で、次のようなことができます。
char* string = "Hello,World!";
char* dup = strdup(string);
char* world = strtok(string, ",");
char delim_used = dup[world - string];
free(dup);