重定向控制台流后使用cin时cout失败

时间:2010-09-10 01:39:16

标签: c++

我想将控制台流重定向到cin,cout和cerr。 (它的gui申请) 好吧,我已经写了这个类,但是当使用cin时,cout不再工作了。

GetLastError告诉我INVALID_HANDLE VALUE

你能解释一下如何解决这个问题吗? 感谢

Kconsole.h
class Kconsole
{

    public:

        Kconsole();
        ~Kconsole();                

        void CreateConsole( void );
        void CloseConsole ( void );

    private:


        HANDLE hin;
        HANDLE hout;
        HWND hwnd;

        bool closed;
        bool err;       

        ofstream n_cout;
        ofstream n_cerr; // new streams
        ifstream n_cin;

        streambuf* old_cout;
        streambuf* old_cerr; // old streams
        streambuf* old_cin;

};

班级方法:

void Kconsole::CreateConsole( void ){

// create a console window
int ok = AllocConsole();

if ( ok == 0 ) // check console creation
{

    this->err = true;
    return;        
}    

// redirect cout to console window
this->old_cout = cout.rdbuf();    
this->n_cout.open("CONOUT$");    
cout.rdbuf( this->n_cout.rdbuf() );

// redirect cerr
this->old_cerr = cerr.rdbuf();
this->n_cerr.open("CONOUT$");
cerr.rdbuf( this->n_cerr.rdbuf() );

// redirect cin
this->old_cin = cin.rdbuf();
this->n_cin.open("CONIN$");
cin.rdbuf( this->n_cin.rdbuf() );

//// set title
SetConsoleTitle("Console");
this->hwnd = GetConsoleWindow();
//
//// get handles
this->hin = GetStdHandle(STD_OUTPUT_HANDLE);    
this->hout = GetStdHandle(STD_OUTPUT_HANDLE); 
return;}

主要功能

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,intnCmdShow){

 // All application initialization as RegisterClass, CreateWindow...

// CreateConsole Call

cout << "\nTest string"; // ok, writes this in opened console

int n = 0;

cin >> n; // ok, get typed number
n++;

cout << "\n test finished"; // dont outputs nothing to console

// here GetLastError says INVALID_HANDLE_VALUE

cerr << "\n testing cerr" // cerr outputs in console " test finished" and "testing cerr"
}

4 个答案:

答案 0 :(得分:1)

我不明白为什么你要弄乱std::cout et al。如果您将stdoutstderrstdin重定向到控制台,则可以致电std::ios::sync_with_stdio()以确保std::coutstd::cerr和{{1一切顺利。 E.g:

std::cin

这是一篇很棒的文章(有来源),explains一切。

答案 1 :(得分:0)

您似乎用fstream两次打开同一个文件。

this->old_cout = cout.rdbuf();    
this->n_cout.open("CONOUT$");    // open for writing #1
cout.rdbuf( this->n_cout.rdbuf() );

// redirect cerr
this->old_cerr = cerr.rdbuf();
this->n_cerr.open("CONOUT$");    // open for writing #2
cerr.rdbuf( this->n_cerr.rdbuf() );

即使您的操作系统支持此功能,现在还有两个独立的I / O缓冲区试图控制该文件。如果您尝试同时使用它们,则会导致输出乱码。

coutcerr发送到不同的文件,或对两者使用相同的filebuf

this->old_cout = cout.rdbuf();    
this->n_cout.open("CONOUT$");    
cout.rdbuf( this->n_cout.rdbuf() );

// redirect cerr
this->old_cerr = cerr.rdbuf();
cerr.rdbuf( this->n_cout.rdbuf() ); // same filebuf

我认为这仍然有点不稳定,但它应该得到标准的支持。

答案 2 :(得分:0)

为什么不将您的应用设为控制台应用?您仍然可以从控制台应用程序创建窗口,但这意味着总会有一个控制台,并且始终是标准的输入和输出流。

答案 3 :(得分:0)

麻烦在于使用cin,cout句柄关闭或释放后。 GetLastError表示代码6(ERROR_INVALID_HANDLE)

我试过打开CONOUT $一次就像你说的那样,尝试打开CONERR $而不是CONOUT $两次,也许通过CloseHandle手动关闭CONOUT $ handle并再次使用GetStdHandle(STD_OUTPUT_HANDLE)或CreateFile打开它。

在所有情况下,cout都不会打印任何内容。只有在使用cerr时才会写入剩余的所有内容。