C++如何同时计算和写入
C++ how to cout and write at the same time
阅读此文后:C++ Writing to file and Console Output at the same time with simple code,我正在尝试编写一个函数来处理我在 for 循环中的内容。但是我不知道如何将这样的一段代码作为参数传递给函数:setw(3) << right << get<0>(*it_party) << setw(9) << ""
以便 cout 和 file 都可以使用它。
The helper function I am trying to write:
void print(std::ostream &os1, std::ostream &os2, const [I don't know what to put in here])
{
os1 << the argument; // cout
os2 << the argument; // file
}
ofstream file;
file.open("test.txt");
for (auto it_party = parties_.begin(); it_party != parties_.end(); ++it_party) {
cout << setw(3) << right << get<0>(*it_party) << setw(9) << "";
file << setw(3) << right << get<0>(*it_party) << setw(9) << "";
cout << setw(7) << left << get<1>(*it_party) << setw(1) << "";
file << setw(7) << left << get<1>(*it_party) << setw(1) << "";
...
...
}
如果你想像那样将输出串在一起,你可能会发现使用某种 "tee" class:
更容易
class Tee {
private:
std::ostream &os1, &os2;
public:
Tee(std::ostream &os1, std::ostream &os2) : os1(os1), os2(os2) { }
template <typename T>
Tee& operator<<(const T &thing) {
os1 << thing;
os2 << thing;
return *this;
}
};
这将采用模板参数,因此它不会关心您传递的是 right
还是 setw(3)
。您可以像这样使用它:
Tee t(std::cout, std::cout);
t << setw(10) << "right" << " Thing" << setw(9);
您可以使用 std::stringstream
轻松完成此操作。我不知道 get<>()
是什么,但这是一个基本示例:
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
void fn(std::string output) {
std::ofstream file("file.txt");
std::cout << output;
file << output;
}
int main() {
std::stringstream buffer;
buffer << "some random text" << std::endl;
fn(buffer.str());
return 0;
}
不幸的是,您不能将所有这些东西仅作为一个参数传递。但是有一些高级技术可以帮助您,例如 variadic templates and C++17 fold expressions.
可变参数模板是一项功能,例如,它允许您在编译时传递未知数量的不同类型的参数。您可以在标准库中看到一些此类示例,例如 std::tuple.
折叠表达式是与前一个功能结合使用的另一个功能。它允许您编写非常简单的可变参数模板代码:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args) << '\n';
}
这里我们看到一个函数,它接受一些 const &
到一些参数(我们不知道它们的数量或不同类型),但是我们有像 args
这样奇特的东西,一个参数pack,代表我们的参数,和 Args
作为它们的类型一起 "packed";
您可以使用它来将任意参数传递给您的流:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args);
(file << ... << args);
}
此解决方案还有一些其他需要改进的地方,例如perfect forwarding,但这些有待进一步研究。
阅读此文后:C++ Writing to file and Console Output at the same time with simple code,我正在尝试编写一个函数来处理我在 for 循环中的内容。但是我不知道如何将这样的一段代码作为参数传递给函数:setw(3) << right << get<0>(*it_party) << setw(9) << ""
以便 cout 和 file 都可以使用它。
The helper function I am trying to write:
void print(std::ostream &os1, std::ostream &os2, const [I don't know what to put in here])
{
os1 << the argument; // cout
os2 << the argument; // file
}
ofstream file;
file.open("test.txt");
for (auto it_party = parties_.begin(); it_party != parties_.end(); ++it_party) {
cout << setw(3) << right << get<0>(*it_party) << setw(9) << "";
file << setw(3) << right << get<0>(*it_party) << setw(9) << "";
cout << setw(7) << left << get<1>(*it_party) << setw(1) << "";
file << setw(7) << left << get<1>(*it_party) << setw(1) << "";
...
...
}
如果你想像那样将输出串在一起,你可能会发现使用某种 "tee" class:
更容易class Tee {
private:
std::ostream &os1, &os2;
public:
Tee(std::ostream &os1, std::ostream &os2) : os1(os1), os2(os2) { }
template <typename T>
Tee& operator<<(const T &thing) {
os1 << thing;
os2 << thing;
return *this;
}
};
这将采用模板参数,因此它不会关心您传递的是 right
还是 setw(3)
。您可以像这样使用它:
Tee t(std::cout, std::cout);
t << setw(10) << "right" << " Thing" << setw(9);
您可以使用 std::stringstream
轻松完成此操作。我不知道 get<>()
是什么,但这是一个基本示例:
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
void fn(std::string output) {
std::ofstream file("file.txt");
std::cout << output;
file << output;
}
int main() {
std::stringstream buffer;
buffer << "some random text" << std::endl;
fn(buffer.str());
return 0;
}
不幸的是,您不能将所有这些东西仅作为一个参数传递。但是有一些高级技术可以帮助您,例如 variadic templates and C++17 fold expressions.
可变参数模板是一项功能,例如,它允许您在编译时传递未知数量的不同类型的参数。您可以在标准库中看到一些此类示例,例如 std::tuple.
折叠表达式是与前一个功能结合使用的另一个功能。它允许您编写非常简单的可变参数模板代码:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args) << '\n';
}
这里我们看到一个函数,它接受一些 const &
到一些参数(我们不知道它们的数量或不同类型),但是我们有像 args
这样奇特的东西,一个参数pack,代表我们的参数,和 Args
作为它们的类型一起 "packed";
您可以使用它来将任意参数传递给您的流:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args);
(file << ... << args);
}
此解决方案还有一些其他需要改进的地方,例如perfect forwarding,但这些有待进一步研究。