C++的I/O(vc版)(三)

c++ 专题 1:IO stream 总结介绍 c++ IO steam 的一些基本概念 阅读详情

  前面已经分析完ios_base类了,现在来分析一下basic_ios<>类,他是依赖于字符特性的流基类,首先明确什么是字符特性?就是与字符类型有关的特性,例如填充符,文件结束符。两个字符之间如何比较大小等等诸如此类的问题:

//此处为了简洁,将许多别文件的定义搬到此文件
typedef int _Mbstatet;
typedef fpos<_Mbstatet> streampos;
typedef streampos wstreampos;
#define EOF (-1)//原本定义于stdio.h
//下面是类char_traits的定义
//不同的字符集,不同的表述,都给string和I/O带来了变数,例如面对不同的表述。enf-of-file
//值和字符比较细节不同,具体说明见《c++标准程序库》P687-689
template<class _Elem,class _Int_type>
struct _Char_traits
{ //properties of s string or stream element
	/*关于char_type和int_type的说明见《c++标准程序库》P688,我们用char_type来表示字符,用char_type以外
	  的值表示end-of-file,例如char表示字符,int值表示结尾符,即int_type足以容纳‘end-of-file’*/
	typedef _Elem char_type;
	typedef _Int_type int_ype;
	typedef streampos pos_type;
	typedef streamoff off_type;

	static int compare(const _Elem* _first1,const _Elem* _first2,size_t _count)
	{//compare [_first1,_first1+_count)with [_first2,_first2+...)
		for(;0<_count;--_count,++_first1,++_first2)
			if(!eq(*_first1,*_first2))
				return (It(*_first1,*_first2)?-1:+1);
		return (0);
	}
	static size_t length(const _Elem* _first)
	{//find length of null-terminated sequence
		size_t _count;
		for(_count=0;!eq(*_first,_Elem());++_first)
			++_count;
		return(_count);
	}
	static _Elem* copy(_Elem* _first1,const _Elem* _first2,size_t _count)
	{//copy[_first1,_first1+_count) to [_first2,..)
		//首先测试_first2有足够的空间
		return(copy(_first,_first2,_count));
	}
	static const _Elem* find(const _Elem* _first,size_t _count,const _Elem& ch)
	{//look for _ch in[_first,_first+_count)
		for(;0<_count;--_count,++first)
			if(eq(*_first,_ch))
				return(_first);
		return(0);
	}
	static _Elem* move(_Elem*_first1,const _Elem* _first2,size_t _count)
	{
		_Elem* _next=_first1;
		if(_first2<_next &&_next<_first2+_count)
			for(_next+=_count,_first2+=_count;0<_count;--_count)
				assign(*--)next,*--_first);
		else
			for(;0<_count;--_count,++_next,+__first)
				assign(*_next,*_first2);
		return(_first1);
	}
	static _Elem* assign(_Elem *_first,size_t _count, _Elem _ch)
		{	// assign _Count * _Ch to [_First, ...)
		_Elem *_next = _first;
		for (; 0 < _count; --_count, ++_next)
			assign(*_next, _ch);
		return (_first);
		}

	static void  assign(_Elem& _left, const _Elem& _right)
		{	// assign an element
		_left = _right;
		}
	static bool eq(const _Elem* _left,const _Elem* _right)
	{//test for element equality
		return(_left==_right);
	}
	static bool It(const _Elem& _left,const _Elem* _right)
	{//test if _left precedes _right
		return(_left<_right);
	}
	static _Elem to_char_type(const int_type& _meta)
	{//convert metacharacter to character
		return(static_cast<_Elem>(_meta));
	}
	static int_type to_int_type(const _Elem& ch)
	{//convert metacharacter to character
		return (static_cast<int_type>(ch));
	}
	static bool eq_int_type(const int_type& _left,const int_type* _right)
	{//test for metacharacter equality
		return (_left==_right);
	}
	static int_type not_eof(const int_type& _meta)
	{//如果不是eof,返回原值,如果是eof,返回任意不是eof的值
		return(_meta!=eof()?static_cast<int_type>(_meta):static_cast<int_type>(!eof()));
	}
	static int_type eof()
	{//return end_of-file metacharacter
		return(static_cast<int_type>(EOF);
	}
};
//下面是char_traits
template<class _Elem>
struct char_traits :public _Char_traits<_Elem,long>
{
};
//下面是char_traits<char>,char_traits<wchar_t>,char_traits<unsigned short>特化版本,unsigned short 等同于wchar_t
//特化版本中出于效率方面的考虑,copy函数使用memcpy和wmemcpy等等,这里就不写了

