使用istream处理输入
本节阅读量:iostream库相当复杂——因此我们无法在这些教程中完整地介绍它。这里,将向您展示最常用的功能。在本节中,将研究输入类(istream)的各个方面。
提取操作符
在许多课程中都可以看到,可以使用提取操作符(»)从输入流中读取信息。C++为所有内置数据类型预定义了提取操作,并且之前我们也介绍了如何为自定义的类重载提取操作符。
读取字符串时,提取操作符的一个常见问题是如何防止输入溢出缓冲区。以下示例:
|
|
如果用户输入18个字符会怎么样?缓冲区溢出,导致的非预期行为没人能预料到了。一般来说,假设用户将输入字符的格式是有问题。
处理此问题的一种方法是使用操纵器。操纵器是与提取(>>)或插入(<<)操作符一起应用时,用于修改stream行为的对象。您已经使用过的一个操纵器是“std::endl”,它既打印换行符,又清空缓冲区。C++提供了一个称为setw(在iomanip头文件中)的操纵器,可用于限制从流中读入的字符数。要使用setw(),只需提供读取的最大字符数作为参数,并将其插入到输入语句中,如下所示:
|
|
该程序现在将仅从流中读取前9个字符(为终止符留出空间)。任何剩余的字符都将保留在流中,直到下一次提取。
提取和空白
作为提示,提取操作符跳过空白(空格、制表符和换行符)。
看看下面的程序:
|
|
当用户输入以下内容时:
|
|
提取操作符跳过空格和换行。因此,输出是:
|
|
通常,希望获得用户输入,不应该丢弃空白。
为此,istream类提供了许多可以用于此目的的函数。最有用的一个是get()函数,它从输入流中获取原始字符。
下面是与上面相同的程序,使用get():
|
|
现在,当我们使用输入时:
|
|
输出是:
|
|
还有一个字符串版本,它需要设置读取的最大字符数量:
|
|
如果我们输入:
|
|
输出是:
|
|
注意,我们只读取前10个字符(必须为终止符保留一个字符)。其余字符留在输入流中。
关于get()需要注意的一件重要事情是,它不读取换行符!这可能会导致一些意外的结果:
|
|
如果用户输入:
|
|
程序将打印:
|
|
然后终止!它为什么不多再读取10个字符?答案是因为第一个get()读取到换行,然后停止。第二个get()看到cin流中仍然有输入,并试图读取它。但第一个字符是换行符,因此它立即停止。
因此,还有一个名为getline()的函数,其工作方式类似于get(),但将提取(并丢弃)分隔符。
|
|
此代码将按预期执行,即使用户输入的字符串中包含换行符。
如果需要知道上次调用getline()提取了多少字符,请使用gcount():
|
|
gcount()包括任何提取和丢弃的分隔符。
用于std::string的getline()的特殊版本
getline()有一个特殊版本,位于istream类之外,用于读取数据到std::string。此特殊版本不是ostream或istream的成员,并包含在string头文件中。下面是它的用法示例:
|
|
几个更有用的istream函数
有几个您可能想使用的更有用的输入函数:
- ignore() 丢弃流中的第一个字符。
- ignore(int nCount) 丢弃前nCount字符。
- peek() 允许您从流中读取字符,而不将其从流中删除。
- unget() 将流中的最后读取一个字符塞回去,以便下次调用可以再次读取它。
- putback(char ch) 允许您将所选的字符放回流中,以便下一次调用读取。
istream包含许多其他函数和上述函数的变体,这些函数可能有用,具体取决于您需要执行的操作。您可以在这里找到对应的文档。
