捕获功能标准输出并将其写入文件 [英] Capture a functions standard output and write it to a file
问题描述
我想做的是将函数内部的所有输出写入文件.也许我需要一种方法来将 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::cout
s 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;
}
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();
}
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屋!