我们基于上述的字符特性类,给出basic_ios<>,下面是一些使用到的类型名:

	typedef basic_ios<_Elem,_Traits> _Myt;
	typedef basic_ostream<_Elem,_Traits> _Myos;
	typedef basic_streambuf<_Elem,_Traits> _Mysb;
	typedef ctype<_Elem> _Ctype;
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef typename _Traits::int_type int_type;
	typedef typename _Traits::pos_type pos_type;
	typedef typename _Traits::off_type off_type;

basic_ios<>中多了三个数据成员:

	_Mysb* _mystrbuf;//pointer to stream buffer
	_Myos* _tiestr;//pointer to tied output stream
	_Elem _fillch;//the fill character

分别是关联的缓冲类,和关联的outstream,这样的话在流执行输入输出操作之前,outstream会先刷新自己的缓冲区。还有填充字符。

为什么把这三个数据放到basic_ios<>中呢?因为这三个数据都是与字符特性有关的数据。

多了这三个数据,我们就得把一些ios_base中的操作重载,以包容这三个数据:

template<class _Elem,class _Traits>
class basic_ios :public ios_base
{//base class for basic_istream/basic_ostream
public:
	typedef basic_ios<_Elem,_Traits> _Myt;
	typedef basic_ostream<_Elem,_Traits> _Myos;
	typedef basic_streambuf<_Elem,_Traits> _Mysb;
	typedef ctype<_Elem> _Ctype;
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef typename _Traits::int_type int_type;
	typedef typename _Traits::pos_type pos_type;
	typedef typename _Traits::off_type off_type;
private:
	_Mysb* _mystrbuf;//pointer to stream buffer
	_Myos* _tiestr;//pointer to tied output stream
	_Elem _fillch;//the fill character
public:
	explicit basic_ios(_Mysb* _strbuf)
	{//construct from stream buffer pointer
		init(_strbuf);
	}
	virtual ~basic_ios()
	{
	}
	//iostate与io_state的不同
	void clear(iostate _state=goodbit,bool _reraise=false)
	{//set state ,possibly reraise exception
		ios_base::clear((iostate)(_mystrbuf==0?(int)_state|(int)badbit :(int)_state),_reraise);
	}
	void clear(io_state _state)
	{
		clear((iostate)_state);
	}
	//只有state非good时才设置
	void setstate(iostate _state,bool _reraise =false)
	{
		if(_state!=goodbit)
			clear((iostate)((int)rdstate()|(int)_state),_reraise);
	}
	void setstate(io_state _state)
	{
		setstate((iostate)_state);
	}
	//从流中复制所有格式定义
	_Myt& copyfmt(const _Myt& _right)
	{
		_tirstr=_right.tie();
		_fillch=_right.fill();
		ios_base::copyfmt(_right);
		return(*this);
	}

	_Myos* tie() const
	{//return tie pointer
		return (_tiestr);
	}
	_Myos* tie(_Myos* _newtie)
	{//set tie pointer
		_Myos* _oldtie=_tiestr;
		_tiestr=_newtie;
		return(_oldtie);
	}

	_Mysb* rdbuf() const
	{//return stream buffer pointer
		return(_mystrbuf);
	}
	_Mysb* rdbuf(_Mysb* _strbuf)
	{//set stream buffer pointer
		_Mysb* _oldstrbuf=_mystrbuf;
		_mystrbuf=_strbuf;
		clear();//记得要清空状态
		return(_oldstrbuf);
	}
	locale imbue(const locale& _loc)
	{//set locale to argument
		locale _oldlocale=ios_base::imbue(_loc);
		if(rdbuf()!=0)
			rdbuf->pubimbue(_loc);
		return (_oldlocale);
	}
	_Elem fill() const
	{//return fill character
		return (_fillch);
	}
	_Elem fill(_Elem _newfill)
	{//set fill character
		_Elem _oldfill=_fillch;
		_fillch=_newfill;
		return(_oldfill);
	}
	char narrow(_Elem _ch,char _dflt='\0')const
	{//convert _ch to byte using imbued locale
		//这里跟字符特性,字符格式有关,由locale解决
		const _Ctype& _Ctype_fac=_USE(getloc(),_Ctype);
		return (_Ctype_fac.narrow(_ch,_dflt));
	}
	_Elem widen(char _byte) const
	{
		const _Ctype& _Ctype_fac=_USE(getloc(),_Ctype);
		return (_Ctype_fac.widen(_byte));
	}
	void swap(_Myt& _right)
	{//swap all but edbuf() with right
		ios_base::swap(_right);
		swap(_fillch,_right._fillch);
		swap(_tiestr,_right._tiestr);
	}
	void set_rdbuf(_Mysb* _strbuf)
	{
		_mystrbuf=_strbuf;
	}
protected:
	void init(_Mysb* _strbuf=0,bool _lsstd=false)
	{//initialize with stream buffer pointer
		_Init();//initialize ios_base
		_mystrbuf=_strbuf;
		_tiestr=0;
		_fillch=widen(' ');
		if(_mystrbuf==0)
			setstate(badbit);
		if(_lsstd)
			_Addstd(this);//specail handling for standard stream
	}
	basic_ios()
	{
	}
private:
	basic_ios(const _Myt&);//not defined not allowed
	_Myt& operator=(const _Myt&);
};

