在使用C++进行程序开发过程中,免不了对std::cout\cerr的使用。我一般用于打印程序运行中的一些关键信息,以便于后面维护时方便灭虫。这两个输出语句都是将信息打印到控制台中,如果是GUI程序,那总不能在程序运行的时候还让控制台也跟着启动吧,这很不优雅。
比较好做法是将这些信息输出到特定的文件中,这样既不用带着控制台,又可以在程序崩溃之后,也能在文件中找到程序运行的流程。要实现这样功能我们需要对std::cerr\cout进行重定向。
重定向
这里主要使用ruduf函数来进行重定向
streambuf* rdbuf() const; streambuf* rdbuf (streambuf* sb);
这个函数在std::ios中被定义,共有两个原型,第一个是返回ios对象的缓冲区指针,第二个是为ios对象设置一个缓冲区,并将老的缓冲区返回。
想要在调用std::cerr时,将信息输入到文件中,只需要实例化一个fstresam对象,并将对象的缓冲区放入std::cerr中,就可以实现。
#include <iostream> #include <fstream> int main() { std::streambuf *psbuf, *backup; std::ofstream filestr; filestr.open("test.txt"); backup = std::cerr.rdbuf(); psbuf = filestr.rdbuf(); std::cerr.rdbuf(psbuf); std::cerr << "This is written to the file"; std::cerr.rdbuf(backup); filestr.close(); return 0; }
嗯~,完美实现功能~~~(骗你的QAQ),不过这样正常输出信息到文件是没有问题的。
这里使用的文件流类是ofstream而不是fstream,是因为在多线程编程中,fstream的缓冲区似乎不是线程安全的,运行时会出现访问冲突。而ofstream没有这样的问题。
打印信息到自定义窗口
因为将输出重定向了,要打印信息到窗口上还是比较容易的,只需要将fstream换成sstream,之后再获取sstream中的流信息即可。
获取的时候有两种选择方式。一种是主动获取,比如开启一个定时器,不停的读取sstream中的信息,获取到信息之后输出到窗口上。第二种是如果能获取到缓冲区被输入的这个事件,那么这个时候再去读取数据。
两种方法我选了第一种。
inputText(QString::fromLocal8Bit(sstream->str().c_str())); sstream->str("");
相比第一种,第二种肯定是节省了许多效率的,但是我不会啊。查阅了许多资料也未果。。哭唧唧。
好在后来学会了第二种,传送门: http://cppdebug.com/?p=125
参考资料:
https://stackoverflow.com/questions/12826751/c-execute-function-any-time-a-stream-is-written-to
文章评论
qt封装的控制台类是哪个类
@Uman QProcess,这个网上搜一下应该有挺多的示例的
有没有办法让一个gui程序支持控制台输入输出,同时点开GUI程序的时候不会弹出控制台
@Uman 可以的,实现的方法有很多,我之前用QT做过一个说的这种需求,QT提供了封装好的控制台类,我在这个基础上实现了GUI
@大脸猫 具体有什么例子吗