【问题标题】:Pairs and stringstream对和字符串流
【发布时间】:2017-02-10 16:10:07
【问题描述】:

previous question 中,我问过我如何读取字符串向量并将其轻松转换为整数或双精度向量。

现在我将简单类型的向量扩展为由冒号分隔的 pairs 类型(考虑 intdouble 甚至 std::string,所有支持流的类型)的向量.

例子:

time:5, length:10

应该读作std::pair<std::string, unsigned int>,类似这样:

// Here declare what to parse: a string and an uint, separated by a colon
get_vector<std::pair<std::string, unsigned int>>(s);

如何编写一个std::stringstream 操作符来解决问题?

我不知道如何(或者即使)我可以使用getline(我的代码如下)。如果可能的话,我真的很想保留get_vector 函数原样

谢谢!

template <class F, class S>
std::stringstream& operator >> (std::stringstream& in, std::pair<F, S> &out)
{
    in >> out.first >> out.second;
    return in;
}

template <class T>
auto get_vector(std::string s) -> std::vector<T>
{
    std::vector<T> v;

    // Vector of strings
    auto tmp = split(s);

    // Magic
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v),
                   [](const std::string& elem) -> T
                   {
                       std::stringstream ss(elem);
                       T value;
                       ss >> value;
                       return value;
                   });

    return v;
}

【问题讨论】:

  • 所以在您的代码中elem 将是字符串"time:5, length:10"?
  • 当您说要保留 get_vector 函数的原样时,您的意思是声明而不是定义,对吗?
  • @NathanOliver elem 将是 "time:5",因为原始字符串已被拆分为逗号分隔的组件。
  • @ChristianHackl 如果可能的话,我希望它保持原样,这就是为什么我认为运营商是必要的。

标签: c++ c++11 vector stringstream std-pair


【解决方案1】:

您的operator&gt;&gt; 收到一个std::stringstream,其中包含一个类似"time:5" 的字符串。操作员需要通过将字符串拆分为两个标记来解析该字符串,然后将第一个标记转换为F,第二个转换为S

执行此操作的一种方法是将std::getline 与自定义分隔符一起使用。你最终会得到两个std::string 令牌。例如,这些可以转换为两个内部std::istringstreams。

这里有一些代码你可以试试:

template <class F, class S>
std::stringstream& operator >> (std::stringstream& in, std::pair<F, S> &out)
{
    std::string first_token;
    std::string second_token;
    std::getline(in, first_token, ':');
    std::getline(in, second_token);

    std::istringstream first_converter(first_token);
    std::istringstream second_converter(second_token);

    first_converter >> out.first;
    second_converter >> out.second;

    return in;
}

当字符串中没有':' 时,您可能需要添加一些错误处理。


请注意,如果您不想合并输入和输出,则不应使用std::stringstream。大多数时候,你会想要std::istringstreamstd::ostringstream

【讨论】:

    【解决方案2】:

    因为我是英语新手,所以我不确定理解你想要什么。 我开玩笑说@Christian Hackl 做了什么。所以如果这个答案没有 与您想要的内容有关,请告诉我,我会删除它。

    我假设您需要从 stringstream 中提取 string,然后将它们放入包含 @987654322 的 vector @

    假设您有这个字符串也可以作为输入流:
    std::string string( "one:1, two:20, three:300, four:40000, five:500000" );

    有不止一种方法可以做到,但我是这样说的!
    所以首先你需要拆分这个字符串,然后把拆分的内容放入vector of pair

    std::string string( "one:1, two:20, three:300, four:40000, five:500000" );
    
    std::stringstream io_stream;
    
    std::basic_regex< char > regex( ", " );
    std::regex_token_iterator< std::string::const_iterator > last;
    std::regex_token_iterator< std::string::const_iterator > first( string.begin(), string.end(), regex, -1 );
    
    std::vector< std::pair< std::string, std::size_t > > vector_of_pair;
    std::string str_pair( "" );
    std::size_t ui_pair( 0 );
    
    while( first != last ){
        io_stream.clear();
        io_stream.seekg( 0 );
        io_stream.seekp( 0 );
    
        io_stream << *first << '\n';
        std::getline( io_stream, str_pair, ':' );
        // error:
        // no match function to call: stream and int
        // std::getline( io_stream, ui_pair);
        io_stream >> ui_pair;
    
        vector_of_pair.emplace_back( str_pair, ui_pair );
    
        ++first;
    }  
    

    测试

    for( std::size_t index = 0; index < vector_of_pair.size(); ++index ){
        std::cout << vector_of_pair[ index ].first << " and " << vector_of_pair[ index ].second << '\n';
    }
    

    输出

    one and 1
    two and 20
    three and 300
    four and 40000
    five and 500000  
    

    工作原理
    没有难懂的代码。它只是通过std::regex_token_iterator 拆分字符串,然后在 while 循环中将其值发送到is_stream,然后读取该行并将其发送到str_pair , 但这里因为std::getline 没有提取int 类型的功能,所以我使用stringstream 本身的&gt;&gt;,然后将emplace_back 用于向量,仅此而已。

    注意
    对于:
    如何编写一个 std::stringstream 操作符来解决问题?
    我想现在你可以自己做。由于我不确定,所以我没有用operator&gt;&gt; 编写代码。

    【讨论】:

      猜你喜欢
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2021-11-20
      • 2019-02-07
      相关资源
      最近更新 更多