如何在使用管道后将std :: cin恢复到键盘?

时间:2012-08-28 17:28:10

标签: c++ c++11

有问题的代码:

#include <array>
#include <iostream>
#include <cstring>

int main(int argc, char *argv[])
{
    using namespace std;

    cout << "Read from file:" << endl;

    while (!cin.eof())
    {
        array<char, 16> l_array;
        cin.read(l_array.data(), l_array.size());
        cout.write(l_array.data(), cin.gcount());
    }

    cout << endl;
    cout << "Read from keyboard:" << endl;

    cin.rdbuf(cout.rdbuf());

    while (!cin.eof())
    {
        array<char, 64> l_array;
        memset(l_array.data(), 0, l_array.size());
        cin.read(l_array.data(), l_array.size());

        cout << "===== DATA =====" << endl;
        cout << l_array.data() << endl;
        cout << "================" << endl;
    }
}

这就是我运行程序的方式:

./application < file.txt

我可以毫无问题地从管道中读取数据,但是当我想再次读取它时,它仍然与管道相关联。我不知道如何将其切换回来。我发现'rdbuf'功能可以改变它,但我不知道如何使用它。

当你用键盘切换到文件并返回键盘时,我只找到了例子。

像这里:http://www.cplusplus.com/reference/iostream/ios/rdbuf/

但我没有记住streambuf所以我不能像他们那样做。我想编写可以从文件中读取大部分数据的程序,只在缺少某些内容时询问,或者只是在运行时向用户询问有关permision的内容。 linux下的所有内部控制台。

@EDIT 谢谢你的帮助,我发布了解决方案

class RedirectCinToConsole
{
    protected:
        std::ifstream m_console;
        std::streambuf *m_oldCin;
        bool m_success;

    public:
        RedirectCinToConsole() :
            m_oldCin(0),
            m_success(false)
        {
            m_console.open("/dev/tty");

            if (m_console.is_open())
            {
                m_success = true;
                m_oldCin = std::cin.rdbuf(m_console.rdbuf());
            }
        }
        virtual ~RedirectCinToConsole()
        {
            if (m_oldCin)
            {
                std::cin.rdbuf(m_oldCin);
            }
            m_console.close();
        }

        operator bool () const { return m_success; }
};

int main()
{
    RedirectCinToConsole l_redirect;
    if (l_redirect)
    {
        std::string l_helloWorld;
        std::cin >> l_helloWorld;
        std::cin.ignore();

        std::cout << l_helloWorld;
    }
    return 0;
}

3 个答案:

答案 0 :(得分:6)

在我看来,无论提出的解决方案如何,最简单的方法 解决方案(可能是最好的)就是做相反的事情: 不要重定向输入,但将文件名传递给程序,然后让 它会打开std::ifstream来阅读它,让std::cin免费 互动输入。

Ben Voigt提出了标准的Unix解决方案,但是还在思考 关于它,似乎上面更自然;这肯定更容易 更便携。

答案 1 :(得分:3)

也许您应该使用fstream创建自己的流,并要求提供文件名或将文件名作为命令行参数。这将使cin可用于其他输入操作。

答案 2 :(得分:0)

尝试打开/dev/tty。这将是您的进程的关联控制台,如果有的话。如果您的进程是从守护进程启动的,则可能会失败。