我想做的是将函数内的所有输出写入文件。也许我需要一种方法来将 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

10-04 10:18
查看更多