如何捕获C++函数的标准输出并写入文件?
这个需求我之前做项目的时候碰到过,刚好有两种很实用的方案,你可以根据能不能修改原函数来选:
方案一:让函数接受输出流参数(推荐,更灵活)
问题出在你原来的test_func硬编码用cout输出,导致输出目标固定死了。我们可以把函数改成接受一个ostream&参数,这样它既可以输出到控制台,也能输出到文件流,完美适配你的write_to_file函数。
修改后的完整代码:
#include <iostream> #include <fstream> #include <functional> #include <ostream> using namespace std; // 修改函数,接受ostream&参数,默认输出到cout(不影响原有调用) void test_func(ostream& os = cout) { int a[] = {20,42,41,40}; int b[] = {2,4,2,1}; os << "Below is the result: "<< endl; for (int i=0; i<4; i++){ os << "***********************" << endl; os << a[i] << " : " << b[i] <<endl; os << "-----------------------" << endl; } } // 现在write_to_file可以接收所有接受ostream&的函数 void write_to_file(function<void(ostream&)> func) { ofstream ofile("abc.txt"); if (ofile.is_open()) { func(ofile); // 直接把文件流传给函数,函数输出内容会写入文件 ofile.close(); } else { cerr << "Failed to open file!" << endl; } } int main() { // 用lambda把test_func包装进去,或者直接传test_func(因为有默认参数) write_to_file([](ostream& os){ test_func(os); }); // 原来的调用方式依然有效,会输出到控制台 // test_func(); return 0; }
这种方式的好处是输出目标完全灵活,不管是控制台、文件还是内存流(比如stringstream)都能支持,而且write_to_file可以统一处理所有格式的函数,只要它们能接受ostream&参数。
方案二:重定向cout缓冲区(无需修改原函数)
如果你没法修改现有的函数(比如这些函数是第三方库或者已经上线的代码),那可以通过重定向cout的底层缓冲区来捕获所有输出,完全不用动原函数的代码。
完整代码示例:
#include <iostream> #include <fstream> #include <functional> #include <ostream> using namespace std; // 原函数保持不变,完全不用修改 void test_func() { int a[] = {20,42,41,40}; int b[] = {2,4,2,1}; cout << "Below is the result: "<< endl; for (int i=0; i<4; i++){ cout << "***********************" << endl; cout << a[i] << " : " << b[i] <<endl; cout << "-----------------------" << endl; } } void write_to_file(function<void()> func) { ofstream ofile("abc.txt"); if (!ofile.is_open()) { cerr << "Failed to open file!" << endl; return; } // 保存cout原来的缓冲区,之后要恢复 streambuf* old_cout_buf = cout.rdbuf(); // 把cout的缓冲区替换成文件流的缓冲区 cout.rdbuf(ofile.rdbuf()); // 调用函数,此时所有cout输出都会写入文件 func(); // 恢复cout的原始缓冲区,不然之后cout会一直输出到文件 cout.rdbuf(old_cout_buf); ofile.close(); } int main() { write_to_file(test_func); // 之后调用test_func()依然会输出到控制台 return 0; }
这个方法的原理是临时替换cout的输出目标,调用完函数再恢复。注意:如果是多线程程序,这个方法要谨慎使用,因为cout是全局对象,重定向期间其他线程的cout输出也会被写到文件里。单线程环境下这个方案非常省心。
内容的提问来源于stack exchange,提问作者Omia
相关产品推荐
相关产品推荐

