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

C++ 使用管道后如何将std::cin恢复到键盘?,c++,c++11,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&g

问题代码:

#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;
    }
}
#包括

但我不记得streambuf,所以我不能像他们那样做。我想写一个程序,它可以读取文件中的大部分数据,并且只在缺少某些内容时询问,或者只是在运行时向用户询问权限之类的问题。都在linux下的控制台内

@编辑 谢谢你的帮助,我发布解决方案

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;
}
类重定向cintoconsole
{
受保护的:
std::ifstream m_控制台;
标准::streambuf*m_oldCin;
布尔穆尔成功;
公众:
重定向cintoconsole():
m_oldCin(0),
m_成功(错误)
{
m_控制台打开(“/dev/tty”);
if(m_console.is_open())
{
成功=真;
m_oldCin=std::cin.rdbuf(m_console.rdbuf());
}
}
虚拟~RedirectCinToConsole()
{
if(m_oldCin)
{
标准:cin.rdbuf(m_oldCin);
}
m_控制台。关闭();
}
运算符bool()常量{return m_success;}
};
int main()
{
重定向到控制台l_重定向;
如果(l_重定向)
{
std::字符串l_helloWorld;
标准::cin>>l_helloWorld;
std::cin.ignore();

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

尝试打开
/dev/tty
。如果有,这将是流程的关联控制台。如果我们的进程是从一个守护进程启动的,它可能会失败。

我觉得,不管建议的解决方案是什么,最简单的解决方案是什么 解决方案(可能是最好的)是做相反的事情: 不要重定向输入,而是将文件名传递给程序,让 它打开一个
std::ifstream
来读取它,让
std::cin
免费阅读 交互式输入

Ben Voigt提出了标准的Unix解决方案,但仍在思考中 关于这一点,似乎上述情况更为自然;这当然更为容易和有效
更方便。

首先,你是从文件中读取的,不是从管道读取的。第二,你必须使用一些依赖于系统的方法来查找你正在运行的终端(如果你在终端中运行)。信息不在标准C++中。最后:<代码>同时((!CIN)。
错了,错了,错了。当然,这是纯粹的Unix。我不知道你在Windows下会怎么做。(MS-DOS为控制台保留了一个名称。我想是“CONS”之类的。但是,我不知道它在Windows下是否仍然有效。)在Windows上,
创建文件(“CONIN$”,…)
。但是这个问题说的是Linux。我错过了。但是在Windows下也值得知道它的等价物。大概
std::filebuf;f.open(“CONIN$”,std::ios_base::in);
也会这样做。然后
std::streambuf*save=std::cout.rdbuf();std::cout.rdbuf(&theNewFileBuf)
并在他完成后还原保存的streambuf。(这正是您在Unix下使用
/dev/tty
所要做的。@James:假设特定库供应商的
filebuf::open
实现在打开文件时传递了正确的标志(我相信控制台需要
open\u现有的
),然后是。否则,您可以使用带有正确选项的
CreateFile
,然后跳过一些环,将
std::filebuf
与操作系统文件句柄关联起来。从技术上讲是可能的,所有这些都是可能的。但这不是适合此用户的正确解决方案。KISS。
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;
}