我想做的是将函数内的所有输出写入文件。也许我需要一种方法来将 test_func 中的所有输出(不仅是数组)分配给某种变量,以便我可以返回它,但我无法弄清楚。
#include <iostream>
#include <fstream>
#include <functional>
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()>test_func)
{
ofstream ofile;
ofile.open("abc.txt");
ofile << test_func(); // This is not allowed
ofile.close();
}
int main()
{
write_to_file(test_func);
return 0;
}
我需要从 test_func 而不是仅从数组a和b中获取所有输出,因为我有多个格式不同的函数,所有这些都需要使用相同的函数 write_to_file 写入文件。有什么逻辑方法可以做到这一点吗? (或替代功能?)
最佳答案
这是一些可以按照您想要的方式工作的代码。您必须用其中一个文件流替换std::cout
的当前rdbuf()
,然后再将其重置:
void write_to_file(function<void()>test_func) {
ofstream ofile;
ofile.open("abc.txt");
std::streambuf* org = cout.rdbuf(); // Remember std::cout's old state
cout.rdbuf(ofile.rdbuf()); // Bind it to the output file stream
test_func(); // Simply call the anonymous function
cout.rdbuf(org); // Reset std::cout's old state
ofile.close();
}
在这里,您可以看到它按预期运行: Demo 要克服函数签名变化的问题,可以使用委托(delegate)的lambda函数:
void test_func2(double a, int b) {
cout << a << " * " << b << " = " << (a * b) << endl;
}
int main() {
// Create a lambda function that calls test_func2 with the appropriate parameters
auto test_func_wrapper = []() {
test_func2(0.356,6);
};
write_to_file(test_func_wrapper); // <<<<< Pass the lambda here
// You can also forward the parameters by capturing them in the lambda definition
double a = 0.564;
int b = 4;
auto test_func_wrapper2 = [a,b]() {
test_func2(a,b);
};
write_to_file(test_func_wrapper2);
return 0;
}
Demo 您甚至可以使用一个小的帮助程序类来做到这一点,该类可以概括所有
std::ostream
类型的情况:class capture {
public:
capture(std::ostream& out_, std::ostream& captured_) : out(out_), captured(captured_), org_outbuf(captured_.rdbuf()) {
captured.rdbuf(out.rdbuf());
}
~capture() {
captured.rdbuf(org_outbuf);
}
private:
std::ostream& out;
std::ostream& captured;
std::streambuf* org_outbuf;
};
void write_to_file(function<void()>test_func)
{
ofstream ofile;
ofile.open("abc.txt");
{
capture c(ofile,cout); // Will cover the current scope block
test_func();
}
ofile.close();
}
Demo 因此,关于您的comment:
我们现在手边一切都可以做到这一点
#include <iostream>
#include <fstream>
#include <functional>
#include <string>
#include <sstream>
using namespace std;
void test_func1(const std::string& saySomething) {
cout << saySomething << endl;
}
void test_func2(double a, int b) {
cout << "a * b = " << (a * b) << endl;
}
class capture {
public:
capture(std::ostream& out_, std::ostream& captured_) : out(out_), captured(captured_), org_outbuf(captured_.rdbuf()) {
captured.rdbuf(out.rdbuf());
}
~capture() {
captured.rdbuf(org_outbuf);
}
private:
std::ostream& out;
std::ostream& captured;
std::streambuf* org_outbuf;
};
int main() {
std::string hello = "Hello World";
auto test_func1_wrapper = [hello]() {
test_func1(hello);
};
double a = 0.356;
int b = 6;
auto test_func2_wrapper = [a,b]() {
test_func2(a,6);
};
std::stringstream test_func1_out;
std::stringstream test_func2_out;
std::string captured_func_out;
{ capture c(test_func1_out,cout);
test_func1_wrapper();
}
{ capture c(test_func2_out,cout);
test_func2_wrapper();
}
captured_func_out = test_func1_out.str();
cout << "test_func1 wrote to cout:" << endl;
cout << captured_func_out << endl;
captured_func_out = test_func2_out.str();
cout << "test_func2 wrote to cout:" << endl;
cout << captured_func_out << endl;
}
当然还有 Demo 。