c++11 标准模板(STL)(std::basic_stringbuf)(五)

定义于头文件 <sstream>
template<

    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>

> class basic_stringbuf : public std::basic_streambuf<CharT, Traits>

std::basic_stringbuf 是关联字符序列为内存常驻的任意字符序列的 std::basic_streambuf 。能从 std::basic_string 的实例初始化它,或将它做成该类的实例。

std::basic_stringbuf 的典型实现保有一个 std::basic_string 类型对象,或等价的可伸缩序列容器作为数据成员,并将它同时用作受控制字符序列(为 std::basic_streambuf 的六个指针所指向的数组)和关联字符序列(所有输入操作的字符源和输出操作的目标)。

另外,典型的实现保有一个 std::ios_base::openmode 类型的数据成员,以指示流的状态(只读、只写、读写、尾端写等)。

若 overflow() 使用过分配策略,则可存储另外的高水位指针,以跟踪最后初始化的字符。(C++11 起)

亦提供二个对常用字符类型的特化:

类型定义
stringbufbasic_stringbuf<char>
wstringbufbasic_stringbuf<wchar_t>


受保护成员函数

回放字符到输出序列中

std::basic_stringbuf<CharT,Traits,Allocator>::pbackfail

protected:
virtual int_type pbackfail( int_type c = Traits::eof() )

 此受保护虚函数为公开函数 basic_streambuf::sungetc 和 basic_streambuf::sputbackc 所调用(转而为 basic_istream::unget 和 basic_istream::putback 所调用)。

1) 调用方要求获取区后备一个字符(以无参数或以 Traits::eof() 为参数调用 pbackfail()

a) 首先,检查是否有回放位置,而若确实无回放位置则失败( stringbuf 无重读用的外部字符序列)

b) 若调用方错误而回放位置实际上可用,则简单地自减 basic_streambuf::gptr() ,例如以调用 gbump(-1) 。

2) 调用方试图回放的字符异于之前取得者(以要需要放回的字符调用 pbackfail() ),该情况下

a) 首先,检查是否有回放位置,若无则失败。

b) 然后检查会放位置中有什么字符。若其处保有的字符已等于 c ,以 Traits::eq(to_char_type(c), gptr()[-1]) 确定,则简单地自减 basic_streambuf::gptr() 。

c) 否则,若缓冲区仅为读取打开,则失败。

d) 否则,若缓冲区为写入打开( mode && std::ios_base::out 非零),则自减 basic_streambuf::gptr() 并写入 c 到调整后的 gptr() 所指向的位置。

参数

c-要返回的字符,或若要求指示获取区的后备则为 Traits::eof()

返回值

成功时为 c ,除非 c 为 Traits::eof() ,该情况下返回 Traits::not_eof(c) 。

失败时为 Traits::eof() 。

调用示例

#include <sstream>
#include <string>
#include <iostream>

//  typedef basic_stringbuf<char> 	stringbuf;
struct mybuf : std::stringbuf
{
    mybuf(const std::string& new_str,
          std::ios_base::openmode which =
              std::ios_base::in | std::ios_base::out)
        : std::stringbuf(new_str, which) {}

    int_type pbackfail(int_type c) override
    {
        std::cout << "Before pbackfail(): get area size is "
                  << egptr() - eback() << ' '
                  << " put area size is "
                  << epptr() - pbase() << std::endl;

        int_type ch = std::stringbuf::pbackfail(c);

        std::cout << "After pbackfail(): get area size is "
                  << egptr() - eback() << ' '
                  << " put area size is "
                  << epptr() - pbase() << std::endl;

        if (ch == EOF)
        {
            std::cout << "pbackfail() returns EOF\n";
        }
        else
        {
            std::cout << "pbackfail() returns '"
                      << char(ch) << "'" << std::endl;
        }

        return ch;
    }
};

int main()
{
    mybuf sbuf("12345"); // 读写流

    sbuf.sungetc();
    std::cout << std::endl;
    sbuf.sputbackc('5');
    return 0;
}
输出

 

后附字符到输出序列

std::basic_stringbuf<CharT,Traits,Allocator>::overflow

protected:
virtual int_type overflow ( int_type c = Traits::eof() );

后附字符 c 到输出字符序列。

c 为文件尾指示器( traits::eq_int_type(c,traits::eof()) == true ),则不后附字符。函数不做任何操作并返回异于 traits::eof() 的未指定值。

否则,若输出序列拥有可用写位置,或若此函数成功令一个写位置可用,则调用 sputc(c) 并返回 c

若 stringbuf 为输出打开( mode & ios_base::out) != 0 ),则此函数能令写位置可用:此情况下,它重分配(或在最初分配)足够大的缓冲区,以保有整个当前缓冲区加上至少一个字符。若 stringbuf 亦为输入打开( (mode & ios_base::in) != 0 ),则 overflow 亦会通过移动 egptr() 到指向恰好越过新放置区的位置,来增加获取区的大小。

参数

c-要存储于放置区的字符

返回值

若失败则为指示失败的 Traits::eof() 。若成功后附字符 c 则为 c 。或若以 Traits::eof() 为参数调用,则为某异于 Traits::eof() 的值。

注意

此函数异于典型的 overflow() ,后者移动缓冲区的内容到关联字符序列,因为 std::basic_stringbuf 的缓冲区和关联序列是同一序列。

调用示例

#include <sstream>
#include <string>
#include <iostream>

//  typedef basic_stringbuf<char> 	stringbuf;
struct mybuf : std::stringbuf
{
    mybuf(const std::string& new_str,
          std::ios_base::openmode which =
              std::ios_base::in | std::ios_base::out)
        : std::stringbuf(new_str, which) {}

    int_type overflow(int_type c = EOF) override
    {
        std::cout << "stringbuf::overflow('"
                  << char(c) << "') called" << std::endl
                  << "Before: size of get area: "
                  << egptr() - eback() << std::endl
                  << "        size of put area: "
                  << epptr() - pbase() << std::endl;

        int_type ret = std::stringbuf::overflow(c);

        std::cout << "After : size of get area: "
                  << egptr() - eback() << std::endl
                  << "        size of put area: "
                  << epptr() - pbase() << std::endl;

        return ret;
    }
};

int main()
{
    std::cout << "read-write stream:" << std::endl;
    mybuf sbuf("   "); // 只读流
    std::iostream stream(&sbuf);
    stream << 1234;
    std::cout << sbuf.str() << std::endl;

    std::cout << std::endl << "read-only stream:" << std::endl;
    mybuf ro_buf("   ", std::ios_base::in); // 只读流
    std::iostream ro_stream(&ro_buf);
    ro_stream << 1234;

    std::cout << std::endl << "write-only stream:" << std::endl;
    mybuf wr_buf("   ", std::ios_base::out); // 只写流
    std::iostream wr_stream(&wr_buf);
    wr_stream << 1234;

    return 0;
}
 输出

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值