1.Streams
cin,cout
何时提示用户输入?
当位置指针达到文件结尾(EOF)并且超过了缓冲区中的最后一个标记时,程序会挂起并等待用户输入。
为什么 cout 操作不会立即将输出打印到控制台?输出什么时候才会被打印?
因为 cout 的输出只是输出到了缓冲区,需要对缓冲区进行刷新才会打印到控制台。
输出刷新的三种情况:
- 使用
cout << endl; - 使用
cout << flush; - 当 cin 正在等待用户输入时。
- 使用
在 >> 操作中,位置指针是在 token 前还是 token 后跳过空白字符?位置指针是否总是读取到空白字符?如果不是,请提供一个反例。
位置指针执行以下操作:
- 在读取前跳过所有空白字符(空格、换行符等)。
- 读取字符,直到满足以下条件之一:
- 遇到空白字符
- 对于原始数据类型,读取足够多的字符以形成有效的变量
- 例如:如果从字符串 "86.2" 中提取一个整数,将得到 86,位置指针停在小数点之后。
读写文件
头文件和类型
- 头文件:
<fstream> - 类型:
ifstream:用于从文件读取。ofstream:用于向文件写入。fstream:可用于读写。
创建和使用流
- 创建
ifstream实例:
1 | |
- 使用
open方法打开文件:
1 | |
文件打开检查
- 检查文件是否成功打开:
1 | |
注意事项
- 使用
ofstream写入不存在的文件时,会创建新文件;若文件已存在,则覆盖内容。 - 由于
open函数较早,因此使用 C++ 字符串时,需将其转换为 C 风格字符串(.c_str())。
流操纵符(Stream Manipulators)
头文件和常用操纵符
- 头文件:
<iomanip> setw:设置输出宽度。setfill:设置填充字符。
示例
1 | |
其他流操纵符
boolalpha:布尔值的文字输出。hex,dec,oct:设置数值的输出进制。
处理流错误
- 流错误可能发生在类型不匹配或读取失败的情况下。
- 流错误会使后续操作失败。
检查错误状态
- 使用
.fail()检查流的错误状态。
1 | |
上述的 while (true) 写法有些复杂,可以使用以下形式进行简化:
1 | |
cin和>>导致的错误
常见问题
cin读取整行数据但仅提取空白分隔的标记。- 缓冲区中的残留数据可能导致
cin在错误的时机等待输入。 cin失败后,所有后续操作也会失败。
示例和问题解释
1 | |
getline 的使用
问题与解决方案
- 使用
>>读取可能导致问题,而getline可以避免这些问题。 getline读取直到换行符,并存储在字符串中。
示例
1 | |
流操作符混用错误
与流提取操作符不同,getline 不会跳过流中仍然存在的空白字符。
1 | |
因此getline会找到cin输入中剩下的换行符,读取并丢弃,最后返回空字符串。
stringstream
概述和用法
- 头文件:
<sstream> - 用于在内存中的字符串缓冲区中读写数据。
示例
1 | |
另一个示例:
1 | |
综合实例:编写 getInteger 函数
在编写函数 getInteger 时,需要解决用户输入可能引发的两种错误:
- 用户可能会输入非整数,导致
cin失败。 - 用户可能会输入过多的数据,例如 "137 246",导致操作成功,但留下额外的数据可能会干扰后续读取。
为解决这些问题,可以采用以下方法:
- 使用
getline从输入中读取整行数据,以便完整接受用户输入。 - 将所读数据保存在
stringstream对象中,然后再从中使用>>进行数据提取,同时检查stringstream对象的状态。 - 读取完数据后,再次使用
>>从stringstream对象中尝试读取数据。如果能够读取数据,说明用户输入过多。
下面是示例代码:
1 | |
示例代码
1.Streams
https://ci-tz.github.io/2024/02/02/1-Streams/