C++输入输出机制与流详解

首先C++把输入输出看作字节流;

  输入时,程序从输入流中抽取字节;

  输出时,程序将字节插入到输出流中;

同时,为了加快程序与磁盘的交互速度,设置内存中的一块内存区域作为缓冲区来缓冲程序的输入与输出

流作为C++中程序与设备之间的桥梁;因此,C++在处理输入或者输出的时候只对流进行处理,而不管流的源头是什么;

总而言之,C++对输入输出的管理本质上就是对相应的流对象和其缓冲区进行管理

管理流和缓冲区的类包含在文件iostream中,其中;

    streambuf类——为缓冲区提供内存、提供填充缓冲区,访问缓冲区内容,刷新缓冲区管理缓冲区内存的相关方法;

    ios_base——表示流的一般特性;(是否可读取;流的格式等)

    ios类——是ios_base类的子类;包括了一个指向streambuf对象的指针;

    ostream——提供了输出的相关方法;

    istream类——提供了输入的相关方法;

    iostream类——继承自istream类和ostream类,故含有输入输出的相关方法;

进行输入输出时创建相应的对象;在创建对象的时候将打开一个流,并且自动创建缓冲区,并将缓冲区与流关联起来,同时对象便能使用相应的类方法对流进行处理;

同时,在程序中包含iostream文件的时候程序将自动创建8个流;其中四个用于窄字符流,4个用于宽字符流;其中——

    cin对应于标准输入流;标准输入流一般连接键盘;wcin对应宽字符的标准输入流;

    cout对应于标准输出流;标准输出流一边与显示器关联;wcout对应宽字符的标准输出流;

    cerr对应标准错误流;通常标准错误流关联到标准输出设备;wcerr同上;

    clog对应标准错误流;关联到标准输出设备;这个流被缓冲;wlog

总而言之,流的一端与程序相连,另一端与标准设备相连,对象凭借steambuf对象的帮助,管理流中的字节信息;

重定向——改变流的关联设备;

使用cout进行输出

#include"pch.h"
#include <iostream>
#include<iomanip>
using namespace std;

void test1 ()
{
	const char *str1="hello";
	const char *str2 = "world";

    //插入运算符<<被重载,能够识别基本的数据类型,以便调用相应的处理函数;例
	cout << 88<<endl;//调用函数ostream &operator<<(int 88)
	                 //以上原型表明插入运算符函数返回一个指向ostream的引用;利用这个机制可以实现输出拼接——
	cout << 1 << 2<<endl;//执行完第一个输出之后返回cout对象;语句变为cout<<2;

	//C++同时为指针重定义了运算符;将字符串指针表示字符串——C++将输出指针指向的字符串;
	
	cout << str1<<endl;
	cout << "hello\n";

	//其他类型的指针使用void*表示;直接输出地址的数值形式;
	int a = 100;
	int *addr = &a;
	cout <<addr<< endl;
	cout << (void*)str1 << endl;//使用强制类型转换可以输出字符串的地址
	cout << (char*)addr << endl;//同样使用强制类型转换可以将其他类型的指针所指向的内容转换为字符串输出;但是这样一般来说没有必要;

	//ostream中其他用于输出的方法:put()和write():
	//put()方法
	cout.put('a').put('b');//put输出字符 原型——ostream &put(char)返回ostream引用,表示可以拼接输出
	cout << endl;
	//write方法用于输出字符串,原型为 basic_ostream(charT,traits) & write(const char_type* s,streamsize n),
	//其中,第一个参数表示字符串的地址指针;第二个参数表示字符串的长度;
	cout.write(str1, strlen(str1)); cout << strlen(str1)<<endl;
	cout.write(str1, strlen(str1) + strlen(str2)); cout << strlen(str2) << endl;
	/*上一行的write输出为:"hello   wo"总共十个字符,说明了write的工作机制:
				输出时不跳过空格,
				中间的4个空格说明编译器使用4个字节调整字符串,
				故o之后的三个字节被填充为空格;也就是说hello被填充成了8个字节存储在内存中;*/

	/*
	刷新缓冲区:
	1)遇到换行符时自动刷新
	2)输入发生时刷新缓冲区:
	cout<<"hello";
	int b;
	cin>>b;
	y由于cin语句的即将执行导致缓冲区被刷新——hello字符串打印在屏幕上;否则程序将等待输入,无法显示hello字符串
	3)控制符flush和endl(控制符也是函数,可以直接调用fulsh()方法刷新缓冲区)
	*/


	//对cout输出进行格式化—

		//—插入运算符将值转化为文本格式,
		cout << 1.0 / 9.0 << endl;//显示六位
		double fl = 2.3e-4;
		cout << fl << endl;
		cout << fl / 100 << endl;//指数部分显示两位,部分编译器显示三位

		//修改显示的记数系统
		/*
			三种控制符:dec、hex、oct
		*/
		hex(cout);//将记数系统格式修改为十六进制,直到到下次修改;
		cout << 18 << endl;//输出十六进制12;
		cout << dec << 18 << endl;//重载插入运算符使得cout<<decy与dec(cout)等价;

		//调整字段宽度
		/*
			int width()  返回当前字段宽度的值
			int width(int i)   将字段宽度设置为i个空格,并返回未修改前的字段宽度值
			以上方法修改只影响当前项目,之后自动恢复默认值
		*/
		int len1 = cout.width(2);
		cout << cout.width() << endl;
		
		//填充字符:
		cout.width(12);
		cout.fill('#');
		cout << 1 << endl;

		//设置浮点数的显示精度:
		cout.precision(9);
		cout << 1.0 / 9.0 << endl;
		cout.precision(6);

		//显示末尾的0
		cout << 2.000 << endl;
		//ios_base类中的setf()方法可以设置显示浮点数末尾的0,以及控制多种格式化方式;
		cout.setf(ios_base::showpoint);
		cout << 2.000 << endl;
		cout << ios_base::showpoint << endl;

		//标准控制符:
		//最简洁的格式控制方法时使用控制符进行格式化,用法和hex类似

		//头文件iomanip中包含了相关格式设置的方法,可以在包含头文件之后直接使用以修改输出格式;
		cout << setw(9) << setfill('#') << 'a' << endl;
}

