第七周学习:输入输出、C++重定向、流操纵算子
输入输出概况
流和缓冲区
关于流
- C++程序把输入和输出看作字节流,输入时,程序从输入流抽取字节;输出时,程序将字节插入到输出流中。
- 流充当了程序和流源或流目标的桥梁,这使得程序可以以相同的方式对待输入和输出(既不管你的输入来自文件还是键盘,C++只负责检查字节流)
关于缓冲区
- 缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序传输给设备的临时存储工具。
- 缓冲区可以帮助匹配两种不同的信息传输速率。比如磁盘驱动器以512字节的块为单位来传输信息,而程序一般只处理1字节信息一次,所以可以用缓冲区来缓存。
- 从磁盘每次读取一个字节需要调用大量硬盘活动,速度非常慢。缓冲方法就是从磁盘里一次性读取大量信息,存储到缓冲区,然后每次从缓冲区读取一个字节。从内存中读取单个字节的速度要比磁盘速度快。
- 处理完一趟信息,刷新缓冲区,准备接受下一趟信息的处理。
- 键盘输入每次提供一个字符,程序无需利用缓冲区来匹配不同速率,但是进行缓冲可以让用户在输入传输之前返回并更正(键盘输入要按下回车,才会把内容传进输入缓冲区)。
- 刷新输出缓冲区: 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包含一些管理流和缓冲区的类
- istream 是用于输入的流类,cin就是该类对象。
- ostream是用于输出的流类,cout就是该类对象。
- ifstream是用于从文件读取数据的类
- ofstream是用于像文件写入数据的类
- iostream是既能输出又能输入的类
- fstream是既能从文件读取数据,又能写入数据的类
要使用这些工具,必须使用适当的类对象,创建对象将打开一个流,自动创建缓冲区,并将其与流关联起来,同时使得能够使用类成员函数。
标准流对象:
cin \ cout \ cerr \ clog
- cin是标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据
- cout标准输出流,也可以重定向为向文件写入数据
- 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);
输出:
判断输入流结束:
- 如果从文件输入,读到文件尾部,输入流就算结束;
- 键盘输入,则单独一行输入
Ctrl+Z
代表输入流结束
istream类成员函数
-
istream& getline(char* buf, int bufSize)
从输入流中读取bufSize-1个字符到缓冲区buf,或碰到’\n’为止 -
``istream& getline(char* buf, int bufSize, char delim)
从输入流中读取bufSize-1个字符到缓冲区buf,或者碰到字符delim为止
- 都会自动在buf读入的数据结尾添加’\0’,判断字符不会被读入buf中,但会被输入流取走。
- 如果在判断字符之前,buf的数据就达到或超过bufSize,就会导致读入出错,结果就是本次读入虽然完成,但之后的读入就会失败。
可以用if(!cin.getline(...))
判断读取是否结束。
- bool eof() 判断输入流是否结束
- int peek()返回下一个字符,但不从流中去掉
- istream& putback(char c) 将字符ch放回输入流
- istream& ignore(int ncount=1,int delim =EOF)
从流中删掉最多ncount个字符,或碰到EOF结束;
流操纵算子
- 整数流的基数:流操纵算子dec,oct,hex,setbase
- 浮点数精度:precision(成员函数),setprecision
- 设置域宽:setw,width(成员函数,且只能影响下一个将要显示的项目)
- 用户自定义的流操纵算子
- 填充字符: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
上一篇: 微信公众号怎么创建上墙活动?