c++中输入与输出都是通过流来完成。
知识点
流类
C++ 的开发者认为数据输入和输出的过程也是数据传输的过程,数据像水一样从一个地方流动到另一个地方,所以 C++ 中将此过程称为“流”,将与数据输入/输出相关的类称为流类
常用的流类及关系
如下图所示:
常用输入输出流列表
类名 | 说明 | 包含文件 |
---|---|---|
抽象流基类ios | 流基类 | ios |
输入流基类istream | 通用输入流基类和其他输入流基类。cin是该类的对象;常用于接收从键盘输入的数据 | istream |
ifstream | 文件输入流类,用于从文件读取数据 | fstream |
输出流类ostream | 通用输出流基类和其他输出流基类。cout是该类的对象;常用于将数据输出到屏幕上; | ostream |
ofstream | 文件输出流类,用于向文件写入数据 | fstream |
输入输出流类 iostream | 通用输入输出流基类和其他输入输出流基类;继承自 istream 和 ostream 类,因为该类的功能兼两者于一身,既能用于输入,也能用于输出; | iostream |
fstream | 文件输入输出流类;兼 ifstream 和 ofstream 类功能于一身,既能读取文件中的数据,又能向文件中写入数据。 | fstream |
避免多重继承二义性问题,从ios派生istream和ostream时,均使用了virtual(虚继承)。
iostream类库头文件
- iostream:包含所有输入输出 流所需的基本信息。包含4个标准流对象,详见下面“标准流对象”,提供无格式和有格式化的i/o功能。
- iomanip:包含格式化i/o的带参数流操纵符,指定数据格式
- fstream;处理文件的有关信息,提供建立文件、读写文件的各种操作接口。
iostream定义的4种标准流对象
为用户提供常用外设与内存之间通信的通道,对数据进行解释和传输,提供必要的数据缓冲等。
4个标准的流对象
cin:
用于从键盘输入数据
cout:
用于向屏幕输出数据1,可以重定向输出到文件,使用freopen函数重定向
FILE *freopen(const char *path,const char *mode,FILE *stream);//mode是指定模式,w(写),t(读)path是输出文件名,steam就是输出流或输入流,如stdin或stdout,失败关闭原来的stream返回NULL,成功返回文件名
实例
#include <fstream>
#include<iomanip>
#include<iostream>
using namespace std;
int main()
{
int a;
fstream fs("abc.txt", ios::in | ios::out | ios::trunc);
fs << 1 << " " << 2 << " " << 3 << endl;//重定向到文件流,插入1 2 3
fs.seekp(0, ios::beg);//设置输出流指针位置
int x, y, z;
fs >> x >> y >> z;//从文件中提取出字符
cout << x << y << z << endl;
}
cerr(非缓冲错误输出流)
直接向显示器输出信息,不能重定向
cerr 也是与流插入运算符 << 结合使用的,
实例
#include <iostream>
using namespace std;
int main()
{
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;//Error message : Unable to read....
return 0;
}
clog(缓冲错误输出流,也叫日志输出流)
先存储到缓冲区,缓冲区满或刷新时才输出到屏幕。
clog 也是与流插入运算符 << 结合使用的
总结
对象 | 含义 | 对应设备 | 对应的类 | c语言中相应的标准文件 |
---|---|---|---|---|
cout | 标准输出流 | 屏幕 | ostream_withassign | stdout |
cerr | 标准错误流 | 屏幕 | ostream_withassign | stderr |
clog | 标准错误流 | 屏幕 | ostream_withassign | stderr |
cin | 标准输入流 | 键盘 | istream_withassign | stdin |
在iostream头文件中定义以上4个流对象用以下的形式(以cout为例):
ostream cout ( stdout);
在定义cout为ostream流类对象时,把标准输出设备stdout作为参数,这样它就与标准输出设备(显示器)联系起来,如果有
cout <<3;
ios类定义的错误状态字及函数
流的状态可以通过检测ios_base类中的位来判断。
错误状态字:
goodbit
0x00,流状态正常位
如果流中的eofbit、failbit 和 badbit位都没有被设置,那么goodbit位将被设置
即如果函数eof, fail 和 bad都返回false值,则成员函数good返回true值。I/O操作只在“好的”流中才能进行。
eofbit,
0x01,文件结束符位
可以调用函数 cin.eof()来判断是否到达文件末尾
在cin中遇到问价末尾时返回true,否则返回false。
failbit
0x02,操作失败,数据未丢失,可以恢复
如程序要求输入整数,但是在输入流中有非整数的字符的情况。在遇到这种错误时,这些字符不会丢失。
成员函数fail将报告流操作失败了,通常这种错误是可以恢复的。
badbit
0x04,非法操作,数据丢失
成员函数bad将报告流操作是否失败了。一般情况下,这种严重的错误是不能修复的。
有关函数
- int eof()const
功能:测试是否到文件尾,到了返加1,否则返回0.crtl+z表示输入流结束。 - int fail()coust
功能:流操作是否失败,失败返加1,否则返回0 - int good()const
int operator void *();
功能:两个函数功能一样,如果eofbit,failbit和badbit都没有被置位,返回1,否则返回0. - int bad()const
int operator void!()
功能:同上,只要三个位中有一个被置位,返回1,否则返回0 - int rdstate()const;
功能:返回流的当前状态,返回流中的错误状态
如,通过调用cout.rdstate返回流的状态,然后通过switch语句检查eofbit、badbit、failbit 和 goodbit来检查这些状态。
检测流状态的首选方法是使用成员函数eof, fial, bad 和 good, 使用这些函数不要求了解具体的状态位 - void clear(int nStata=0);
功能:恢复状态字,即将流状态恢复为正常。
clear函数的默认参数是goodbit所以语句
cin.clear()
清空了cin, 并且为该流设置goodbit位。
语句cin.clear(ios::failbit)则为流设置failbit位
实例
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int integerValue;
cout << "Before a bad input operation:"
<< "\ncin.rdstate():" << cin.rdstate()// cin.rdstate():0
<< "\ncin.eof():" << cin.eof()// cin.eof():0
<< "\ncin.fail():" << cin.fail()// cin.fail():0
<< "\ncin.bad():" << cin.bad()// cin.bad():0
<< "\ncin.good():" << cin.good()// cin.good():1
<< "\n\nExpects an integer, but enter a character:";
cin >> integerValue;
cout << endl;
cout << "After a bad input operation:"
<< "\ncin.rdstate():" << cin.rdstate()// cin.rdstate():4
<< "\ncin.eof():" << cin.eof()// cin.eof():0
<< "\ncin.fail():" << cin.fail()// cin.fail():1
<< "\ncin.bad():" << cin.bad()// cin.bad():0
<< "\ncin.good():" << cin.good() << endl << endl;// cin.good():0
cin.clear();
cout << "After cin.clear()" << "\ncin.fail():" << cin.fail()// After cin.clear()
<< "\ncin.good():" << cin.good() << endl;// cin.fail():0
// cin.good():1
return 0;
}
i/o格式控制,即cin和cout 输入或输出格式控制
一般有使用流操纵符、设置标志字和调用成员函数。
iomanip中定义的流操纵符(格式控制符,不带参数)
endl:输出一个新行符,并清空流
ends:输出字符串结束,并清空流
flush:清空流缓冲区
dec* :以十进制形式输入或输出整数,*不是操纵符一部分,表示是默认设置。
hex:以十六进制形式输入或输出整数
oct:以八进制形式输入或输出整数
ws:提取空白字符
iomanip中定义的流操纵符(带参),考点
setbase(int b):设置输出整数时的进制
setw(int w):指定输出宽度为w个字符,或输入字符串时读入w个字符。一次有效,有小数点等要算个数
setfill()配合setw使用,设置其他字符填充
==setprecision(int n):==浮点值可以四舍五入到若干位有效数或精度,这是出现在小数点前后的总位数。控制显示浮点数值的有效数的数量。precision:英文 精度 的意思。小数点不算个数。要充分理解有效个数,如0.0321,保留两位有效位数,应该是:0.032
noboolapha*:把true和false 分别输出为1或0
showbase:输出表示数值进制的前缀,十六进制是0x
noshowpoint*:只有当小数部分存在时才显示的小数点
实例
注意与调用cout或cin成员函数时的不同。调用操纵符是cout<<+直接跟操作纵函数
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int n = 64;
double d = 123.45;
double d2 = 0.0183;
//精度控制会影响下面的输出
cout << setprecision(4) << d << endl; //控制有效数字的位数 123.5
cout << setprecision(2) << d2 << endl;//四舍五入,而不是简单的截断 0.018
cout << d << endl;//1.2e+02
cout << setiosflags(ios::fixed); //控制小数点后面的位数
cout << setprecision(4) << d << endl; //同样是四舍五入 123.4500
cout << setprecision(2) << d2 << endl;//0.02
//进制控制
cout << "dec: " << n << endl;//dec: 64
cout << "oct: " << oct << n << endl;//oct: 100
cout << "hex: " << hex << n << endl;//hex: 40
cout << n << endl;//40
cout << setiosflags(ios::showbase);//显示对应进制前面的符号
cout << "dec: " << dec << n << endl;
cout << "oct: " << oct << n << endl;//oct: 0100
cout << "hex: " << hex << n << endl;//hex: 0x40
cout << setbase(8) << n << endl; //进制输出 0100
cout << setbase(10) << n << endl;//64
cout << setbase(16) << n << endl;//0x40
}
setiosflags()函数可设置的标志字
头文件iostream中的setiosflags()函数用以设置指定的显示格式的标志字,函数的参数为流的格式标志位。如下图所示:
调用cout成员函数,考点
控制输出格式,作用和对应的流操纵符相同,如下图:因为是调用成员函数的形式,所以不需要 iomanip头文件
C++ cout 输出流对象常用成员方法:
成员方法名 | 功能 |
---|---|
put() | 输出单个字符。 |
write() | 输出指定的字符串。 |
tellp() | 用于获取当前输出流指针的位置。 |
seekp() | 设置输出流指针的位置。 |
flush() | 刷新输出流缓冲区。 |
operator<< | 重载 << 运算符,使其用于输出其后指定类型的数据。 |
实例
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << setiosflags(ios::left | ios::showpoint); // 设左对齐,以一般实数方式显示
cout.precision(5); // 设置除小数点外有五位有效数字
cout << 123.456789 << endl;//123.46
cout.width(10); // 设置显示域宽10
cout.fill('*'); // 在显示区域空白处用*填充
cout << resetiosflags(ios::left); // 清除状态左对齐
cout << setiosflags(ios::right); // 设置右对齐 <iomainp>中设置输出格式的标志字
cout << 123.456789 << endl;// ****123.46
cout << setiosflags(ios::left | ios::fixed); // 设左对齐,以固定小数位显示
cout.precision(3); // 设置实数显示三位小数
cout << 999.123456 << endl;// 999.123
cout << resetiosflags(ios::left | ios::fixed); //清除状态左对齐和定点格式
cout << setiosflags(ios::left | ios::scientific); //设置左对齐,以科学技术法显示
cout.precision(3); //设置保留三位小数
cout << 123.45678 << endl;// 1.235e+02
return 0;
}
调用cin成员函数
C++ cin 输入流对象常用成员方法
成员方法名 | 功能 |
---|---|
getline(char *buf,int n) | 从输入流中的当前字符开始读取n-1个字符到缓冲区buf,或读到‘\n’为止,结尾自动添加结束标‘\0’ |
getline(char *buf,int n,char ch) | 读到字符ch为止,结尾自动添加‘\0’,ch为终止界定符 |
get() | 从键盘输入一个字符,ascii码形式,输入crl+z,再回车,返回EOF(文件结束符标记,常量,-1),同时该字符会从输入流中消失。 |
gcount() | 返回上次从输入流提取出的字符个数,该函数常和 get()、getline()、ignore()、peek()、read()、readsome()、putback() 和 unget() 联用。 |
peek() | 返回输入流中的第一个字符,但并不是提取该字符,只是读。可以返回空格和回车符,及文件结束符EOF. |
putback© | 将字符 c 置入输入流(缓冲区)。 |
ignore(int n,char ch) | 跳过输入流中的n个字符,或跳过ch 及其之前的所有字符。默认为cin.ignore(1,EOF),跳过一个字符,该函数常用于跳过输入中无用的部分,以便提取有用的部分。 |
operator>> | 重载 >> 运算符,用于读取指定类型的数据,并返回输入流对象本身。 |
eof() | 判断输入流是否已经结束,返回值为true |
实例
#include<iostream>
using namespace std;
int main()
{
char val;
val = cin.get();
cout.put(val);//输入一个字母会返回一个相同字母
}
C++ 编译器根据要输出变量的数据类型,选择合适的流插入运算符来显示值。所以,可以说用cout就不用管数据类型 ↩︎