如何在C ++中覆盖cout?

我有一个要求,我需要使用printfcout来显示数据到console and file 。 对于printf我已经做了,但对于我很挣扎,怎么做?

  #ifdef _MSC_VER #define GWEN_FNULL "NUL" #define va_copy(d,s) ((d) = (s)) #else #define GWEN_FNULL "/dev/null" #endif #include <iostream> #include <fstream> using namespace std; void printf (FILE * outfile, const char * format, ...) { va_list ap1, ap2; int i = 5; va_start(ap1, format); va_copy(ap2, ap1); vprintf(format, ap1); vfprintf(outfile, format, ap2); va_end(ap2); va_end(ap1); } /* void COUT(const char* fmt, ...) { ofstream out("output-file.txt"); std::cout << "Cout to file"; out << "Cout to file"; }*/ int main (int argc, char *argv[]) { FILE *outfile; char *mode = "a+"; char outputFilename[] = "PRINT.log"; outfile = fopen(outputFilename, mode); char bigfoot[] = "Hello World!\n"; int howbad = 10; printf(outfile, "\n--------\n"); //myout(); /* then i realized that i can't send the arguments to fn:PRINTs */ printf(outfile, "%s %i",bigfoot, howbad); /* error here! I can't send bigfoot and howbad*/ system("pause"); return 0; } 

我已经在COUT (caps,上面的代码的注释部分)中完成了它。 但我想使用正常的std::cout ,所以我怎么能覆盖它。 它应该适用于sting and variables

 int i = 5; cout << "Hello world" << i <<endl; 

或者无论如何要捕获stdout数据,以便他们可以很容易地写入file and console

重写std::cout的行为是一个非常糟糕的想法,因为其他开发人员很难理解使用std::cout行为不正常。

用简单的课程让你的意图清晰

 #include <fstream> #include <iostream> class DualStream { std::ofstream file_stream; bool valid_state; public: DualStream(const char* filename) // the ofstream needs a path : file_stream(filename), // open the file stream valid_state(file_stream) // set the state of the DualStream according to the state of the ofstream { } explicit operator bool() const { return valid_state; } template <typename T> DualStream& operator<<(T&& t) // provide a generic operator<< { if ( !valid_state ) // if it previously was in a bad state, don't try anything { return *this; } if ( !(std::cout << t) ) // to console! { valid_state = false; return *this; } if ( !(file_stream << t) ) // to file! { valid_state = false; return *this; } return *this; } }; // let's test it: int main() { DualStream ds("testfile"); if ( (ds << 1 << "\n" << 2 << "\n") ) { std::cerr << "all went fine\n"; } else { std::cerr << "bad bad stream\n"; } } 

这提供了一个干净的界面,并输出相同的控制台和文件。 您可能需要添加刷新方法或以附加模式打开文件。

如果你有另一个流缓冲区,你可以替换std::cout的:

 std::cout.rdbuf(some_other_rdbuf); 

请参阅http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf

你可以交换底层的缓冲区。 这是通过RAII完成的。

 #include <streambuf> class buffer_restore { std::ostream& os; std::streambuf* buf; public: buffer_restore(std::ostream& os) : os(os), buf(os.rdbuf()) { } ~buffer_restore() { os.rdbuf(buf); } }; int main() { buffer_restore b(std::cout); std::ofstream file("file.txt"); std::cout.rdbuf(file.rdbuf()); // ... } 

我假设你有一些代码使用std::coutprintf ,你不能修改,否则最简单的方法来解决你的问题将是从cout写入不同的流,并使用fprintf而不是与printf结合。

通过遵循这种方法,您可以定义一个新的流类,它既可以写入标准输出也可以写入给定的文件,也可以定义一个将调用结合到printffprintf printf

然而更简单的方法是使用最初来自UNIX的tee程序,它将输入复制到输出和给定文件。 有了这个,你可以简单地调用你的程序:

 your_program | tee your_log_file 

这个问题的答案导致了一些可用于Windows的替代实现。 就个人而言,我总是在我的电脑上安装cygwin ,以提供UNIX / Linux实用程序。

如果我猜对了,你想把所有输出到输出文件也记录下来。

你想要的是一个观察者模式 。

将代码中的所有直接日志记录替换为新的中继的调用。 记录中继将你的消息发送给观察者。 您的观察员之一将消息记录到屏幕上。 另一个登录到文件。 如果可能,避免让你的继电器单身。

如果您可以编辑所有的源文件,这个建议才有效。

std::cout写入stdout文件,您可以在Linux和Windows上执行以下操作

 #include <stdio.h> #include <iostream> int main() { freopen("test.txt", "w", stdout); std::cout << "Hello strange stdout\n"; } 

把它改回来,从这里拿走下面的内容

 #include <stdio.h> #include <stdlib.h> void main(void) { FILE *stream ; if((stream = freopen("file.txt", "w", stdout)) == NULL) exit(-1); printf("this is stdout output\n"); stream = freopen("CON", "w", stdout); printf("And now back to the console once again\n"); } 

注意:后者仅适用于Windows

cout通常是作为一个对象实例实现的,所以你不能以覆盖/覆盖函数或类的方式来覆盖它。

你最好的选择就是不去争取 – 是的,你可以建立一个my_cout#define cout my_cout但是这会让你的代码变得迟钝。

为了可读性,我会保持原样。 这是一个标准,每个人都知道它能做什么,不能做什么。

尝试使用宏 – 像这样(你需要添加包括):

 #define MY_COUT(theos,printThis) { cout << printThis ; theos << printThis; } void test() { ofstream myos; myos.open("testfile", ios::trunc|ios::out); int i = 7; MY_COUT(myos, "try this numbers" << i << i + 1 << endl); myos.close() } 

现在已经有了一个Boost类: tee