欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-03-24 20:25:57
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包含一些管理流和缓冲区的类

第七周学习:输入输出、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的文件中,这样输出就得打开文件查看了
输入:
第七周学习:输入输出、C++重定向、流操纵算子
输出:
第七周学习:输入输出、C++重定向、流操纵算子

方法二:
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";

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

输入重定向:(如果有大量数据输入,可以用这个从文件输入,而不是控制台手打)
同上
文件输入:
第七周学习:输入输出、C++重定向、流操纵算子

方法1:

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

文件输出:
第七周学习:输入输出、C++重定向、流操纵算子
方法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);

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

判断输入流结束

  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";
	
}

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

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

相关标签: C++ MOOC Study