C++关于std::cerr\cout\cin的重定向

2021年1月23日 8656点热度 4人点赞 5条评论

在使用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("");

相比第一种,第二种肯定是节省了许多效率的,但是我不会啊。查阅了许多资料也未果。。哭唧唧。

2021.3.8更新

好在后来学会了第二种,传送门: http://cppdebug.com/?p=125

 

 

参考资料:

https://stackoverflow.com/questions/12826751/c-execute-function-any-time-a-stream-is-written-to

http://www.cplusplus.com/reference/ios/ios/rdbuf/

大脸猫

这个人虽然很勤快,但什么也没有留下!

文章评论

  • Uman

    qt封装的控制台类是哪个类

    2024年11月12日
    • 大脸猫

      @Uman QProcess,这个网上搜一下应该有挺多的示例的

      2024年11月13日
  • Uman

    有没有办法让一个gui程序支持控制台输入输出,同时点开GUI程序的时候不会弹出控制台

    2024年11月11日
    • 大脸猫

      @Uman 可以的,实现的方法有很多,我之前用QT做过一个说的这种需求,QT提供了封装好的控制台类,我在这个基础上实现了GUI

      2024年11月12日
      • Uman

        @大脸猫 具体有什么例子吗

        2024年11月12日