タブ区切りの文字列を安全に解析するにはどうすればよいですか?
-
27-09-2019 - |
質問
タブ区切り文字列を安全に解析するにはどうすればよいですか?例えば:テスト bla-bla-bla 2332 ?
解決
strtok()
は、任意の区切り文字を含む文字列を解析するための標準的な機能です。それは、しかし、スレッドセーフではありません。選択のあなたのCライブラリはスレッドセーフな変数がある場合があります。
別の標準に準拠した方法(ちょうどこのアップを書いて、それが にテストされていません)。
#include <string.h>
#include <stdio.h>
int main()
{
char string[] = "foo\tbar\tbaz";
char * start = string;
char * end;
while ( ( end = strchr( start, '\t' ) ) != NULL )
{
// %s prints a number of characters, * takes number from stack
// (your token is not zero-terminated!)
printf( "%.*s\n", end - start, start );
start = end + 1;
}
// start points to last token, zero-terminated
printf( "%s", start );
return 0;
}
他のヒント
strtok の代わりに strtok_r を使用します (使用可能な場合)。再入可能であることを除けば、同様の使用法があります。 ではない strtok と同様に文字列を変更します。[編集: 実は、言い間違えてしまいました。Christoph が指摘しているように、strtok_r は区切り文字を「\0」に置き換えます。したがって、元の文字列を保持したい場合は、文字列のコピーを操作する必要があります。ただし、再入可能でスレッドセーフであるため、strtok を使用することをお勧めします。]
strtok は元の文字列を変更したままにします。区切り文字を「\0」に置き換えます。また、文字列がたまたま定数で、読み取り専用メモリに保存されていた場合 (一部のコンパイラはこれを行います)、実際にアクセス違反が発生する可能性があります。
strtok()
からstring.h
を使用します。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "test\tbla-bla-bla\t2332";
char * pch;
pch = strtok (str," \t");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " \t");
}
return 0;
}
現在のページを参照してください、任意の正規表現ライブラリ、あるいはのGLib GScanner
を使用することができますとここの詳細については、。
さらに別バージョン。この1つは新しい関数にロジックを分離
#include <stdio.h>
static _Bool next_token(const char **start, const char **end)
{
if(!*end) *end = *start; // first call
else if(!**end) // check for terminating zero
return 0;
else *start = ++*end; // skip tab
// advance to terminating zero or next tab
while(**end && **end != '\t')
++*end;
return 1;
}
int main(void)
{
const char *string = "foo\tbar\tbaz";
const char *start = string;
const char *end = NULL; // NULL value indicates first call
while(next_token(&start, &end))
{
// print substring [start,end[
printf("%.*s\n", end - start, start);
}
return 0;
}
あなたが与えられた文字列をトークン化するために、バイナリセーフな方法が必要な場合:
#include <string.h>
#include <stdio.h>
void tokenize(const char *str, const char delim, const size_t size)
{
const char *start = str, *next;
const char *end = str + size;
while (start < end) {
if ((next = memchr(start, delim, end - start)) == NULL) {
next = end;
}
printf("%.*s\n", next - start, start);
start = next + 1;
}
}
int main(void)
{
char str[] = "test\tbla-bla-bla\t2332";
int len = strlen(str);
tokenize(str, '\t', len);
return 0;
}