当前位置: 移动技术网 > 移动技术>移动开发>IOS > 第七周学习:输入输出、C++重定向、流操纵算子

第七周学习:输入输出、C++重定向、流操纵算子

2020年09月20日  | 移动技术网移动技术  | 我要评论
istream 是用于输入的流类,cin就是该类对象。ostream是用于输出的流类,cout就是该类对象。ifstream是用于从文件读取数据的类ofstream是用于像文件写入数据的类iostream是既能输出又能输入的类fstream是既能从文件读取数据,又能写入数据的类标准流对象:cin \ cout \ cerr \ clogcin是标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据cout标准输出流,也可以重定向为向文件写入数据cerr和clog是...

输入输出概况

流和缓冲区

关于流

  1. C++程序把输入和输出看作字节流,输入时,程序从输入流抽取字节;输出时,程序将字节插入到输出流中。
  2. 流充当了程序和流源或流目标的桥梁,这使得程序可以以相同的方式对待输入和输出(既不管你的输入来自文件还是键盘,C++只负责检查字节流)

关于缓冲区

  1. 缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序传输给设备的临时存储工具。
  2. 缓冲区可以帮助匹配两种不同的信息传输速率。比如磁盘驱动器以512字节的块为单位来传输信息,而程序一般只处理1字节信息一次,所以可以用缓冲区来缓存。
  3. 从磁盘每次读取一个字节需要调用大量硬盘活动,速度非常慢。缓冲方法就是从磁盘里一次性读取大量信息,存储到缓冲区,然后每次从缓冲区读取一个字节。从内存中读取单个字节的速度要比磁盘速度快。
  4. 处理完一趟信息,刷新缓冲区,准备接受下一趟信息的处理。
  5. 键盘输入每次提供一个字符,程序无需利用缓冲区来匹配不同速率,但是进行缓冲可以让用户在输入传输之前返回并更正(键盘输入要按下回车,才会把内容传进输入缓冲区)。
  6. 刷新输出缓冲区: ostream类对cout对象处理的输出进行缓冲,所以输出被存储到缓冲区,直到缓冲区填满然后才刷新缓冲区,输出到目标位置。然后清空缓冲区。当标准输出与文件连接,这将节省不少时间。但是对于屏幕输出这就没什么必要了。换行符发送到缓冲区将导致刷新缓冲区。程序期待输入也将导致刷新缓冲区。还可以手动刷新。
cout<<flush;
cout<<endl;
flush(cout); //与第一个相同,因为对ostream类对<<重载了。
补:cout输出的两个函数
cout.put(char)  
原型ostream& put(char)
cout.write(char*,int) //输出字符串,输出int位
原型ostream& write(char*, int)
  • iostream包含一些管理流和缓冲区的类

转自MOOC北京大学C++课程

  1. istream 是用于输入的流类,cin就是该类对象。
  2. ostream是用于输出的流类,cout就是该类对象。
  3. ifstream是用于从文件读取数据的类
  4. ofstream是用于像文件写入数据的类
  5. iostream是既能输出又能输入的类
  6. fstream是既能从文件读取数据,又能写入数据的类

要使用这些工具,必须使用适当的类对象,创建对象将打开一个流,自动创建缓冲区,并将其与流关联起来,同时使得能够使用类成员函数。

标准流对象:
cin \ cout \ cerr \ clog

  1. cin是标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据
  2. cout标准输出流,也可以重定向为向文件写入数据
  3. cerr和clog是标准错误输出流,传输到屏幕(重定向时会有用)

重定向

cout、cin都是默认为屏幕输出,键盘输入,现在想对文件输出,从文件输入,重定向可以满足需求。

输出重定向:
方法一:
FILE *freopen( const char *path, const char *mode, FILE *stream )

  • path是文件名,mode为打开方式r或w,stream是标准流文件(stdin or stdout,stderr)
  • 功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认
int x,y;
cin>>x>>y;
freopen("test1.txt","w",stdout);
if(y==0)
	cerr<<"error"<<endl;
else
	cout<<x<<"/"<<y<<"= "<<x/y;
fclose(stdout)	; 

将标准输出流传输到test1.txt的文件中,这样输出就得打开文件查看了
输入:
在这里插入图片描述
输出:
在这里插入图片描述

方法二:
rdbuf原型有如下两个:
streambuf* rdbuf () const;
streambuf* rdbuf (streambuf*) ;

第一个函数是 函数获得流缓冲区
第二个函数是 函数设置流缓冲区

#include<iostream>
#include<fstream>
	ofstream outf("test1.txt") ;
	streambuf* buf;    //streambuf类是管理输入输出缓冲区的内存的
	buf = cout.rdbuf();  //buf获得流缓冲区(现在是控制台)
	cout.rdbuf(outf.rdbuf());	//将cout设置为流向文件缓冲区的对象
	cout<<"This is the method 2\n";
	cout.rdbuf(buf);	//将cout的输出方向设置回去
	cout<<"this will be printed to the screen";

输出:
在这里插入图片描述
在这里插入图片描述

输入重定向:(如果有大量数据输入,可以用这个从文件输入,而不是控制台手打)
同上
文件输入:
在这里插入图片描述

方法1:

