c++ - 从 ostream 获取 char* 而不进行复制

标签 c++ char copy buffer ostream

我有一个ostream并且数据已写入其中。现在我想要 char 数组形式的数据。有没有办法在不复制所有字节的情况下获取字符缓冲区及其大小?我的意思是,我知道我可以使用 ostringstream 并对其调用 str().c_str() ,但这会生成临时拷贝。

最佳答案

我想这就是您正在寻找的 - 一个返回指向其缓冲区的指针的流缓冲区:

#include <iostream>
#include <vector>
#include <string>

class raw_buffer : public std::streambuf
{
public:
    raw_buffer(std::ostream& os, int buf_size = 256);
    int_type overflow(int_type c) override;
    std::streamsize showmanyc() override;
    std::streamsize xsputn(const char_type*, std::streamsize) override; 
    int sync() override;
    bool flush();
    std::string const& str() const;
private:
    std::ostream& os_;
    std::vector<char> buffer;
    std::string aux;
};

现在 str() 很简单。它返回一个指向辅助缓冲区底层缓冲区的指针:

std::string const& raw_buffer::str() const
{
    return aux;
}

其余函数是流缓冲区的常见实现。 showmanyc() 应该返回辅助缓冲区的大小(aux 只是整个缓冲区的运行总和,buffer 另一方面是施工时指定的尺寸)。

例如,这里是 overflow(),它应该同时更新两个缓冲区,但仍将 buffer 视为主缓冲区:

raw_buffer::int_type raw_buffer::overflow(raw_buffer::int_type c) override
{   
    if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
    {
        aux += *this->pptr() = traits_type::to_char_type(c);
        this->pbump(1);

        if (flush())
        {
            this->pbump(-(this->pptr() - this->pbase()));
            this->setp(this->buffer.data(),
                       this->buffer.data() + this->buffer.size());
            return c;
        } 
    }
    return traits_type::eof();
}

flush()用于将buffer的内容复制到流(os_),而sync() 也应该被重写以调用 flush()

xsputn 也需要被重写才能写入 aux:

std::streamsize raw_buffer::xsputn(const raw_buffer::char_type* str, std::streamsize count) override
{
    for (int i = 0; i < count; ++i)
    {
        if (traits_type::eq_int_type(this->sputc(str[i]), traits_type::eof()))
            return i;
        else
            aux += str[i];
    }
    return count;
}

现在我们可以将其与自定义流结合起来:

class raw_ostream : private virtual raw_buffer
                  , public std::ostream
{
public:
    raw_ostream(std::ostream& os) : raw_buffer(os)
                                  , std::ostream(this)
    { }

    std::string const& str() const
    {
        return this->raw_buffer::str();
    }

    std::streamsize count()
    {
        return this->str().size();
    }
};

可以这样使用:

int main()
{
    raw_ostream rostr(std::cout);
    rostr << "Hello, World " << 123 << true << false;

    auto& buf = rostr.str();
    std::cout << buf;
}

关于c++ - 从 ostream 获取 char* 而不进行复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22277960/

相关文章:

c - "Save 38% now"C 字符串中止程序

java - 为什么 if 语句中的表达式顺序很重要

C++从函数调用的多个返回构建字符串 vector 的最佳方法

c++ - 套接字数据的十六进制表示(char)c++

在 C 中将一个数组的元素复制到另一个数组

mysql - 将 MySQL 表合并为一张表

mysql - 将一个表的内容复制到另一个表,其中列内容不同

c++ - 平等测试功能

c++ - 将文件的一部分读入 std::vector<char> 的有效方法?

macos - 如何在 OS X 10.7.3 中复制目录?