void main()
{
	test1();
	
}

使用cin进行输入

#include"pch.h"
#include <iostream>
#include<iomanip>
using namespace std;

//输入匹配
void test1 ()
{
	int a;
	cin >> a;//input 123ZX
	cout << a;//output 123(cin在遇到格式不匹配的时候将停止提取,经剩下的内容留在输入缓冲区中,下次抽取)
	char b;
	cin >>b;//该句不用显式输入,因为输入缓冲区中仍有匹配的字符,>>直接进行了抽取;
	cout << b;//outputZ;
}

//流状态——设置流状态将会影响到流对之后的输入输出是否关闭;
void test2()
{
	/*
	eofbit //到达文件尾时设置为1
	badbit//流被破坏时设置为1
	failbit//未能读取预期的字符时设置为1
	goodbit
    eof()
	bad()
	fail()
	rdstate()//返回当前状态
    clear(iostate s)//设置当前状态为s(s默认为0)——此处注意在设置的时候将清除其他两位
	setstate(iostate s)//调用clear(rdstate()|s)——设置某位且不会影响其他位
	exceptions(iostate ex)//  即((rdstate()&exception())!=0时将引发异常
	*/

	/*
	cout <<"当前状态为:"<< cin.rdstate()<<endl;

	cin.clear(ios_base::eofbit);//设置eofbit而清除其他两个状态
	cout << cin.rdstate()<<endl;

	cin.clear();//清楚所有状态;
	cout <<"clear(): "<< cin.rdstate()<<endl;

	cin.setstate(ios_base::eofbit);
	cout <<"setstate(eofbit):"<< cin.rdstate()<<endl;
	cout.clear();
	
	
	cout <<cin.exceptions();
	*/
	cin.exceptions(ios_base::eofbit);//设置异常引发状态;
	
	cin.clear();

	int a;
	while (cin >> a)//当所有流状态良好的时候才返回true; 
		            //输为非整数时格式不匹配将导致循环终止
	{
		switch (a) {
		case 0:cin.setstate(ios_base::eofbit);//执行该句之后将引发异常并且终止循环;
		case 1:;
		defult:;
		}

	}

}

//其他istream类方法
/*
单字符输入
get(char&)/抽取运算符将跳过空白——制表符换行符和空格;get方法提取包括空白字符在内的下一个输入字符,
get(void)
isspace()//参数是空白字符时返回true

字符串输入:
getline()
get()
ignore()
其中,get保留换行符在输入流中
getline抽取并丢弃换行符

*/
void test3()
{
	char ch;
	cin.get(ch);
	cout.put(ch); cout.put('\n');
	cout << cin.get();
	
}
void main()
{
	test3();
	
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值