3

次のような 2 つの文字列があります。

string text1 = "you,are,good";
string text2 = "1,2,3,4,5";
stringstream t1(text1);
stringstream t2(text2);

次のコードを使用して、コンマ区切りのデータとして解析しています

template <typename T>
std::istream &operator>>(std::istream &is, Array<T> &t)
{
    T i;
    while (is >> i)
    {
        t.push_back(i);

        if (is.peek() == ',')
            is.ignore();
    }
    return is;
}

ここで、「is」は t1 または t2 です。これは text2 を分離しますが、text1 で失敗します。それを手伝ってくれて、なぜ文字列でうまくいかないのか教えてくれませんか? 文字列と数値を解析する一般的なコードが必要です。

努力してくれてありがとう:)

4

2 に答える 2

3

文字列をコンマで正確に分割する必要がある場合、私が知っている最も簡単なアプローチは、ストリームのスペースの意味を再定義することです。std::ctype<char>これは、ファセットを簡単に置き換えることができます。これは私が以前に投稿したこのバージョンです...

#include <iostream>
#include <iterator>
#include <string>
#include <set>
#include <algorithm>

using namespace std;

typedef string T; // to simplify, always consider T as string

template<typename input_iterator>
void do_something(const input_iterator& first, const input_iterator& last) {
    const ostream_iterator<T> os(cout, "\n");
    const set<T> words(first, last);
    copy(words.begin(), words.end(), os);
}

#include <locale>
template <char S0, char S1>
struct commactype_base {
    commactype_base(): table_() {
        std::transform(std::ctype<char>::classic_table(),
                       std::ctype<char>::classic_table() + std::ctype<char>::table_size,
                       this->table_, 
                       [](std::ctype_base::mask m) -> std::ctype_base::mask {
                           return m & ~(std::ctype_base::space);
                       });
        this->table_[static_cast<unsigned char>(S0)] |= std::ctype_base::space;
        this->table_[static_cast<unsigned char>(S1)] |= std::ctype_base::space;
    }
    std::ctype<char>::mask table_[std::ctype<char>::table_size];
    static std::ctype_base::mask clear_space(std::ctype_base::mask m) {
        return m & ~(std::ctype_base::space);
    }
};
template <char S0, char S1 = S0>
struct ctype:
    commactype_base<S0, S1>,
    std::ctype<char>
{
    ctype(): std::ctype<char>(this->table_, false) {}
};

int main() {
    std::cin.imbue(std::locale(std::locale(), new ::ctype<',', '\n'>));
    const istream_iterator<T> is(cin), eof;
    do_something(is, eof);
    return 0;
}
于 2012-11-24T19:37:08.497 に答える
3

istream>>演算子を文字列に適用すると、最終的な最初のスペースが破棄され、最初の「スペース」まで読み取られます。

どの型 (int を含む) でも同じように機能します。「、」で「intリーダー」が失敗し、以下が別のものであると想定するため、コードで機能します。

コンマで区切られた文字列を読み取る最も簡単な方法は、区切り文字として a を指定してstd::getline関数を使用すること','です。

あなたの場合、テンプレート関数

template <typename T>
std::istream &operator>>(std::istream &is, Array<T> &t)
{ ...... }

有効なままですが、専門化が必要です

std::istream &operator>>(std::istream &is, Array<std::string> &t)
{
    std::string r;
    while(std::getline(is,r,','))
        t.push_back(r);
    return is;
}
于 2012-11-24T19:45:03.087 に答える