在 sending/getting 结构时使用 streambuf
Using streambuf when sending/getting struct
我正在研究 boost::asio::streambuf
并发现我可以 send/get 使用它的结构,但是当我发送结构时,我无法在发送时得到它。文档说应该使用commit()
和consume()
,但是我应该在哪里使用它们呢?
struct person
{
int m_id;
std::string m_message;
};
std::istream& operator>>(std::istream& in, struct person& p)
{
return in >> p.m_id >> p.m_message;
}
std::ostream& operator<<(std::ostream& out, struct person& p)
{
return out << p.m_id << " " << p.m_message;
}
int main()
{
boost::asio::streambuf buf;
std::ostream out(&buf);
person p;
p.m_id = 1;
p.m_message = "Hello World!";
out << p;
std::istream in(&buf);
person p1;
in >> p1;
cout << "ID: " << p1.m_id << endl;
cout << "Message: " << p1.m_message << endl;
return 0;
}
问题出在字符串上,所以当我只输入 "hello"(没有世界)时,它工作正常,但如果我添加 "world!",如上所示,它只是看不到添加的 "world!",为什么?
来自 http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt(强调和省略我的):
2) ... reads characters from is and appends them to str ... until one
of the following conditions becomes true:
- ...
- ...
- std::isspace(c,is.getloc()) is true for the next character c in is (this whitespace character remains in the input stream). ...
基本上这意味着如果您使用 operator >>
从 istream
中提取字符串,它会在空格处停止。
如果您想将流中的所有内容都放入您的字符串中,有很多问题会问(例如 this one or this one)。
有很多问题。
首先,尽可能使参数const&
:
std::ostream &operator<<(std::ostream &out, person const &p) {
其次,确保流刷新到缓冲区。我认为限制 ostream
或 istream
实例
的生命周期是个好习惯
第三,选择一种稳健的格式。当你有 m_id = 1
和 m_message = "123"
时,你的样本已经有更大的问题(你能看到吗?)。
在文本格式中,您需要固定长度的字段或定界协议。让我们修复它:
std::ostream &operator<<(std::ostream &out, person const &p) {
return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message;
}
现在回读时,您会发现自己需要更加精确:
std::istream &operator>>(std::istream &in, person &p) {
char separator;
size_t length;
bool ok = in >> p.m_id
&& in >> separator && separator == ';'
&& in >> length
&& in >> separator && separator == ';'
;
if (ok) {
p.m_message.resize(length);
in.read(&p.m_message[0], length);
p.m_message.resize(in.gcount());
}
// ensure the expected number of bytes were read
ok = ok && (p.m_message.length() == length);
if (!ok)
in.setstate(std::ios::failbit);
return in;
}
哎呀。真的吗?对真的。至少!
做错误处理
完整演示
#include <boost/asio.hpp>
#include <iostream>
struct person {
int m_id;
std::string m_message;
};
std::ostream &operator<<(std::ostream &out, person const &p) {
return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message;
}
std::istream &operator>>(std::istream &in, person &p) {
char separator;
size_t length;
bool ok = in >> p.m_id
&& in >> separator && separator == ';'
&& in >> length
&& in >> separator && separator == ';'
;
if (ok) {
p.m_message.resize(length);
in.read(&p.m_message[0], length);
p.m_message.resize(in.gcount());
}
// ensure the expected number of bytes were read
ok = ok && (p.m_message.length() == length);
if (!ok)
in.setstate(std::ios::failbit);
return in;
}
int main() {
boost::asio::streambuf buf;
std::ostream(&buf) << person{ 1, "Hello World!" };
person received;
if (std::istream(&buf) >> received) {
std::cout << "ID: " << received.m_id << std::endl;
std::cout << "Message: " << received.m_message << std::endl;
} else {
std::cout << "Couldn't receive person\n";
}
}
版画
ID: 1
Message: Hello World!
奖金
C++14 添加std::quoted
:
#include <iomanip>
std::ostream &operator<<(std::ostream &out, person const &p) { return out << p.m_id << std::quoted(p.m_message); }
std::istream &operator>>(std::istream &in, person &p) { return in >> p.m_id >> std::quoted(p.m_message); }
在这种情况下,也可以完成以下工作:Live On Coliru
我正在研究 boost::asio::streambuf
并发现我可以 send/get 使用它的结构,但是当我发送结构时,我无法在发送时得到它。文档说应该使用commit()
和consume()
,但是我应该在哪里使用它们呢?
struct person
{
int m_id;
std::string m_message;
};
std::istream& operator>>(std::istream& in, struct person& p)
{
return in >> p.m_id >> p.m_message;
}
std::ostream& operator<<(std::ostream& out, struct person& p)
{
return out << p.m_id << " " << p.m_message;
}
int main()
{
boost::asio::streambuf buf;
std::ostream out(&buf);
person p;
p.m_id = 1;
p.m_message = "Hello World!";
out << p;
std::istream in(&buf);
person p1;
in >> p1;
cout << "ID: " << p1.m_id << endl;
cout << "Message: " << p1.m_message << endl;
return 0;
}
问题出在字符串上,所以当我只输入 "hello"(没有世界)时,它工作正常,但如果我添加 "world!",如上所示,它只是看不到添加的 "world!",为什么?
来自 http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt(强调和省略我的):
2) ... reads characters from is and appends them to str ... until one of the following conditions becomes true:
- ...
- ...
- std::isspace(c,is.getloc()) is true for the next character c in is (this whitespace character remains in the input stream). ...
基本上这意味着如果您使用 operator >>
从 istream
中提取字符串,它会在空格处停止。
如果您想将流中的所有内容都放入您的字符串中,有很多问题会问(例如 this one or this one)。
有很多问题。
首先,尽可能使参数
const&
:std::ostream &operator<<(std::ostream &out, person const &p) {
其次,确保流刷新到缓冲区。我认为限制
ostream
或istream
实例 的生命周期是个好习惯
第三,选择一种稳健的格式。当你有
m_id = 1
和m_message = "123"
时,你的样本已经有更大的问题(你能看到吗?)。在文本格式中,您需要固定长度的字段或定界协议。让我们修复它:
std::ostream &operator<<(std::ostream &out, person const &p) { return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message; }
现在回读时,您会发现自己需要更加精确:
std::istream &operator>>(std::istream &in, person &p) { char separator; size_t length; bool ok = in >> p.m_id && in >> separator && separator == ';' && in >> length && in >> separator && separator == ';' ; if (ok) { p.m_message.resize(length); in.read(&p.m_message[0], length); p.m_message.resize(in.gcount()); } // ensure the expected number of bytes were read ok = ok && (p.m_message.length() == length); if (!ok) in.setstate(std::ios::failbit); return in; }
哎呀。真的吗?对真的。至少!
做错误处理
完整演示
#include <boost/asio.hpp>
#include <iostream>
struct person {
int m_id;
std::string m_message;
};
std::ostream &operator<<(std::ostream &out, person const &p) {
return out << p.m_id << ";" << p.m_message.length() << ";" << p.m_message;
}
std::istream &operator>>(std::istream &in, person &p) {
char separator;
size_t length;
bool ok = in >> p.m_id
&& in >> separator && separator == ';'
&& in >> length
&& in >> separator && separator == ';'
;
if (ok) {
p.m_message.resize(length);
in.read(&p.m_message[0], length);
p.m_message.resize(in.gcount());
}
// ensure the expected number of bytes were read
ok = ok && (p.m_message.length() == length);
if (!ok)
in.setstate(std::ios::failbit);
return in;
}
int main() {
boost::asio::streambuf buf;
std::ostream(&buf) << person{ 1, "Hello World!" };
person received;
if (std::istream(&buf) >> received) {
std::cout << "ID: " << received.m_id << std::endl;
std::cout << "Message: " << received.m_message << std::endl;
} else {
std::cout << "Couldn't receive person\n";
}
}
版画
ID: 1
Message: Hello World!
奖金
C++14 添加std::quoted
:
#include <iomanip>
std::ostream &operator<<(std::ostream &out, person const &p) { return out << p.m_id << std::quoted(p.m_message); }
std::istream &operator>>(std::istream &in, person &p) { return in >> p.m_id >> std::quoted(p.m_message); }
在这种情况下,也可以完成以下工作:Live On Coliru