【问题标题】:std::cin: empty the input buffer without blockingstd::cin:清空输入缓冲区而不阻塞
【发布时间】:2014-01-20 11:39:41
【问题描述】:

this 问题的后续行动。

如何清除输入缓冲区?

sleep(2);
// clear cin
getchar();

我只想要最后输入的字符,我想丢弃在程序休眠时输入的任何输入。有没有办法做到这一点?

另外,我不想主动等待清除cin,因此我不能使用ignore()。

我的方法是获取缓冲区的当前大小,如果它不等于 0,则静默清空缓冲区。但是,我还没有找到获取缓冲区大小的方法。 std::cin.rdbuf()->in_avail() 总是为我返回 0。 peek() 也会主动等待。

我不想使用 ncurses。

【问题讨论】:

  • 所以sleep 完成并且在getchar 开始使用之前输入一个字符。这算不算?
  • 这是一个我还没有考虑过的案例,但对于这个问题暂时不重要。
  • @EdHeal:我个人认为这种情况和“在睡眠期间”实际上无法区分,特别是因为sleep(2) 是“2 秒或更多”。

标签: c++


【解决方案1】:

拥有支持 tcgetattr/tcsetattr 的系统:

#include <iostream>
#include <stdexcept>

#include <termios.h>
#include <unistd.h>

class StdInput
{
    // Constants
    // =========

    public:
    enum {
        Blocking = 0x01,
        Echo = 0x02
    };

    // Static
    // ======

    public:
    static void clear() {
        termios attributes = disable_attributes(Blocking);
        while(std::cin)
            std::cin.get();
        std::cin.clear();
        set(attributes);
    }

    // StdInput
    // ========

    public:
    StdInput()
    :   m_restore(get())
    {}

    ~StdInput()
    {
        set(m_restore, false);
    }

    void disable(unsigned flags) { disable_attributes(flags); }
    void disable_blocking() { disable_attributes(Blocking); }
    void restore() { set(m_restore); }

    private:
    static termios get() {
        const int fd = fileno(stdin);
        termios attributes;
        if(tcgetattr(fd, &attributes) < 0) {
            throw std::runtime_error("StdInput");
        }
        return attributes;
    }

    static void set(const termios& attributes, bool exception = true) {
        const int fd = fileno(stdin);
        if(tcsetattr(fd, TCSANOW, &attributes) < 0 && exception) {
            throw std::runtime_error("StdInput");
        }
    }

    static termios disable_attributes(unsigned flags) {
        termios attributes = get();
        termios a = attributes;
        if(flags & Blocking) {
            a.c_lflag &= ~ICANON;
            a.c_cc[VMIN] = 0;
            a.c_cc[VTIME] = 0;
        }
        if(flags & Echo) {
            a.c_lflag &= ~ECHO;
        }
        set(a);
        return attributes;
    }

    termios m_restore;
};


int main()
{
    // Get something to ignore
    std::cout << "Ignore: ";
    std::cin.get();

    // Do something

    StdInput::clear();

    std::cout << " Input: ";
    std::string line;
    std::getline(std::cin, line);
    std::cout << "Output: " << line << std::endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 2018-04-02
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多