freopen("test2.txt","r",stdin) ;
cin>>x>>y;
cout<<setprecision(7)<<"x is "<<x<<" and y is "<<y<<endl;
fclose(stdin);

文件输出:

方法2:

streambuf* buf;
ifstream inf("test2.txt");
buf = cin.rdbuf();
cin.rdbuf(inf.rdbuf());
cin>>x>>y;
cout<<setprecision(7)<<"I always "<<x<<" to you.\n你整点shit "<<y<<"..."<<endl;
cin.rdbuf(buf);

输出:
在这里插入图片描述

判断输入流结束

  1. 如果从文件输入,读到文件尾部,输入流就算结束;
  2. 键盘输入,则单独一行输入Ctrl+Z代表输入流结束

istream类成员函数

  1. istream& getline(char* buf, int bufSize)
    从输入流中读取bufSize-1个字符到缓冲区buf,或碰到’\n’为止

  2. ``istream& getline(char* buf, int bufSize, char delim)
    从输入流中读取bufSize-1个字符到缓冲区buf,或者碰到字符delim为止

  1. 都会自动在buf读入的数据结尾添加’\0’,判断字符不会被读入buf中,但会被输入流取走。
  2. 如果在判断字符之前,buf的数据就达到或超过bufSize,就会导致读入出错,结果就是本次读入虽然完成,但之后的读入就会失败。
    可以用if(!cin.getline(...))判断读取是否结束。
  1. bool eof() 判断输入流是否结束
  2. int peek()返回下一个字符,但不从流中去掉
  3. istream& putback(char c) 将字符ch放回输入流
  4. istream& ignore(int ncount=1,int delim =EOF)
    从流中删掉最多ncount个字符,或碰到EOF结束;
流操纵算子
  1. 整数流的基数:流操纵算子dec,oct,hex,setbase
  2. 浮点数精度:precision(成员函数),setprecision
  3. 设置域宽:setw,width(成员函数,且只能影响下一个将要显示的项目)
  4. 用户自定义的流操纵算子
  5. 填充字符:fill(char) (成员函数,将一直有效)
名称作用性质属性使用
dec十进制整数流基数流操纵算子cout<<dec<<..
oct八进制整数流基数流操纵算子dec(cout)
hex十六进制整数流基数流操纵算子同上
precision调整浮点数精度成员函数cout.precision(2)
setprecision调整浮点数精度流操纵算子cout<<setprecision(2)
setw设置字符宽度流操纵算子cout<<setw(8)
width设置字符宽度成员函数cout.width(8)
fill填补字符成员函数cout.fill('*')
格式常量setf( )含义
ios::boolalpha输入和输出bool,可以是true和false
ios::showbase对于输出,使用C++基数前缀 (0 , 0x)
ios::showpoint显示末尾小数点
ios::uppercase对于16为输出,是用大写字母,E表示法
ios::showpos正数前面有+号

头文件 iomanip

int n = 10;
cout<<n<<endl;
cout<<hex<<n<<endl; (十六进制)
cout<<dec<<n<<endl;(十进制)
cout<<oct<<n<<endl;(八进制)
	//precision是成员函数,
	cout.precision(int n);
	cout<<setprecision(int n)...; 可以连续输出

以小数点位置固定的方式输出:(小数点要在个位数后面)
setiosflags(ios::flxed)
resetiosflags(ios::flxed)取消这样子输出

设置域宽(有效性是一次性的)
setw()是流操纵算子,width()是成员函数。 不足的话会被填补(默认为空格)

科学计数法输出
scientific流操纵算子

自定义流操纵算子

ostream& name(ostream& os)
{	return os<<'\t' ;}

返回ostream引用,且参数只有一个ostream引用
因为iostream里对<<重载了,
ostream& operator<<(ostream& (*P)(ostream&));
调用P所指向的函数,且以*this作为参数。
参数意思:指针指向一个返回ostream&的且参数为ostream&引用的函数,
name函数就是这么一个函数

#include<iostream> 
#include<iomanip>
using namespace std;
ostream& Haha(ostream& os)
{
	os<<"\n";
}
int main()
{
	int x =10;
	//分别以 16进制 、 10进制 、 8进制输出
	cout<<"1) "<<hex<<x<<endl<<"2) "<<dec<<x<<endl<<"3) "<<oct<<x<<endl;
	
	double x1=1234.56789;
	//保留5位有效数字(四舍五入了) 
	cout<<setprecision(5)<<x1<<endl; 
	//保留小数点后五位
	cout<<fixed<<setprecision(5)<<x1<<endl;
	//科学计数法,保留小数点后五位
	cout<<scientific<<setprecision(5)<<x1<<endl; 
	//非负数显示+,宽度为12,宽度不足用 * 代替
	cout<<showpos<<fixed<<setw(12)<<setfill('*') <<12.22<<endl;
	//不显示+,宽度12,宽度不足右边用填充字符代替
	cout<<noshowpos<<setw(12)<<left<<12.22<<endl; 
	//左边
	cout<<setw(12)<<right<<-12.22<<endl;
	cout<<12.1<<endl; 
	cout<<"This is defined "<<Haha<<"by me";
	
}

输出:
在这里插入图片描述

本文地址:https://blog.csdn.net/ZmJ6666/article/details/108684870

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网