如何在不复制的情况下将 std::string 的一部分放入 streambuf 中
How to get part of a std::string into a streambuf without copying?
我最近经常使用boost asio,我发现我正在使用std::string
和asio::streambuf
很多。我发现作为解析网络数据的一部分,我正在尝试在 streambuf
秒和string
秒之间来回获取数据。一般来说,我不想弄乱"格式化io",所以iostream
不是很有用。我发现,虽然ostream::operator<<()
,尽管有官方文档,似乎将我的string
转发到streambuf
不受干扰,但istream::operator>>()
破坏了我streambuf
的内容(正如您所期望的那样,因为它是"格式化的")。
在我看来,标准库确实缺少大量用于处理streambuf
s和string
s以及未格式化io的迭代器和流对象。例如,如果我想将string
的子字符串放入streambuf
中,如何在不创建string
副本的情况下做到这一点?基本的全进全出转移可以像以下方式完成:
// Get a whole string into a streambuf, and then get the whole streambuf back
// into another string
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
os << message;
std::istreambuf_iterator<char> sbit(&sbuf);
std::istreambuf_iterator<char> end;
std::string sbuf_it_wholestr(sbit, end);
cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;
}
指纹:
message=abcdefghijk lmnopqrs tuvwxyz
sbuf_it_wholestr=abcdefghijk lmnopqrs tuvwxyz
如果我想只将streambuf
的一部分放入字符串中,这似乎非常困难,因为istreambuf_iterator
不是随机访问迭代器,也不支持算术:
// Get a whole string into a streambuf, and then get part of the streambuf back
// into another string. We can't do this because istreambuf_iterator isn't a
// random access iterator!
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
os << message;
std::istreambuf_iterator<char> sbit(&sbuf);
// This doesn't work
//std::istreambuf_iterator<char> end = sbit + 7; // Not random access!
//std::string sbuf_it_partstr(sbit, end);
//cout << "sbuf_it_partstr=" << sbuf_it_partstr << endl;
}
而且似乎没有任何方法可以直接使用 string::iterator
将string
的一部分转储到streambuf
中:
// istreambuf_iterator doesn't work in std::copy either
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
std::istreambuf_iterator<char> sbit(&sbuf);
//std::copy(message.begin(), message.begin()+7, sbit); // Doesn't work here
}
如果我不介意格式化io,我总是可以从streambuf
中提取部分string
s,但我这样做 - 格式化io几乎从来都不是我想要的:
// Get a whole string into a streambuf, and then pull it out using an ostream
// using formatted output
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
string part1, part2;
os << message;
os >> part1;
os >> part2;
cout << "part1=" << part1 << endl;
cout << "part2=" << part2 << endl;
}
指纹:
message=abcdefghijk lmnopqrs tuvwxyz
part1=abcdefghijk
part2=lmnopqrs
如果我对丑陋的副本没问题,我可以生成一个子字符串,当然 - std::string::iterator
随机访问......
// Get a partial string into a streambuf, and then pull it out using an
// istreambuf_iterator
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
string part_message(message.begin(), message.begin()+7);
os << part_message;
cout << "part_message=" << part_message << endl;
std::istreambuf_iterator<char> sbit(&sbuf);
std::istreambuf_iterator<char> end;
std::string sbuf_it_wholestr(sbit, end);
cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;
}
指纹:
message=abcdefghijk lmnopqrs tuvwxyz
part_message=abcdefg
sbuf_it_wholestr=abcdefg
stdlib 还有一个奇怪的独立std::getline()
,它可以让您从ostream
中提取单个行:
// If getting lines at a time was what I wanted, that can be accomplished too...
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyzn1234 5678n");
cout << "message=" << message << endl;
os << message;
string line1, line2;
std::getline(os, line1);
std::getline(os, line2);
cout << "line1=" << line1 << endl;
cout << "line2=" << line2 << endl;
}
指纹: message=abcdefghijk lmnopqrs tuvwxyz 1234 5678
line1=abcdefghijk lmnopqrs tuvwxyz
line2=1234 5678
我觉得我错过了一些罗塞塔石碑,如果我发现它,处理std::string
和asio::streambuf
会容易得多。是否应该放弃std::streambuf
界面并利用asio::mutable_buffer
,我可以摆脱asio::streambuf::prepare()
?
-
iStream::operator>>() 破坏了我的 Streambufs 的内容(正如您所期望的那样,因为它是"格式化的")。
使用
std::ios::binary
标志打开输入流并使用is >> std::noskipws
进行操作 -
例如,如果我想将字符串的子字符串放入 streambuf,如何在不创建字符串副本的情况下做到这一点?基本的全进全出转移可以像
尝试喜欢
outstream.write(s.begin()+start, length);
或使用
boost::string_ref
:outstream << boost::string_ref(s).instr(start, length);
-
而且似乎没有任何方法可以直接使用 string::iterators 将字符串的一部分转储到 streambuf 中:
std::copy(it1, it2, ostreambuf_iterator<char>(os));
-
重新解析消息行:
您可以使用
iter_split
拆分为迭代器范围。您可以使用
boost::spirit::istream_iterator
即时解析嵌入式语法
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- C++:如何使函数只返回作为列表一部分的字符串
- 为std::string的某个索引赋值
- std::sort()函数无法对向量的一部分进行排序
- std中有类似find_last_of的函数,而string中没有
- 使用 std::string () const 函数启动线程或未来
- 使用char类型将decimal转换为string,将string转换为decimal
- 迭代和比较映射<字符串、矢量<string>> c++ 中的值
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 将向量解析<string>为字符串
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 如何更改大小(std::string)
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 我可以在循环中引用 std::string 的一部分并将其放在外面吗?
- 是否可以在程序中使用 std::string 作为 if else 语句的一部分
- 多次擦除 std::string 的一部分
- 如何在不复制的情况下将 std::string 的一部分放入 streambuf 中
- 有一对<字符串,字符串>如何找到它是否是map<string,string>中的某个对的一部分?
- 是 std::string 是 STL 的一部分