STL之自定义缓冲区
来源:互联网 发布:python好学么 编辑:程序博客网 时间:2024/05/29 17:56
简介
流缓冲区是一种I/O缓冲区,接口由basic_streambuf定义。针对字符型别char和wchar,标准程序库分别提供预先定义好的流缓冲区(streambuf)和宽字符流缓冲区(wstreambuf)。尤其是在特殊通道上,各类可以当做基类。
- 函数eback(),gptr()和egptr()构成了read(input)缓冲区的界面。
- 函数pbase(),pptr(),epptr()构成了write(output)缓冲区的界面。
pbase()是指output stream缓冲区的起始位置。pptr()是当前写入位置。epptr()是output 缓冲区的结尾。pbase()至pptr()之间的序列字符已被写至相应的输出通道,但未被清空。
输出缓冲区
对于程序员和程序开发者来说,类basic_streambuf仅仅是发送(sent)和提取(extracted)字符的地方。通常有两个公共函数,用于写入字符。
int streambuf::sputc( int nCh );
int streambuf::sputn( const char* pch, int nCount );
函数sputc发生错误时,会返回traits_type::eof()。
成员函数sputc()可用来向缓冲区中写入一个字符,如果当时有一个空的改写位置,字符就会被复制到该位置上。之后,指向当前改写位置的那个指针就会加1。如果缓冲区是空的,就调用虚函数overflow()将output缓冲区的内容发送至对应的输出管道中。
所以,通过重载overflow()函数可以自定义streambuffer。
#include <IOSTREAM>#include <streambuf>#include <LOCALE>#include <CSTDIO>using namespace std;class outbuf : public std::streambuf{protected:virtual int_type overflow(int_type c){if(c != EOF){c = std::toupper(c ,getloc());if(putchar(c) == EOF){return EOF;}}return c;}};void main(){outbuf ob;std::ostream out(&ob);int num = 56;out << "56 十六进制数值: " << std::hex << std::showbase << num << endl;}上面是一个没有缓冲区的demo。因为缓冲区为空,每输出一个字符都会调用一次overflow()函数,在overflow中直接将字符输出。
#include <iostream>#include <io.h>#include <streambuf>#include <cstdio>using namespace std;static const int bufferSize = 10;class outbuf : public std::streambuf{protected:char buffer[bufferSize];//定义一个数组表示缓冲区。public:outbuf(){setp(buffer ,buffer + bufferSize - 1);//设置streambuf对象的缓冲区;}virtual ~outbuf(){sync();//程序退出时,将数组中的残余数据输出至外部设备。}protected:int flushBuffer(){int num = pptr() - pbase();if(write(1 ,buffer , num) != num)//输出。{return EOF;}pbump(-num);//将当前写指针清空,指向缓冲区的开始位置。return num;}virtual int_type overflow(int_type c){/*注意setp(buffer ,buffer + bufferSize - 1),所以pptr()==epptr()的时候,(也就是调用underflow的时候),pptr()指向缓冲区的最后一个位置(数组的最后一个位置)。所以pptr()指向有效内存。*/if(c != EOF){*pptr() = c;pbump(1);//使当前位置指向数组最后一个元素之后。}if(flushBuffer() == EOF){return EOF;}return c;}virtual int sync(){if(flushBuffer() == EOF){return -1;}return 0;}};class fdostream : public std::ostream{protected:outbuf buf;public:fdostream(int fd):ostream(0){rdbuf(&buf);//设置streambuf对象。}};void main(){fdostream out(1);out << "51 hexadecimal: " << std::hex << std::showbase << 51 << endl;}输入缓冲区
函数sgetc()和sbumpc()可以从streambuf中读取一个字符,不同之处是sbumpc()会使当前指针后移,而sgetc()仅返回当前字符。
如果缓冲区为空,就没有可用字符了。缓冲区必须重新补给。如果没有可用字符,函数sbumpc()会调用虚函数uflow(),而uflow()的默认行为是调用underflow(),移动“读取指针”。
需要说明一下的时,eback()返回缓冲区中有效数据的起始位置。epptr()返回缓冲区有效数据末端位置。pptr()返回当前读取位置。这里需要注意的是,eback()并不一定等于pptr(),因为为了支持回退,eback()和pptr()之间存储已经读取过的字符。而epptr()并不一定是缓冲区数组的最后一个元素,因为可能没有从输入设备读取这么多的数据。
在给出demo之前,由于输入缓冲区支持回退,也就是读取指针可以左移,读取之前读取过的字符。所以,在重写函数underflow自定义自己的streambuf时,也需要支持这种特性。
#include <iostream>#include <streambuf>#include <cstring>#include <io.h>using namespace std;static const int bufferSize = 10;static const int maxBackNum = 4;class inbuf : public std::streambuf{protected:char buffer[bufferSize];public:inbuf(){setg(buffer + maxBackNum ,buffer + maxBackNum ,buffer + maxBackNum);}protected:virtual int_type underflow(){if(gptr() < egptr()){return *gptr();}int numputback;numputback = gptr() - eback();if(numputback > maxBackNum)numputback = maxBackNum;memcpy(buffer + maxBackNum - numputback ,gptr() - numputback ,numputback);int num ;num = read(0 ,buffer + maxBackNum ,bufferSize - maxBackNum);if(num < 0)return EOF;setg(buffer + (maxBackNum - numputback) ,buffer + maxBackNum ,buffer + maxBackNum + num);return *gptr();}};void main(){inbuf ib;std::istream in(&ib);char c;for(int i = 1 ;i <= 20 ;i++){in.get(c);cout << c << flush;if(i == 8){in.unget();in.unget();}}cout << endl;}
- STL之自定义缓冲区
- STL之缓冲区迭代器
- C++之自定义的output缓冲区
- 自定义缓冲区
- STL之Set自定义排序
- STL函数对象之自定义函数对象
- 自定义字符流缓冲区
- 自定义字节缓冲区
- C++自定义缓冲区streambuf
- 自定义字节流缓冲区
- 自定义一个缓冲区的大小
- STL set 用法之 —— 自定义结构体
- 黑马程序员之缓冲区
- D3D之索引缓冲区
- linux之缓冲区
- Java NIO 之缓冲区
- Java NIO 之缓冲区
- AE#GP之缓冲区
- OD脚本脱壳
- 【转】自制嗡嗡闹钟
- 网络获取北京时间和系统时间
- jquery动态添加验证规则
- Unityios开发--Unity bundle的制作和使用
- STL之自定义缓冲区
- eclipse安装插件常用的一种方法
- spring 集成shiro 之 自定义过滤器
- DataSource
- C++字符串转化为数字的库函数
- SAX与DOM的比较
- java基础与基础加强反射/注解
- PopUp下半透明叠加层的简单设置
- Oracle的几种常见的人机交互命令