捕获功能标准输出并将其写入文件 [英] Capture a functions standard output and write it to a file

查看:50
本文介绍了捕获功能标准输出并将其写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的是将函数内部的所有输出写入文件.也许我需要一种方法来将 test_func 中的所有输出(不仅是数组)分配给某种变量,以便我可以返回它,但无法弄清楚.

  #include< iostream>#include< fstream>#include< functional>使用命名空间std;无效test_func(){int a [] = {20,42,41,40};int b [] = {2,4,2,1};cout<<以下是结果:<<恩德尔为(int i = 0; i< 4; i ++){cout<<" ************************"<<恩德尔cout<<a [i]<<":"<<b [i]<< endl;cout<<" -----------------------"<<恩德尔}}无效write_to_file(function< void()> test_func){ofofofile;ofile.open("abc.txt");ofile<<test_func();//这是不允许的ofile.close();}int main(){write_to_file(test_func);返回0;} 

我需要从 test_func 中获取所有输出,而不是仅从数组a和b中获取所有内容,因为我有多种格式不同的函数,都需要使用相同的函数将其写入文件 write_to_file .

有没有合乎逻辑的方法来做到这一点?(或替代功能?)

解决方案

下面是一些可以按照您想要的方式工作的代码.您必须用其中一个文件流替换 std :: cout 的当前 rdbuf(),然后将其重置:

  void write_to_file(function< void()> test_func){ofofofile;ofile.open("abc.txt");std :: streambuf * org = cout.rdbuf();//记住std :: cout的旧状态cout.rdbuf(ofile.rdbuf());//将其绑定到输出文件流test_func();//只需调用匿名函数cout.rdbuf(org);//重置std :: cout的旧状态ofile.close();} 

在这里您可以看到它按预期运行: 演示


要克服函数签名变化的问题,可以使用委托的lambda函数:

  void test_func2(double a,int b){cout<<<<"*"<<b<<"="<<(a * b)<<恩德尔}int main(){//创建一个lambda函数,该函数使用适当的参数调用test_func2自动test_func_wrapper = [](){test_func2(0.356,6);};write_to_file(test_func_wrapper);//<<<<<在这里传递lambda//您也可以通过在lambda定义中捕获参数来转发参数双a = 0.564;int b = 4;自动test_func_wrapper2 = [a,b](){test_func2(a,b);};write_to_file(test_func_wrapper2);返回0;} 

演示


您甚至可以使用一个小的帮助程序类来做到这一点,该类可以概括任何 std :: ostream 类型的情况:

 类捕获{上市:capture(std :: ostream& out_,std :: ostream& capture_):out(out _),captured(captured _),org_outbuf(captured_.rdbuf()){capture.rdbuf(out.rdbuf());}〜capture(){capture.rdbuf(org_outbuf);}私人的:std :: ostream&出去;std :: ostream&被俘std :: streambuf * org_outbuf;};无效write_to_file(function< void()> test_func){ofofofile;ofile.open("abc.txt");{捕获c(ofile,cout);//将覆盖当前的作用域块test_func();}ofile.close();} 

演示


因此,关于您的评论:

当然可以,但是我将需要一些东西来存储这些cout,或者也许还有另一种完全不同的方法来代替在过程中使用test_func()?

我们现在手边一切都可以做到

  #include< iostream>#include< fstream>#include< functional>#include< string>#include< sstream>使用命名空间std;无效的test_func1(const std :: string& saySomething){cout<<saySomething<<恩德尔}无效的test_func2(double a,int b){cout<<" a * b ="<<(a * b)<<恩德尔}类捕获{上市:capture(std :: ostream& out_,std :: ostream& capture_):out(out _),captured(captured _),org_outbuf(captured_.rdbuf()){capture.rdbuf(out.rdbuf());}〜capture(){capture.rdbuf(org_outbuf);}私人的:std :: ostream&出去;std :: ostream&被俘std :: streambuf * org_outbuf;};int main(){std :: string hello ="Hello World";自动test_func1_wrapper = [hello](){test_func1(你好);};双a = 0.356;int b = 6;自动test_func2_wrapper = [a,b](){test_func2(a,6);};std :: stringstream test_func1_out;std :: stringstream test_func2_out;std :: string capture_func_out;{捕获c(test_func1_out,cout);test_func1_wrapper();}{捕获c(test_func2_out,cout);test_func2_wrapper();}capture_func_out = test_func1_out.str();cout<<"test_func1写入cout:"<<恩德尔cout<<capture_func_out<<恩德尔capture_func_out = test_func2_out.str();cout<<"test_func2写入cout:"<<恩德尔cout<<capture_func_out<<恩德尔} 

当然还有 演示 .

What I try to do is to write all output inside a function into a file. Maybe I need a way to assign all output (not only arrays) in test_func to some kind of variable so that I can return it, but I can't figure out.

#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;
}

I need to get all output from test_func instead of only the array a and b, because I have multiple functions in different formats, which are all needed to write into the file using same function write_to_file.

Is there any logical way to do this? (or alternative to function?)

解决方案

Here is some code that will work the way you want. You have to replace std::couts current rdbuf() with the one of the file streams, and reset it afterwards:

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();
}

Here you can see it running as you intended: Demo


To overcome the problem with the varying function signatures, you can use a delegating lambda function:

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


You can even do this with a little helper class, which generalizes the case for any std::ostream types:

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


So regarding your comment:

Sure, but I will require something to store those cout, or maybe there's another completely different way instead of using test_func() for the process?

We have everything at hand now to do this

#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;
}

And the Demo of course.

这篇关于捕获功能标准输出并将其写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