对和字符串流
Pairs and stringstream
在 中,我问过如何读取字符串向量并将其轻松转换为整数或双精度向量。
现在我将该简单类型的向量扩展为 对 类型的向量(考虑 int
、double
,甚至 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::istringstream
s.
您可以尝试以下代码:
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::istringstream
或 std::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.
我假设你需要从 string 或 stream 中提取一个 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>>
。
在
现在我将该简单类型的向量扩展为 对 类型的向量(考虑 int
、double
,甚至 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::istringstream
s.
您可以尝试以下代码:
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::istringstream
或 std::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.
我假设你需要从 string 或 stream 中提取一个 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>>
。