使用istream输入
iostream库相当复杂,因此我们无法在这些教程中完整地介绍它。但是,我们将向您展示最常用的功能。在本节中,我们将介绍输入类(istream)的各个方面。
注意:本课程中的所有I / O功能都位于std命名空间中。这意味着所有I / O对象和函数都必须以“std ::”为前缀,或者必须使用“using namespace std;”语句。
提取算子
正如现在许多课程中所见,我们可以使用提取运算符(>>)从输入流中读取信息。C ++为所有内置数据类型预定义了提取操作,您已经了解了如何为自己的类重载提取操作符。
读取字符串时,提取运算符的一个常见问题是如何防止输入溢出缓冲区。给出以下示例:
char buf[10];
cin >> buf;
如果用户输入18个字符会发生什么?缓冲区溢出,发生了不好的事情。一般来说,对用户将输入多少个字符进行任何假设都是一个坏主意。
解决这个问题的一种方法是使用操纵器。操纵器是用于当与提取(>>)或插入(<<)运算符应用于修改流的对象。你已经广泛使用的一个操纵器是“endl”,它既可以打印换行符,也可以刷新任何缓冲输出。C ++提供了一个称为setw的操作符(在iomanip.h头文件中),可用于限制从流中读入的字符数。要使用setw(),只需提供要作为参数读取的最大字符数,然后将其插入到输入语句中,如下所示:
#include <iomanip.h>
char buf[10];
cin >> setw(10) >> buf;
此程序现在只读取流中的前9个字符(为终结器留出空间)。任何剩余的字符将保留在流中,直到下一次提取。
提取和空格
到目前为止我们忽略的一件事是提取操作符使用“格式化”数据,也就是说,它跳过空格(空格,制表符和换行符)。
看看以下程序:
int main()
{
char ch;
while (cin >> ch)
cout << ch;
return 0;
}
当用户输入以下内容时:
Hello my name is Alex
提取运算符会跳过空格和换行符。因此,输出是:
HellomynameisAlex
通常情况下,您需要获取用户输入但不要丢弃空白。为此,istream类提供了许多可用于此目的的函数。
其中最有用的是get()函数,它只是从输入流中获取一个字符。这是与上面相同的程序使用get():
int main()
{
char ch;
while (cin.get(ch))
cout << ch;
return 0;
}
现在,当我们使用输入时:
Hello my name is Alex
输出是:
Hello my name is Alex
get()也有一个字符串版本,需要读取最多字符数:
int main()
{
char strBuf[11];
cin.get(strBuf, 11);
cout << strBuf << endl;
return 0;
}
如果我们输入:
Hello my name is Alex
输出是:
Hello my n
请注意,我们只读取前10个字符(我们不得不为终结符留下一个字符)。剩余的字符留在输入流中。
关于get()的一个重要注意事项是它不会读取换行符!这可能会导致一些意外结果:
int main()
{
char strBuf[11];
// 最多可读取10个字符
cin.get(strBuf, 11);
cout << strBuf << endl;
//最多可读取10个字符
cin.get(strBuf, 11);
cout << strBuf << endl;
return 0;
}
如果用户输入:
Hello!
该计划将打印:
Hello!
然后终止!为什么不再要10个字符呢?答案是因为第一个get()读取到换行符然后停止。第二个get()看到cin流中仍有输入并尝试读取它。但是第一个字符是换行符,所以它立即停止了。
因此,还有一个名为getline()的函数与get()完全相同,但也会读取换行符。
int main()
{
char strBuf[11];
// 最多10个字符
cin.getline(strBuf, 11);
cout << strBuf << endl;
// 最多可读取10个字符
cin.getline(strBuf, 11);
cout << strBuf << endl;
return 0;
}
即使用户输入带有换行符的字符串,此代码也会按预期执行。
如果您需要知道上次调用getline()时提取了多少字符,请使用gcount():
int main()
{
char strBuf[100];
cin.getline(strBuf, 100);
cout << strBuf << endl;
cout << cin.gcount() << " characters were read" << endl;
return 0;
}
std :: string的特殊版本的getline()
有一个特殊版本的getline(),它位于istream类之外,用于读取std :: string类型的变量。此特殊版本不是ostream或istream的成员,并且包含在字符串标头中。以下是其使用示例:
#include <string>
#include <iostream>
int main()
{
using namespace std;
string strBuf;
getline(cin, strBuf);
cout << strBuf << endl;
return 0;
}
一些更有用的istream函数
您可能希望使用一些更有用的输入函数:
ignore()丢弃流中的第一个字符。
ignore(int nCount)丢弃第一个nCount字符。
peek()允许您从流中读取字符而不从流中删除它。
unget()返回读回流中的最后一个字符,以便下次调用时再次读取它。
putback(char ch)允许您将您选择的字符放回流中,以便下次调用时读取。
istream包含上述功能的许多其他功能和变体,可能很有用,具体取决于您需要做什么。但是,这些主题更适合专注于标准库的教程或书籍(例如Nicolai M. Josuttis 出色的“The C ++ Standard Library”)。