【问题标题】:Splitting a stringstream that contains comma separated entries拆分包含逗号分隔条目的字符串流
【发布时间】:2012-11-12 17:53:47
【问题描述】:

我有两个字符串,如下所示:

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;
}

其中“是”是 t1 或 t2。这将 text2 分开,但使用 text1 失败。你们能帮我解决这个问题并告诉我为什么它不适用于字符串吗? 我需要一个可以解析字符串和数字的通用代码。

感谢您的努力:)

【问题讨论】:

    标签: c++ string stream operator-overloading stringstream


    【解决方案1】:

    如果您需要精确地以逗号分隔字符串,我知道的最简单的方法是重新定义流的空间含义。这很容易替换std::ctype&lt;char&gt; 方面。这是我之前发布的版本...

    #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;
    }
    

    【讨论】:

    • 当然。您可以使用上面的语言环境设置流,也可以专门处理字符串。事情是当流找到一个空格时,读取一个字符串就会停止。由于您的输入不包含任何空格,因此有必要将逗号视为空格(或以不同方式处理字符串)。
    【解决方案2】:

    istream &gt;&gt; 运算符在应用于字符串时会丢弃最终的初始空格并读取到第一个“空格”。

    它适用于任何类型(包括 int)。它可以在您的代码中使用,因为在“int reader”处,“int reader”失败,并假定以下是其他内容。

    读取逗号分隔字符串的最简单方法是使用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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-28
      • 2018-12-21
      • 2015-03-07
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 2018-01-25
      • 2012-05-24
      相关资源
      最近更新 更多