5

現在、文字列を ,;= とスペースの区切り文字でトークンに分割するコードを設定しています。また、特殊文字をトークンとして含めたいと思います。

char * cstr = new char [str.length()+1];
strcpy (cstr, str.c_str());

char * p = strtok (cstr," ");

while (p!=0)
{
    whichType(p);
    p = strtok(NULL," ,;=");
}

したがって、今、次のような文字列のトークンを出力すると、次のasd sdf qwe wer,sdf;werようになります。

asd
sdf
qwe
wer
sdf
wer

のようにしたい

asd
sdf
qwe
wer
,
sdf
;
wer

どんな助けでも素晴らしいでしょう。ありがとう

4

3 に答える 3

11

もっと柔軟性が必要です。(さらに、strtok悪い、エラーが発生しやすいインターフェイスです)。

トークンを生成し、それらを出力イテレータにコピーする柔軟なアルゴリズムを次に示します。これは、それを使用して、選択したコンテナーに入力したり、出力ストリームに直接出力したりできることを意味します (これをデモとして使用します)。

動作はオプション フラグで指定されます。

enum tokenize_options
{
    tokenize_skip_empty_tokens              = 1 << 0,
    tokenize_include_delimiters             = 1 << 1,
    tokenize_exclude_whitespace_delimiters  = 1 << 2,
    //
    tokenize_options_none    = 0,
    tokenize_default_options =   tokenize_skip_empty_tokens 
                               | tokenize_exclude_whitespace_delimiters
                               | tokenize_include_delimiters,
};

名前を付けていない追加の要件を実際に抽出した方法ではありませんが、サンプルは、区切り文字が空白でない限りトークンとして出力することを意味します( ' ')。これが 3 番目のオプションの目的ですtokenize_exclude_whitespace_delimiters

これが本当の肉です:

template <typename Input, typename Delimiters, typename Out>
Out tokenize(
        Input const& input,
        Delimiters const& delim,
        Out out,
        tokenize_options options = tokenize_default_options
        )
{
    // decode option flags
    const bool includeDelim   = options & tokenize_include_delimiters;
    const bool excludeWsDelim = options & tokenize_exclude_whitespace_delimiters;
    const bool skipEmpty      = options & tokenize_skip_empty_tokens;

    using namespace std;
    string accum;

    for(auto it = begin(input), last = end(input); it != last; ++it)
    {
        if (find(begin(delim), end(delim), *it) == end(delim))
        {
            accum += *it;
        }
        else
        {
            // output the token
            if (!(skipEmpty && accum.empty()))
                *out++ = accum;   // optionally skip if `accum.empty()`?

            // output the delimiter
            bool isWhitespace = std::isspace(*it) || (*it == '\0'); 
            if (includeDelim && !(excludeWsDelim && isWhitespace))
            {
                *out++ = { *it }; // dump the delimiter as a separate token
            }

            accum.clear();
        }
    }

    if (!accum.empty())
        *out++ = accum;

    return out;
}

完全なデモは、Live on Ideone (デフォルト オプション)およびLive on Coliru (オプションなし)です。

int main()
{
    // let's print tokens to stdout
    std::ostringstream oss;
    std::ostream_iterator<std::string> out(oss, "\n"); 

    tokenize("asd sdf qwe wer,sdf;wer", " ;,", out/*, tokenize_options_none*/);

    std::cout << oss.str();
    // that's all, folks
}

版画:

asd
sdf
qwe
wer
,
sdf
;
wer
于 2013-09-26T21:27:55.723 に答える