写什么代码来清空缓冲区

在 C++ 中,清空输入缓冲区的方法主要用于清除 std::cin 输入流中的残留字符,避免它们影响后续的输入操作。下面介绍几种常用的办法。

1. cin.ignore() 方法

cin.ignore() 是最常用的清空缓冲区方法,可以忽略输入流中的若干字符。

  • cin.ignore(numeric_limits<streamsize>::max(), '\n');:

    • 忽略缓冲区中的所有字符,直到遇到换行符 \n

    • numeric_limits<streamsize>::max() 设置了一个非常大的忽略字符数,以确保足够多的字符被忽略。

    • 举一个例子

    #include <iostream>
    #include <limits> // 用于 numeric_limits
    using namespace std;
    
    int main() {
        char ch;
        cout << "请输入一个字符: ";
        cin >> ch;
    
        // 清空缓冲区
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    
        string line;
        cout << "请输入一行文字: ";
        getline(cin, line);
    
        cout << "您输入的字符是: " << ch << endl;
        cout << "您输入的行是: " << line << endl;
    
        return 0;
    }
    

    输出如下:

    img

    插一句题外话:

    如果不加cin.ignore(numeric_limits<streamsize>::max(), '\n');这句的话,输出会是这样的:

    img

    原因:

    在输入一个字符输入步骤中,cin >> ch; 会读取用户输入的一个字符,但它只读取一个字符的内容,用户在输入字符后可能还按了“回车键” (Enter),这会留在输入缓冲区里。如果不清空缓冲区,后续调用 getline(cin, line); 时,会直接读取缓冲区中残留的“回车”,导致 line 获得一个空字符串,无法读取到用户实际输入的内容。

    再附上c++_primer上的一段话来帮助理解:

    img

  • cin.ignore(1, '\n');:

    • 忽略一个字符(如换行符)。适用于需要跳过单个字符的情况。

    • 常用于输入特定字符后直接忽略后面的一个换行符。

2. cin.clear() 和 cin.sync()

在某些情况下,除了 cin.ignore() 外,还可能需要用 cin.clear()cin.sync(),尤其当 cin 的错误标志被设置时:

  • cin.clear();:

    • 清除 cin 的错误标志(如输入不符合期望的数据类型)。

      在这篇博客cin和scanf的返回值知多少提到过一点 cin 的错误标志。

    • 如果 cin 发生输入错误(如输入字符到整数变量),会设置错误标志,需要使用 cin.clear() 清除。

    • 清除错误标志后再配合 cin.ignore(),可以清空错误输入,并让 cin 恢复正常工作。

  • cin.sync();:

    • 清除输入缓冲区中所有内容。

    • 在某些编译器中,它可以立即清空缓冲区,但在一些平台上不一定完全可靠。

  • 举一个例子

    #include <iostream>
    using namespace std;
    
    int main() {
        int num;
        cout << "请输入一个整数: ";
        cin >> num;
    
        if (cin.fail()) {
            // 清除错误标志并清空缓冲区
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "输入无效,请重新输入一个整数。" << endl;
        }
    
        return 0;
    }
    

    输出如下:

    img

插一句题外话

对于上面这个例子,当我改成如下代码:

#include <iostream>
using namespace std;

int main() {
    int num;
    cout << "请输入一个整数: ";
    cin >> num;

    if (cin.fail()) {
        // 清除错误标志并清空缓冲区
        cin.clear();
        //cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "输入无效,请重新输入一个整数。" << endl;
    }

    char ch = cin.get();
    cout << "ch: " << ch << endl;
    return 0;
}

输出如下:

img

看了这个输出情况应该更能体会到cin.ignore(numeric_limits<streamsize>::max(), '\n');的作用了。

然后又试着改成这样:

#include <iostream>
using namespace std;

int main() {
    int num;
    cout << "请输入一个整数: ";
    cin >> num;

    //if (cin.fail()) {
    //    // 清除错误标志并清空缓冲区
    //    cin.clear();
    //    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    //    cout << "输入无效,请重新输入一个整数。" << endl;
    //}

    char ch = cin.get();
    cout << "ch: " << ch << endl;
    return 0;
}

输出如下:

img

在这种情况下,输出为“乱码”是因为当 cin >> num; 读取无效输入(字母 a)时,cin 会进入失败状态(即 fail 状态),并设置错误标志。由于 cin 处于失败状态,接下来的 cin.get() 也无法正常读取字符。

在失败状态下,cin.get() 不会从输入缓冲区中读取任何有效的字符,因此 ch 变量未被正确赋值,而是包含了一个未定义的值。这就是导致输出“乱码”或一个不可见字符的原因。

3. 使用 while (cin.get() != '\n'); 清除缓冲区

这是一个循环方法,用于逐个读取并丢弃缓冲区中的字符,直到遇到换行符。

  • while (cin.get() != '\n');:

    • 使用 cin.get() 读取每个字符,直到换行符结束。

    • 适合当不确定输入缓冲区有多少残留字符时,可以完全清空缓冲区。

  • 举一个例子:

    #include <iostream>
    using namespace std;
    
    int main() {
        char ch;
        cout << "请输入一个字符: ";
        cin >> ch;
    
        // 手动逐个读取并丢弃直到换行符
        while (cin.get() != '\n');
    
        string line;
        cout << "请输入一行文字: ";
        getline(cin, line);
    
        cout << "您输入的字符是: " << ch << endl;
        cout << "您输入的行是: " << line << endl;
    
        return 0;
    }
    

    输出如下:

    img

posted @ 2024-11-08 18:39  hisun9  阅读(28)  评论(0编辑  收藏  举报