C++基础教程面向对象(学习笔记(102))

使用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”)。

猜你喜欢

转载自blog.csdn.net/qq_41879485/article/details/84880848