c++输入输出流

程序的输入指将外界的数据传送到程序(内存),程序的输入是指从程序将数据传送出来,站在内存的角度来看的其实是

c++常用流类型

包含以下三个内容:

(1).对系统指定的标准设备的输入和输出,即从键盘输入数据,输出到显示器屏幕,这种输入输出称为标准的输入输出,简称标准I/O

(2) 以外存磁盘文件为对象进行输入和输出,即从磁盘文件输入数据,数据输出到磁盘文件。以外存文件为对象的输入输出称为文件的输入输出,简称文件 I/O 。

(3) 对内存中指定的空间进行输入和输出。通常指定一个字符数组作为存储空间(实际上可以利用该空间存储任何信息)。这种输入和输出称为字符串输入输出,简称 I/O 。

通用IO其实是包含了标准IO,文件IO和字符串IO

流的四种状态

IO 操作与生俱来的一个问题是可能会发生错误,一些错误是可以恢复的,另一些是不可以的。在C++ 标准库中,用 iostate 来表示流的状态,不同的编译器 iostate 的实现可能不一样,不过都有四种状态:

  • badbit 表示发生系统级的错误,如不可恢复的读写错误。通常情况下一旦 badbit 被置位,流就无法再使用了。

  • failbit 表示发生可恢复的错误,如期望读取一个int数值,却读出一个字符等错误。这种问题通常是可以修改的,流还可以继续使用。

  • eofbit表示到达流结尾位置, 流在正常输入输出的情况下结束,会被置为eofbit状态。

  • goodbit 表示流处于有效状态。流在有效状态下,才能正常使用。如果 badbit 、 failbit 和 eofbit 任何一个被置位,则流无法正常使用。

这四种状态都定义在类 ios_base 中,作为其数据成员存在。在 GNU GCC7.4 的源码中,流状态的实现

查看状态

1
2
3
4
5
6
7
8
9
10
11
12
13
void test(){
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;

int num = 10;
cin >> num;//输入asdlaksjdlk的非int形,会发现进入了fail状态
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void checkStreamStatus(istream& c){
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;
}
void test(){
checkStreamStatus(cin);
int num = 10;
cin >> num;//输入乱七八糟的值会发现下面的cin也不能用了
checkStreamStatus(cin);
int num2 = 1;
cin >> num2;
}

恢复流的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void checkStreamStatus(istream& c){
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;
}
void test(){
checkStreamStatus(cin);
int num = 10;
cin >> num;//输入乱七八糟的值会发现下面的cin也不能用了
checkStreamStatus(cin);
if(!cin.good()){
cin.clear();
}//确实恢复流的状态了 ,但是发现下面的cin还是不能用,下面的cin的状态又被置为fail了

int num2 = 1;
cin >> num2;
}

可能是缓冲区的问题,验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void checkStreamStatus(istream& c){
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;
}
void test(){
checkStreamStatus(cin);
int num = 10;
cin >> num;//输入乱七八糟的值会发现下面的cin也不能用了
checkStreamStatus(cin);
if(!cin.good()){
cin.clear();
}

string str1;
cin >> str1;
//验证发现确实是直接把缓冲区的数据填充到str1里面了
}

所以不仅要恢复流的状态还需要清空缓冲区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <limits>
void checkStreamStatus(istream& c){
cout << cin.good() << endl;
cout << cin.fail() << endl;
cout << cin.bad() << endl;
cout << cin.eof() << endl;
}
void test(){
checkStreamStatus(cin);
int num = 10;
cin >> num;//输入乱七八糟的值会发现下面的cin也不能用了
checkStreamStatus(cin);
if(!cin.good()){
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize::max()>,'\n');//默认是清除缓冲区的一个字符
//参数含义,第一个参数是表示释放多少个字符,第二个参数是指,如果释放的碰到某一个指定的字符就停止
}

int num2 = 1;
cin >> num2;
//验证发现确实是直接把缓冲区的数据填充到str1里面了
}