IO流
1. IO流的概念
- C++将数据的输入输出看作是字节序列的波动
- 输入是字节序列从设备(如键盘,磁盘)流向内存
- 输出是字节序列从内存流向设备(如屏幕,磁盘)
2. 标准IO流
2.1. 标准IO流对象
-
2.1.1. cin
标准输入流对象,类型为istream,关联到标准输入设备,一般是键盘
2.1.2. cout
标准输出流对象,类型为ostream,关联到标准输出设备,一般是屏幕可以重定向,有缓冲
2.1.3. cerr
标准错误流对象,类型为ostream,关联到标准错误设备,一般是屏幕不可重定向,无缓冲。
- 重用于输出程序的错误信息
2.1.4. 示例代码
```cppinclude
using namespace std;
int main(){ int n; cout << “请输入一个整数: “ << endl; cin >> n; cerr << “cerr can not be redirected” << endl; // 不能重定向 cout << “cout can be redirected” << endl; // 可以重定向
cerr << "hello cerr"; // 无缓冲
cout << "hello cout"; // 有缓冲
cin >> n; // 输入语句会刷新输出缓冲区
while(1){
;
}
return 0;
}
<a name="mdCx2"></a>
## 2.2. 缓冲区
<a name="pHjPv"></a>
### 2.2.1. 概念
- 为了提高输入输出效率,标准IO流使用缓冲区技术。
- 缓冲区是用来临时存储输入或者输出的数据的一块内存。
<a name="DXpD8"></a>
### 2.2.2. 标准输入缓冲区
- 从键盘输入的数据首先进入输入缓冲区。
- 键盘->输入缓冲区->变量内存
- 在刷新缓冲区前,用户有机会更正之前的输入
- 刷新输入缓冲区时,所有数据从缓冲区流入到变量
- 用户输入回车键可以刷新输入缓冲区
<a name="JKwz0"></a>
### 2.2.3. 标准输出缓冲区
- 输出到屏幕的数据首先进入输出缓冲区
- 变量->输出缓冲区->屏幕
- 刷新缓冲区时,数据从输出缓冲区流入到屏幕
- 标准输出缓冲区刷新的条件(符合以下其一即可):
- 缓冲区满时 //缓冲区的大小一般为512字节的整数倍
- 输出控制符endl或者flush时
- 程序执行到输入语句时
- 程序执行完毕时
<a name="YKcFe"></a>
## 2.3. 输入流
<a name="BU89q"></a>
### 2.3.1. 格式化输入
- cin使用提取运算符operator>>()从输入缓冲区中提取字符序列,转换成指导类型的数据存入变量,称为格式化输入。
- istream针对各种基本类型重载了operator>>(),因此可以将字符序列转换成各种基本类型的数据
- operator>>()提取并丢弃有效字符前面的空白字符(空格,制表符,换行符)
- operator>>()遇到有效字符后面的空白字符(空格,制表符,换行符)时结束输入
<a name="YXgVD"></a>
### 2.3.2. 非格式化输入
- istream的某些输入函数会读取缓冲区中的所有字符,不忽略空白字符,也不进行类型转换,称为非格式化输入。
- int get(void) //提取一个字符,返回ascii码
- eg: `int charval = cin.get();`
- istream& get(char ch) //将字符存到ch中
- eg: `cin.get(ch);`
- istream& get(char* buf, int n, char end = '\n'); //最多读取n-1个字符到buf中,并在结尾添加'\n',将行分隔符end留在缓冲区中
- eg: `char test[32] = {0}; cin.get(test, 32, '\n');`
<a name="JapX2"></a>
### 2.3.3. 非正常输入
- 非正常输入会使输入函数返回,并导致输入流进入错误状态
- 输入流进入错误状态后将对后面的输入关闭,直到状态恢复正常
- 输入流关闭后,非正常输入的数据任然留在缓冲区中
- 非正常输入的种类及其判断:
- 文件结束EOF,cin.eof()返回true
- 与预期类型不一致的字符,(cin.fail()&&!cin.eof())返回true
- 其他情况,cin.bad()返回true
- 对非正常输入的处理:
- 判断非正常输入的种类
- 使用cin.clear()恢复流的状态至正常
- 使用cin.ignore()清除缓冲区中的非正常数据
<a name="qUYPN"></a>
### 2.3.4. 示例代码
```cpp
#include <iostream>
using namespace std;
int main(){
/*
// 格式化输入
int n;
cin >> n;
cout << n << endl;
string str;
cin >> str;
cout << str << endl;
*/
/*
// 非格式化输入
int ch = cin.get();
cout << "ch = " << ch << endl;
char ch1 = 0;
cin.get(ch1);
cout << "ch1 = " << (int)ch1 << endl;
//cout << (int)'\n' << endl;
char arrch[32] = {0};
cin.get(arrch, 32, '\n');
cout << "你输入字符串是: " << arrch << endl;
*/
// 非正常输入的处理
int num = 0;
while(1){
cout << "请输入一个整数" << endl;
cin >> num;
if(cin.fail() && !cin.eof()){
cin.clear();
cin.ignore(1024, '\n');
cin >> num;
}
cout << "你输入的数字num是: " << num << endl;
}
return 0;
}
2.4. 输出流
2.4.1. 概念
cout使用插入运算符<< 将变量中的数据转换成字符序列,插入到输出缓冲区。
2.4.2. 默认的输出格式
对于可打印的char,显示一个字符
- 对于字符串,显示字符串包含的所有字符。
- 对于整型数值,以十进制形式显示
-
2.4.3. 控制输出格式
可以使用IO操作符控制输出格式
- IO操作符的头文件包括
和 - 常用IO操纵符: | std::setprecision(n) | 控制精度,有效数字个数 | | —- | —- | | std::setw(w) | 设置输出宽度 | | std::setfill(c) | 设置填充字符 | | std::boolalpha | 以字母格式输出true和false | | std::noboolalpha | 不以字母格式输出true和false | | std::showpos | 显示正号“+” | | std::noshowpos | 不显示正号“+” | | std::left | 输出时左对齐 | | std::right | 输出时右对齐 | | std::dec | 以十进制输出数字 | | std::hex | 以十六进制输出数字 | | std::oct | 以八进制输出数字 | | std::showbase | 显示0x或者0 | | std::noshowbase | 不显示0x或者0 | | std::endl | 输出换行符并刷新输出缓冲区 |
2.4.4. 示例代码
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
// 默认格式
cout << 'a' << endl;
cout << "hello" << endl;
cout << 123 << endl;
cout << 3.141592653579 << endl;
// 格式控制
cout << setprecision(5) << 3.141592653579 << endl;
cout << setw(5) << setfill('*') << 123 << endl;
cout << boolalpha << true << endl;
cout << noboolalpha << false << endl;
cout << showpos << 17 << endl;
cout << noshowpos << 17 << endl;
cout << left << setw(5) << setfill('*') << 123 << endl;
cout << hex << showbase << 17 << endl;
return 0;
}