对和字符串流

Pairs and stringstream

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

现在我将该简单类型的向量扩展为 类型的向量(考虑 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;
}

您的 operator>> 收到一个 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.

Because I am new in English I am not sure to understand what you want. I jest seeing that @Christian Hackl do what. So if this answer does not relate to what you want please tell me and I will delete it.

我假设你需要从 stringstream 中提取一个 string 然后把他们变成一个 vector 包含一个 std::pair< std::string, std::size_t >

假设这个字符串也可以是 input-stream:
std::string string( "one:1, two:20, three:300, four:40000, five:500000" );

方法不止一种,我是这样说的!
所以首先你需要拆分这个字符串,然后将拆分后的内容放入的向量中。

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 本身的 >>,然后 emplace_back 到向量,就是这样。

注意
对于:
我怎样才能编写一个 std::stringstream 运算符来实现这个目的?
我想现在你可以自己做。由于我不确定,所以我没有写代码 operator>>