在发送/获取结构时使用 streambuf

Using streambuf when sending/getting struct

本文关键字:streambuf 结构 获取      更新时间:2023-10-16

我正在研究boost::asio::streambuf,发现我可以使用它发送/获取结构,但是当我发送结构时,我无法像发送它一样获取它。文档说应该使用 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!",为什么?

存在许多问题。

  1. 首先,尽可能const&参数:

    std::ostream &operator<<(std::ostream &out, person const &p) {
    
  2. 其次,确保流刷新到缓冲区。我认为限制ostreamistream实例的生命周期是一种很好的做法

  3. 第三,选择一种强大的格式。当你有m_id = 1m_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;
    }
    

    伊克斯。真?是的,真的。至少!

  4. 执行错误处理

完整演示

住在科里鲁

#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 personn";
    }
}

指纹

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); }

在这种情况下,这也完成了这项工作:住在科里鲁

从 http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt(强调和省略号我的(:

2( ...从 IS 读取字符并将其附加到 str ...直到一个 以下条件变为真:

  • std::isspace(c,is.getloc((( 对于 is 中的下一个字符 c 为 true(此空格字符保留在输入流中(。

基本上这意味着,如果您使用operator >>istream中提取字符串,它将在空格处停止。

如果你想把流中的所有内容都放到你的字符串中,有很多问题要问(比如这个或这个(。