Limesn
Limesn
发布于 2026-09-16 / 1 阅读
0

第三章 IO

1. 流的四种状态是什么?什么情况下会进入到这种状态?

在C++中,流的状态由 ios_base 类中的状态标志位表示,共有四种:

  • goodbit (good):值为0,表示流处于正常状态,一切操作准备就绪。
    • 触发条件:默认状态或发生错误并成功清除错误后。
  • eofbit (eof):表示到达了文件末尾(End of File)。
    • 触发条件:读取操作尝试读取超出文件末尾的数据时(如 getline>> 读到文件最后)。
  • failbit (fail):表示I/O操作失败,通常是逻辑上的错误,流还可以继续使用。
    • 触发条件:类型匹配错误(例如试图将字母读入一个 int 变量),或者打开文件失败。注意:读到文件末尾时也会同时设置 eofbit 和 failbit。
  • badbit (bad):表示流发生了严重的底层错误(如硬件错误、内存分配失败或写入只读文件),流通常已无法继续使用。
    • 触发条件:物理I/O错误,例如磁盘已满或设备故障。

(注:可以通过 cin.good(), cin.eof(), cin.fail(), cin.bad() 来检测状态,使用 cin.clear() 来重置状态。)

2. cout的本质是什么?

cout 的本质是一个 全局的 std::ostream 类的对象(具体是 std::basic_ostream<char> 的派生类 std::ostream 的实例)。

  • 它定义在 <iostream> 头文件中。
  • 它代表“标准输出设备”(通常是控制台/终端)。
  • 它被设计为将数据格式化后插入到标准输出流中(通常使用 << 运算符重定向到标准输出,底层通过缓冲区刷新到屏幕)。

3. cin的本质是什么?

cin 的本质是一个 全局的 std::istream 类的对象(具体是 std::basic_istream<char> 的派生类 std::istream 的实例)。

  • 它同样定义在 <iostream> 头文件中。
  • 它代表“标准输入设备”(通常是键盘)。
  • 它负责从标准输入流中提取数据(通常使用 >> 运算符,或者 get(), getline() 等函数)。

4. 什么是全缓冲?什么是行缓冲?

这是指I/O流底层的缓冲区策略,主要为了减少频繁的系统调用,提高效率。

  • 全缓冲(Full Buffering):只有当缓冲区被填满时,才会执行实际的I/O系统调用(写入设备或从设备读取)。典型代表是磁盘文件读写(fstream)。如果程序崩溃,缓冲区里未满的数据可能会丢失。
  • 行缓冲(Line Buffering):当遇到换行符 \n 时,或者缓冲区满时,就会执行实际的I/O操作。典型代表是终端上的 cincout。这样做是为了让用户能及时看到输出(比如打印一行日志)。标准错误流 cerr 通常是无缓冲的。

5. 如何读取文件中的数据?有哪些方式?

首先需要包含头文件 <fstream>,并创建 ifstream(输入文件流)对象。
主要方式有:

  1. 使用流提取运算符 >>:适用于格式化数据(如整数、浮点数、以空格分隔的字符串)。file >> var;
  2. 使用 getline() 函数:读取整行数据(直到遇到换行符或指定分隔符)。std::getline(file, str);
  3. 使用 get() 函数:读取单个字符,可以读取包含空格在内的所有字符。char ch = file.get();
  4. 使用 read() 函数:用于读取二进制数据。file.read(buffer, size);
  5. 使用迭代器或 std::copy:搭配 istreambuf_iterator 遍历读取。

6. 如何向文件中写入数据?有哪些方式?

需要包含 <fstream>,并创建 ofstream(输出文件流)对象。打开时可以指定模式如 ios::out(默认,覆盖)、ios::app(追加)、ios::binary(二进制)。
主要方式有:

  1. 使用流插入运算符 <<:格式化写入,方便写入文本。file << "Hello" << 123 << endl;
  2. 使用 put() 函数:写入单个字符。file.put('A');
  3. 使用 write() 函数:用于写入二进制数据。file.write(buffer, size);
  4. 使用 std::copy 搭配 ostream_iterator:将容器中的数据直接写入文件。

7. 字符串流stringstream有什么作用?

stringstream<sstream> 头文件中提供的类(包括 istringstreamostringstreamstringstream),它的作用是在内存中操作字符串,将字符串当作流来处理。主要作用包括:

  1. 数据类型转换:无需使用 sprintfatoi。可以轻松实现 intstring,或者 stringint/double。例如:
    stringstream ss;
    ss << 123; 
    string str = ss.str(); // int转string
    
  2. 字符串分割与解析:可以像读取 cin 一样,利用 >> 运算符自动按空格分割字符串。
  3. 格式化拼接:将多个不同类型的变量拼接成一个复杂的字符串,比字符串加法更灵活,尤其适合格式化输出。
  4. 清空流:注意 ss.clear() 清空状态,ss.str("") 清空内容。