上述是其部分代码,主体内容跟ios_base相似,大部分函数都是调用ios_base的成员,只是我们需要考虑的是:缓冲类;具体的考虑在代码中已经很清楚了。


我们的基本的流类已经完成了,对于特定的流类,只需要加上特定的操作或数据成员即可。



C++的I/O(vc版)(四) 下面进行我们的第二大类,流缓冲类。stream并不负责写或者读,毕竟如它原本的目的一样:负责格式化,存储格式化信息;当然我们还用它存储状态信息等等。stream把它的读写工作转交给stream buffer,即缓冲区类。 缓冲区类主要是围绕着位置展开操作,下面先介绍一个与位置有关的类: /*fpos:它可以存储还原任何流中的任意文件的位置指示器所需的所有信息 * 对象的类 fpos 阅读详情

相关推荐

c++builder调用VC的dll以及VC调用c++builder的dll

解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式。 比如说__cdecl,它是标准的c方法的堆栈调用方式,就是在函数调用时的参数压入堆栈是与函数的声明顺序相反的,其它两个可以看MSDN,不过这个对我们编程没有太大的作用 ------------------------------------------

6700

C++ 基础: std::string

std::string 快速上手

Mr.Sugarcane 1万+

使你的C/C++代码支持Unicode

使你的C/C++代码支持Unicode

jhfyuf的博客 4680

C++ Traits技术

要想深入的理解STL的迭代器、分配器等,就必须了解C++模板编程中的一个技巧——Traits。 1、问题的提出 C++的模板特性为泛型编程提供了支持。这样我们就可以编写更加通用的代码,而不必过分去关心参数的类型。然而事实却是,类型的不同,很多时候却影响到了算法中的某个小小的实现。举个标准库里的类string,wstring。 其实它们对应的是两个模板,前者单字符,后者宽字符。 ...

weixin_30809173的博客 408

VC/C++实现TXT到DAT文件转换的源代码

本文还有配套的精品资源,点击获取 简介:在IT行业中,文件格式转换是一个常见任务,特别是在文本数据处理方面。本文详细介绍了如何通过VC/C++编程语言实现从TXT文本文件到DAT数据文件的转换。此转换流程包括读取TXT文件内容、数据预处理、创建并写入DAT文件等步骤。在VC/MFC环境中,还可以利用MFC库简化文件操作,并创建图形用户界面。 1. 文件格式转换基础...

weixin_35649491的博客 1314

高效处理大文件的重叠I/O VC++源代码解析

OVERLAPPED结构体是Windows平台上用于处理异步I/O请求的一种数据结构。它允许应用程序在文件操作(如读取和写入)进行的同时,继续执行其他任务。在本章节中,我们详细讨论了OVERLAPPED结构体的介绍、在重叠I/O中的应用,以及处理超大文件和错误管理的高级技巧。在Windows平台开发中,合理利用OVERLAPPED结构体能够有效提升应用程序的性能和效率。在接下来的章节中,我们将继续探讨如何在VC++中实现重叠I/O,以及WinAPI中CreateFileReadFile。

weixin_33193177的博客 769

istream头文件

istream是什么 支持以信息流的格式输入 istream怎么用 单用istream很难用,建议用iostream #include<istream> using namespace std; int a; int main(){ //输入 cin>>a; return 0; } istream缺失 在C:\Program Files (x86)\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.

m0_68927910的博客 1269

RTL8306MB交换芯片驱动开发避坑指南:从硬件接线到SDK移植全流程解析

本文详细解析了RTL8306MB交换芯片驱动开发的全流程,重点从硬件接线、SDK移植到实战调试。针对RMII模式下的常见问题,特别是TXEN与RXDV信号交叉连接等关键“坑点”,提供了清晰的排查指南和解决方案,旨在帮助嵌入式工程师高效完成网络设备开发。

278

C/C++开发,无可避免的字符串(篇一).字节数组

C/C++开发,无可避免的字符串(篇一).字节数组。标准库实现字符串功能主要是通过类似于std::vector容器的std::basic_string类模板实现的,该模板提供了针对各种字符型号的特化类,如using std::string = std::basic_string;博文还阐述了std::basic_string—_view、空终止字节字符串、空终止宽字符串、空终止多字节字符串等功能函数集,并给出演示代码。

技术需要分享 1858

碳纳米管NRAM:突破5纳米制程的下一代存储技术

在半导体存储领域,非易失性存储器和随机存取存储器是两大基础技术方向。传统DRAM速度快但断电易失,NAND Flash非易失但写入慢、寿命有限,两者在先进制程下都面临物理极限挑战。碳纳米管作为一种新型纳米材料,凭借其优异的导电性、机械强度和尺寸微缩潜力,为存储技术革新提供了物理基础。基于碳纳米管的NRAM技术,通过控制纳米管间的可逆接触实现电阻状态切换,兼具DRAM级速度和Flash的非易失性,同时具备近乎无限的擦写寿命和出色的CMOS工艺兼容性。这项技术不仅能满足5纳米以下制程的存储需求,在数据中心缓存、

weixin_42576804的博客 427

瑞萨RA6M4平台I2C驱动移植实战:MPU6050传感器集成指南

本文详细介绍了在瑞萨RA6M4平台上进行I2C驱动移植并集成MPU6050传感器的实战指南。通过FSP配置工具添加I2C主栈,适配MPU6050官方驱动,实现传感器数据读取与调试,为嵌入式开发提供完整的解决方案。

banana的博客 109

Linux C\C++方式下的文件I/O编程

在旧头文件里的fstream.h,如果使用ifstreamfile的默认参数声明一个输入文件流,当这个要读的file文件不存在时,会自动创建一个空文件,从而给判断文件是否存在造成了很多麻烦。因为C++兼容C,所以C中的输入输出函数依然可以在C++中使用,但是很显然,直接把C的那套输入输出搬到C++中肯定无法满足C++的需求,更重要的一点是,C中的输入输出有类型要求,只支持基本类型,因此C++设计了易于使用的并且多种输入输出流接口统一的I/O类库,并且支持多种格式化操作,还可以自定义格式化操作。

夏天又到了的专栏 3182

学Simulink——基于Simulink的输入-输出线性化精确转矩控制

本文详细介绍了基于Simulink的永磁同步电机(PMSM)输入-输出线性化(IOL)精确转矩控制方法。针对传统解耦控制在非线性转矩特性下的局限性,提出通过精确反馈线性化实现转矩指令与实际转矩的严格线性关系。文章系统阐述了IOL原理、PMSM控制器推导过程,并提供了完整的Simulink建模步骤,包括电机模型搭建、IOL控制器实现和闭环系统构建。通过仿真对比验证了IOL方法在转矩跟踪精度、动态响应和参数鲁棒性方面的显著优势,最后讨论了工程实现要点和扩展应用方向。该方法为高性能伺服系统开发提供了有效解决方案。

amy_mhd的博客 60

c++的I/O(vc版)(一)

c++的I/O是我们最常用的库之一,也是操作复杂,功能复杂的类库之一。  在C++的程序中,很少有不用I/O的程序,但是,对于我来说,I/O我却用的出奇的差,只会几个简单的函数,尽管够用,但是却用的效率奇低,于是,在此学习c++ I/O类库的使用方法。 首先是I/O中流的概念,c++的I/O中的所有的操作都是基于流。 流i/o:要传递的数据是无结构的字节流,字符流或者任意同等大小单位

wangyanphp的专栏 1212

22、常见加密哈希算法及安全机制解析

本文详细解析了多种常见加密哈希算法,包括SHA系列、RIPEMD、Tiger、HAVAL、Whirlpool等,涵盖其工作原理、安全性与性能对比。同时探讨了哈希攻击方式如预映像攻击和彩虹表,并介绍了盐、MAC、HMAC等防御机制。结合密码存储、消息完整性验证及区块链应用案例,分析了不同场景下的算法选择建议,并展望了哈希算法在创新、融合与标准化方面的未来发展趋势。

seed的博客 391

库存管理系统项目部署方案(基于jdk17)

不需要安装到服务器,运维本地安装就行,主要是用来编译前端代码的。构建完成后将dist文件夹复制到服务器内。

程序员诚哥 6373

C++的I/O(vc版)(六)

首先回忆一下,我们已经分析过的类:基本的流类完成:流状态信息,格式化信息,其中一些不能用掩码表示,需要特定的数据成员,locale对象,流缓冲类指针,耦合的ostream;基本的流缓冲类完成:六个指针的存储。 这个我们分析的是basic_ostream  首先是类中会用到的类型声明: typedef basic_ostream _Myt; typedef basic_ios _Myios

wangyanphp的专栏 1678

火灾图像检测识别:cnn卷积神经网络 Adaboost 支持向量机 随机森林 决策树 完整代码数据

火灾图像检测识别:cnn卷积神经网络 Adaboost 支持向量机 随机森林 决策树 完整代码数据

862

C++的I/O(vc版)(二)

根据流类体系,我们可以看出基本的流类是ios_base和basic_ios  首先是ios_base是流类始祖,先分析ios_base,ios_base中储存的是不依赖于读写的数据的类型的基本信息,如格式化信息、异常状态、事件回调函数等。 首先看一下数据成员: iostate _mystate;//stream state iostate _except_;//except

wangyanphp的专栏 945

(十二)深入理解蓝牙BLE之“移植Bluez 5.18源码到嵌入式平台”

在某嵌入式平台进行蓝牙开发,发现上面居然没有btmon,hciattach,hcitool等蓝牙调试工具,无奈之下,只好移植bluez协议栈到目标嵌入式平台,建议移植5.18版本(最新的5.54版本居然hcitool等工具不是默认编译的,需要修改Makefile才可以)。 看到很多讲解移植过程的文章都是需要积分的,觉得写一篇免积分的文章还是有些意义的,欢迎同行来交流。 移植环境:Linux ubuntu 目标平台:sigmastar 星宸科技 配置交叉编译工具链:export PATH=$PATH:

2964

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

VC中C++的输入输出I/O 流函数

(1)什么是“流”?   C++中的“流”(stream)是一种抽象,它表示数据从源端流向目的端。   输入流(Input Stream)表示的是数据从输入设备(如键盘、磁盘等)流向内存,输出流(Output Stream)表示的是数据从内存流向输出设备(如屏幕、打印机、磁盘等)。输入输出流(I/O Stream)是输入流和输出流的合称。   “流”中的内容可以是任意形式的数据,例如:ASC

心在天涯 2180

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

C++的I/O(vc版)(五)

具体的缓冲类有filebuf,stringbuf,由于filebuf的大部分工作都转交给了C流,不好分析,所以重点分析的还是stringbuf。  对于stringstream,我们最常用的语句就是: string s="1.2 5.6 7 7 "; istringstream is(s); float f; is >> f; 上述语句,给出了stringbuf的基本形式:以string初

wangyanphp的专栏 1239

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C++的I/O(vc版)(七)

首先,我们还有很多的类没有分析:istream,filestream,filebuf,还有对应得迭代器。第二,即使前面的分析也不能说明I/O的使用规范。如果想要熟练的使用I/O,建议读《C++标准程序库》,那是一本经典。第三,流的格式化读取和输出大部分依靠的是locale,而我们前面很少涉及,现在还看不懂源码,只能以后分析了。  下面摘抄《c++标准程序库》中关于如何自定义I/O操作符的说明。

wangyanphp的专栏 912

C++打造局域网聊天室第八课: 异步I/O模型及多线程

C++打造局域网聊天室第八课: 异步I/O模型及多线程

qq_59940419的博客 1506

如何在Visual Studio中新建MB-System的I/O模块

实现了在windows平台下使用Microsoft Visual Studio Community 2022 (64 位)构建MB-system的I/O模块项目,用于将国产声呐数据添加到MB-system的数据支持中去。

qq_21472607的博客 1272

socket网络通信(重叠I/O方式实现)包含4种方式

采用重叠I/O方式实现的socket网络编程,异步非阻塞方式,代码效率比阻塞式的socket编程方式高。实现了TCP server,TCP client,UDP server,UDP client,四种方式可选,可以使用在各种场合用于监控网络数据。本程序只支持单客户端和服务端的应用场合。代码封装成库形式,非常方便移植。平台使用的是VC6.0,语言用的是C++,MFC做的界面。使用ws2_32....

hill_guo的博客 824
上一篇: C++的I/O(vc版)(二)
下一篇: C++的I/O(vc版)(四)
wangyanphp
博客等级 码龄14年 90粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值