4

strtok_s で使用するために文字列を char * に変換する必要があり、それを理解できませんでした。c_str() は、互換性のない const char * に変換されます。

また、2 番目の strtok_s 関数 (ループ内) が必要な理由を誰かが説明できれば、非常に役立ちます。たとえば、ファイルの各行を連続して暗黙的にフェッチする while ループではなく、トークンを明示的に進める必要があるのはなぜですか。

while( getline(myFile, line) ) { // Only one line anyway. . . is there a better way?
    char * con = line.c_str();
    token = strtok_s( con, "#", &next_token);
    while ((token != NULL))
    {
        printf( " %s\n", token );
        token = strtok_s( NULL, "#", &next_token);
    }
}

関連する質問

4

10 に答える 10

8

返された byを astrdup()にコピーするために使用します (後でそれを覚えておいてください)const char *c_str()char *free()

strdup()free()は C++ ではなく C の関数であり、std::string代わりにの メソッドを使用する方がよいことに注意してください。

2 番目の strtok_s() が必要なのは、そうしないとループが終了しないためです (tokenの値は変更されません)。

于 2009-10-07T15:34:24.433 に答える
5

ダニエルが言ったように、あなたは一緒に行くことができます

strdup(line.c_str());

必要なスペースを割り当てるため、最初に提案した strcpy よりも優れています

于 2009-10-07T15:31:51.630 に答える
5

に変換することはできません。これにより、の内部バッファーchar *に書き込むことができるようになるからです。の実装が見えるようになるのstd::stringを避けるため、これは許可されていません。std::string

の代わりにstrtok、より「C++ に似た」方法で文字列をトークン化してみてください。この質問を参照してください:

C++ で文字列をトークン化するにはどうすればよいですか?

于 2009-10-07T15:32:18.447 に答える
2

strtok()そもそも不適切に設計された関数です。ドキュメントをチェックして、より良いドキュメントがあるかどうかを確認してください。ところで、strtok()呼び出しの間に状態を保存し、呼び出された文字列を変更するため、ドキュメントで安全であると明確に述べられていない限り、いかなる種類のスレッド環境でも使用しないでください。はより安全なバージョンだと思いstrtok_s()ますが、本当に安全なバージョンにはなりません。

を に変換するstd::stringには、次のchar *ようにします。

char * temp_line = new char[line.size() + 1];  // +1 char for '\0' terminator
strcpy(temp_line, line.c_str());

と使用しますtemp_line。インストールにはstrdup()、上記と重複する機能がある場合があります。

2 つの呼び出しが必要な理由strtok_s()は、それらが異なることを行うためです。最初のものはstrtok_s()どの文字列を処理する必要があるかを示し、2 番目のものは同じ文字列を続けます。これが NULL 引数の理由です。strtok_s()元の文字列を使い続けるように指示します。

したがって、最初のトークンを取得するために 1 回の呼び出しが必要であり、その後のトークンごとに 1 回の呼び出しが必要です。それらは次のようなものと組み合わせることができます

char * temp_string_pointer = temp_line;
while ((token = strtok_s( con, "#", &next_token)) != NULL)
{
   temp_string_pointer = NULL;

strtok_s()など、これは文字列ポインターで 1 回呼び出され、その後NULL. 処理後にしたいので、これには temp_line を使用しないでくださいdelete[] temp_line;

これはかなりいじっていると思うかもしれませんが、それはstrtok()親戚が通常必要とするものです。

于 2009-10-07T16:09:11.010 に答える
1

std::stringがあり、必要なものが(変更可能な)文字配列である場合はいつでも、必要なものは次のstd::vector<char>とおりです。

void f(char* buffer, std::size_t buffer_size);

void g(std::string& str)
{
  std::vector<char> buffer(str.begin(),str.end());
  // buffer.push_back('\0');    // use this if you need a zero-terminated string
  f(&buffer[0], buffer.size()); // if you added zero-termination, consider it for the size
  str.assign(buffer.begin(), buffer.end());
}
于 2009-10-07T15:45:50.150 に答える
1

strtok は次のように機能します。

最初の呼び出しは、区切り文字が見つからない場合は区切り文字またはすべての文字列を解放する最初から文字列を返します。

token = strtok_s(con, "#", &next_token);

NULL を使用して 2 回目の呼び出しを行うと、同じ文字列の解析を続けて次の区切り文字を見つけることができます。

token = strtok_s(NULL, "#", &next_token);

文字列の最後に到達すると、次の呼び出しは NULL を返します。

于 2009-10-07T15:35:19.703 に答える
0

文字列をトークン化し、部分文字列のベクトルを返す変換ルーチンを簡単に作成できます。

std::vector<std::string> parse(const std::string& str, const char delimiter)
{
    std::vector<std::string> r;

    if(str.empty())
        return r;

    size_t prev = 0, curr = 0;

    do
    {
        if(std::string::npos == (curr = str.find(delimiter, prev)))
            curr = str.length();

        r.push_back(str.substr(prev, curr - prev));
        prev = curr + 1;
    }
    while(prev < (int)str.length());
    return r;
}
于 2009-10-07T20:20:56.010 に答える
0

文字列の内部バッファに本当にアクセスする必要がある場合は、次の方法があります&*string.begin()。文字列のバッファへの直接アクセスは、場合によっては便利です。ここでそのようなケースを見ることができます。

于 2009-10-07T15:54:42.190 に答える
0

2 番目の strtok 呼び出しはループ内にあります。トークン ポインターを進めて、トークンを 1 つずつ出力し、すべてのトークンを出力するまで、ポインターが null になり、ループを終了します。

あなたの質問の最初の部分に答えるために、他の人が示唆しているように、 c_str() は内部バッファーポインターのみを提供します-それを変更することはできません。それが const である理由です。変更する場合は、独自のバッファーを割り当て、文字列の内容をそこにコピーする必要があります。

于 2009-10-07T15:37:08.827 に答える
-1

最初に文字列を const char* に変換し、次に const char* を char* バッファーにコピーしてさらに使用できると思います。

于 2009-10-07T15:33:53.170 に答える