IO流

1. IO流的概念

  • C++将数据的输入输出看作是字节序列的波动
  • 输入是字节序列从设备(如键盘,磁盘)流向内存
  • 输出是字节序列从内存流向设备(如屏幕,磁盘)

2. 标准IO流

2.1. 标准IO流对象

  • 头文件中预定义了3个标准IO流对象

    2.1.1. cin

  • 标准输入流对象,类型为istream,关联到标准输入设备,一般是键盘

    2.1.2. cout

  • 标准输出流对象,类型为ostream,关联到标准输出设备,一般是屏幕可以重定向,有缓冲

    2.1.3. cerr

  • 标准错误流对象,类型为ostream,关联到标准错误设备,一般是屏幕不可重定向,无缓冲。

  • 重用于输出程序的错误信息

    2.1.4. 示例代码

    ```cpp

    include

    using namespace std;

int main(){ int n; cout << “请输入一个整数: “ << endl; cin >> n; cerr << “cerr can not be redirected” << endl; // 不能重定向 cout << “cout can be redirected” << endl; // 可以重定向

  1. cerr << "hello cerr"; // 无缓冲
  2. cout << "hello cout"; // 有缓冲
  3. cin >> n; // 输入语句会刷新输出缓冲区
  4. while(1){
  5. ;
  6. }
  7. return 0;

}

  1. <a name="mdCx2"></a>
  2. ## 2.2. 缓冲区
  3. <a name="pHjPv"></a>
  4. ### 2.2.1. 概念
  5. - 为了提高输入输出效率,标准IO流使用缓冲区技术。
  6. - 缓冲区是用来临时存储输入或者输出的数据的一块内存。
  7. <a name="DXpD8"></a>
  8. ### 2.2.2. 标准输入缓冲区
  9. - 从键盘输入的数据首先进入输入缓冲区。
  10. - 键盘->输入缓冲区->变量内存
  11. - 在刷新缓冲区前,用户有机会更正之前的输入
  12. - 刷新输入缓冲区时,所有数据从缓冲区流入到变量
  13. - 用户输入回车键可以刷新输入缓冲区
  14. <a name="JKwz0"></a>
  15. ### 2.2.3. 标准输出缓冲区
  16. - 输出到屏幕的数据首先进入输出缓冲区
  17. - 变量->输出缓冲区->屏幕
  18. - 刷新缓冲区时,数据从输出缓冲区流入到屏幕
  19. - 标准输出缓冲区刷新的条件(符合以下其一即可):
  20. - 缓冲区满时 //缓冲区的大小一般为512字节的整数倍
  21. - 输出控制符endl或者flush时
  22. - 程序执行到输入语句时
  23. - 程序执行完毕时
  24. <a name="YKcFe"></a>
  25. ## 2.3. 输入流
  26. <a name="BU89q"></a>
  27. ### 2.3.1. 格式化输入
  28. - cin使用提取运算符operator>>()从输入缓冲区中提取字符序列,转换成指导类型的数据存入变量,称为格式化输入。
  29. - istream针对各种基本类型重载了operator>>(),因此可以将字符序列转换成各种基本类型的数据
  30. - operator>>()提取并丢弃有效字符前面的空白字符(空格,制表符,换行符)
  31. - operator>>()遇到有效字符后面的空白字符(空格,制表符,换行符)时结束输入
  32. <a name="YXgVD"></a>
  33. ### 2.3.2. 非格式化输入
  34. - istream的某些输入函数会读取缓冲区中的所有字符,不忽略空白字符,也不进行类型转换,称为非格式化输入。
  35. - int get(void) //提取一个字符,返回ascii码
  36. - eg: `int charval = cin.get();`
  37. - istream& get(char ch) //将字符存到ch中
  38. - eg: `cin.get(ch);`
  39. - istream& get(char* buf, int n, char end = '\n'); //最多读取n-1个字符到buf中,并在结尾添加'\n',将行分隔符end留在缓冲区中
  40. - eg: `char test[32] = {0}; cin.get(test, 32, '\n');`
  41. <a name="JapX2"></a>
  42. ### 2.3.3. 非正常输入
  43. - 非正常输入会使输入函数返回,并导致输入流进入错误状态
  44. - 输入流进入错误状态后将对后面的输入关闭,直到状态恢复正常
  45. - 输入流关闭后,非正常输入的数据任然留在缓冲区中
  46. - 非正常输入的种类及其判断:
  47. - 文件结束EOF,cin.eof()返回true
  48. - 与预期类型不一致的字符,(cin.fail()&&!cin.eof())返回true
  49. - 其他情况,cin.bad()返回true
  50. - 对非正常输入的处理:
  51. - 判断非正常输入的种类
  52. - 使用cin.clear()恢复流的状态至正常
  53. - 使用cin.ignore()清除缓冲区中的非正常数据
  54. <a name="qUYPN"></a>
  55. ### 2.3.4. 示例代码
  56. ```cpp
  57. #include <iostream>
  58. using namespace std;
  59. int main(){
  60. /*
  61. // 格式化输入
  62. int n;
  63. cin >> n;
  64. cout << n << endl;
  65. string str;
  66. cin >> str;
  67. cout << str << endl;
  68. */
  69. /*
  70. // 非格式化输入
  71. int ch = cin.get();
  72. cout << "ch = " << ch << endl;
  73. char ch1 = 0;
  74. cin.get(ch1);
  75. cout << "ch1 = " << (int)ch1 << endl;
  76. //cout << (int)'\n' << endl;
  77. char arrch[32] = {0};
  78. cin.get(arrch, 32, '\n');
  79. cout << "你输入字符串是: " << arrch << endl;
  80. */
  81. // 非正常输入的处理
  82. int num = 0;
  83. while(1){
  84. cout << "请输入一个整数" << endl;
  85. cin >> num;
  86. if(cin.fail() && !cin.eof()){
  87. cin.clear();
  88. cin.ignore(1024, '\n');
  89. cin >> num;
  90. }
  91. cout << "你输入的数字num是: " << num << endl;
  92. }
  93. return 0;
  94. }

2.4. 输出流

2.4.1. 概念

  • cout使用插入运算符<< 将变量中的数据转换成字符序列,插入到输出缓冲区。

    2.4.2. 默认的输出格式

  • 对于可打印的char,显示一个字符

  • 对于字符串,显示字符串包含的所有字符。
  • 对于整型数值,以十进制形式显示
  • 对于浮点数值,显示六位有效数字,末尾的0不显示

    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. 示例代码

  1. #include <iostream>
  2. #include <iomanip>
  3. using namespace std;
  4. int main(){
  5. // 默认格式
  6. cout << 'a' << endl;
  7. cout << "hello" << endl;
  8. cout << 123 << endl;
  9. cout << 3.141592653579 << endl;
  10. // 格式控制
  11. cout << setprecision(5) << 3.141592653579 << endl;
  12. cout << setw(5) << setfill('*') << 123 << endl;
  13. cout << boolalpha << true << endl;
  14. cout << noboolalpha << false << endl;
  15. cout << showpos << 17 << endl;
  16. cout << noshowpos << 17 << endl;
  17. cout << left << setw(5) << setfill('*') << 123 << endl;
  18. cout << hex << showbase << 17 << endl;
  19. return 0;
  20. }