标准IO库

本文深入探讨了C++中流对象不可复制性及其对容器存储的影响,详细解释了流对象作为参数和返回值的限制,并阐述了如何在程序中正确地管理IO标准库的状态。通过实例演示了如何利用clear()和sync()函数来处理流的状态位,避免了程序陷入死循环。同时,对比了clear()和setstate()方法在改变流状态时的不同作用,以及它们在特定场景下的正确使用方式。


一、IO对象不可复制或赋值,以此导致三个行为:

1、只有支持复制的元素类型可以存储在 vector 或其他容器类型里。由于流对象不能复制,因此不能存储在 vector(或其他)容器

中(即不存在存储流对象的 vector 或其他容器)。

2、形参或返回类型也不能为流类型。如果需要传递或返回 IO对象,则必须传递或返回指向该对象的指针或引用。

3、一般情况下,如果要传递 IO 对象以便对它进行读写,可用非 const 引用的方式传递这个流对象。对 IO 对象的读写会改变它的状

态,因此引用必须是非const 的。

二、IO标准库的条件状态

strm::iostate机器相关的整型名,由各个 iostream 类定义,用于定义条件状态
strm::badbitstrm::iostate 类型的值,用于指出被破坏的流
strm::failbitstrm::iostate 类型的值,用于指出失败的 IO 操作
strm::eofbitstrm::iostate 类型的值,用于指出流已经到达文件结束符
s.eof()如果设置了流 s 的 eofbit 值,则该函数返回 true
s.fail()如果设置了流 s 的 failbit 值,则该函数返回 true
s.bad()如果设置了流 s 的 badbit 值,则该函数返回 true
s.good()如果流 s 处于有效状态,则该函数返回 true
s.clear()将流 s 中的所有状态值都重设为有效状态
s.clear(flag)将流 s 中的某个指定条件状态设置为有效。flag 的类型是strm::iostate
s.setstate(flag)给流 s 添加指定条件。flag 的类型是 strm::iostate
s.rdstate()返回流 s 的当前条件,返回值类型为 strm::iostate

三、关于clear(iostate::state = goodbit)与sync()的使用:

1、clear函数用于更改流的状态指示符,形参的默认值是goodbit,意思是设置流的状态位为goodbit,同理strm.clear(std::failbit)是将流的

状态位设置为failbit,clear的作用绝不是用于清空流指定的状态位,

2、clear通常与sync搭配使用,sync方法的作用是清除流的缓冲区,如下面的例子,当输入流要求输入的是整形,而用户却输入非整形的字

符,这会导致流的状态位为failbit,调用strm.clear()后将流的状态位设置为goodbit,但是用户输入的内容仍在cin的缓冲区中,即下次再调

用cin >> ival时,返回给ival的依然是存在缓冲区中非法的值,此时cin >> ival 不再生效,而是直接执行!cin.eof()函数,即程序会进入一个死

循环。要防止这个死循环,就是在clear之后,调用sync,即清空cin的缓冲区。

void test_clear_sync(){
	int ival;
	while(std::cin >> ival, !std::cin.eof() ){
		if( std::cin.bad() ){
			throw std::runtime_error("Input stream is error!");
		}
		if( std::cin.fail() ){
			std::cout << "Please enter a number type!" << std::endl;
			std::cin.clear();
			std::cin.sync();
			continue;
		}
		std::cout << "ival:" << ival << std::endl;
	}
}

四、关于setstate与clear的区别:

对于setstate方法的使用,通常使用setstate方法设置流的错误状态值,已经设置为错误状态(三种badbit,failbit,eofbit)的,当试图使用

setstate(goodbit)修改流的状态为有效时,流的错误状态不会被更改,应该使用使用clear()设置流的有效状态。

void test_mul_state_setstate_1()
{
	// 同时设置多个状态值:
	std::cin.setstate(std::istream::badbit | std::istream::failbit);
	std::cout << std::cin.rdstate() << std::endl;//6
	std::cin.setstate(std::istream::goodbit);
	std::cout << std::cin.rdstate() << std::endl;//6,错误状态值没有被更改
}

void test_mul_state_setstate_2()
{
	// 同时设置多个状态值:
	std::cin.setstate(std::istream::badbit | std::istream::failbit);
	std::cout << std::cin.rdstate() << std::endl;//6
	std::cin.sync();
	std::cin.setstate(std::istream::goodbit);
	//std::cin.sync(); // 刷新缓冲区只影响缓冲区之前缓冲的数据,对流的状态没有影响
	std::cout << std::cin.rdstate() << std::endl;//6,错误状态值没有被更改
}


//正确的方式应该是采用clear
void test_mul_state_clear_1()
{
	// 同时设置多个状态值:
	std::cin.setstate(std::istream::badbit | std::istream::failbit);
	std::cout << std::cin.rdstate() << std::endl;//6
	std::cin.clear();
	std::cout << std::cin.rdstate() << std::endl;//0,成功设置
}

void test_mul_state_clear_2()
{
	// 同时设置多个状态值:
	std::cin.setstate(std::istream::badbit | std::istream::failbit | std::istream::eofbit);
	std::cout << std::cin.rdstate() << std::endl;//7
	std::cin.clear();
	std::cout << std::cin.rdstate() << std::endl;//0,成功设置
}









评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值