是否有一个很好的习惯用法来处理替代输出流?
Is there a good idiom to deal with alternative output streams?
我想编写一个简单的程序,根据传递给它的选项,可执行文件将输出打印到屏幕或文件。程序简单
#include<iostream>
int main(int argc, char* argv[]){
... process options...
std::ostream& out = ... // maybe std::cout, maybe a *new* std::ofstream;
out << "content\n";
}
是否有一个好的习惯用法可以在运行时替代地引用 std::cout
或文件流?
我试过用指针,但它很糟糕。我无法避免使用指针(更不用说以后需要更丑陋的代码来删除指针)。
#include<iostream>
#include<ofstream>
int main(int argc, char* argv[]){
std::string file = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
std::ostream* out = (file=="")?&std::cout:(new std::ofstream(file)); // horrible code
*out << "content" << std::endl;
if(out != &std::cout) delete out;
}
我不知道,也许 C++ 流的某些功能允许这样做。也许我必须使用某种类型的擦除。我认为,问题是 std::cout
是 已经 存在的东西(是全局的),但是 std::ofstream
是必须创建的东西。
我设法使用 open
并避免了指针,但它仍然很难看:
int main(int argc, char* argv[]){
std::string file = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
std::ofstream ofs;
if(file != "") ofs.open(file);
std::ostream& out = (file=="")?std::cout:ofs;
out << "content" << std::endl;
}
所需流的运行时绑定非常需要看起来像您已有的那样。
关于指针问题,确定您可以稍微清理一下...也许是这样的?这是假设您只想在参数存在时创建 ofstream
。
int main(int argc, char* argv[]){
std::string file = argc > 1 ? argv[1] : "";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
std::unique_ptr<std::ostream> fp;
if (file == "")
fp = std::make_unique<std::ofstream>(file);
std::ostream& out = (fp && fp->is_open()) ? std::cout : *fp; // not so horrible code
out << "content" << std::endl;
}
如果不需要动态对象,最简单的可能是列出这个;
int main(int argc, char* argv[]){
std::string filename = (argc > 1) ? argv[1] : "";
std::ofstream file(filename);
// if there is no argument (file) it will print to screen
std::ostream& out = file.is_open() ? file : std::cout;
out << "content" << std::endl;
}
也许是参考资料?
#include<iostream>
#include<ofstream>
int main(int argc, char* argv[])
{
auto &out = std::cout;
std::ofstream outFile;
std::string fileName = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
if(!fileName.empty())
{
outFile.open(fileName);
out = outFile;
}
out<<"one, one, two";
return 0;
}
太多过度设计了。
#include <iostream>
#include <fstream>
int main(int argc, char* argv[]) {
std::ofstream ofs(argc > 1 ? argv[1] : "");
std::ostream& os = ofs.is_open() ? ofs : std::cout;
// use os ...
}
您可以使用指向流的共享指针来实现多态行为:
#include <memory>
#include <fstream>
#include <sstream>
#include <iostream>
void nodelete(void*) {}
std::shared_ptr<std::ostream> out_screen_stream() { return std::shared_ptr<std::ostream>(&std::cout, nodelete); }
std::shared_ptr<std::ostream> out_file_stream() { return std::make_shared<std::ofstream>(); }
std::shared_ptr<std::ostream> out_string_stream() { return std::make_shared<std::ostringstream>(); }
int main ()
{
std::shared_ptr<std::ostream> out;
// case condition:
out = out_screen_stream();
out = out_file_stream();
out = out_string_stream();
*out << "content" << std::endl;
return 0;
}
注意:std::shared_ptr 允许管理不同的可能流,其中一些流不应被删除(例如:std::cout)。
类似,但与 std::unique_ptr:
#include <memory>
#include <fstream>
#include <sstream>
#include <iostream>
class Deleter
{
public:
Deleter(bool use_delete = true) : use_delete(use_delete) {}
template <typename T>
void operator () (const T* p) {
if(use_delete)
delete p;
}
bool nodelete() const { return ! use_delete; }
private:
bool use_delete;
};
using unique_ostream_ptr = std::unique_ptr<std::ostream, Deleter>;
unique_ostream_ptr out_screen_stream() { return unique_ostream_ptr(&std::cout, false); }
unique_ostream_ptr out_file_stream() { return unique_ostream_ptr{ new std::ofstream }; }
unique_ostream_ptr out_string_stream() { return unique_ostream_ptr{ new std::ostringstream }; }
int main ()
{
unique_ostream_ptr out;
// case condition:
out = out_screen_stream();
out = out_file_stream();
out = out_string_stream();
*out << "content" << std::endl;
return 0;
}
我的偏好是使用安装了合适的流缓冲区的流。这是直接输出到文件或 std::cout
:
的一种方法
#include <iostream>
#include <fstream>
int main(int ac, char* av) {
std::ofstream ofs;
if (1 < ac) {
ofs.open(av[1]);
// handle errors opening the file here
}
std::ostream os(file? file.rdbuf(): std::cout.rdbuf());
// use os ...
}
我经常使用类似这样的命令行工具:
int main(int, char* argv[])
{
std::string filename;
// args processing ... set filename from command line if present
if(argv[1])
filename = argv[1];
std::ofstream ofs;
// if a filename was given try to open
if(!filename.empty())
ofs.open(filename);
// bad ofs means tried to open but failed
if(!ofs)
{
std::cerr << "Error opeing file: " << filename << '\n';
return EXIT_FAILURE;
}
// Here either ofs is open or a filename was not provided (use std::cout)
std::ostream& os = ofs.is_open() ? ofs : std::cout;
// write to output
os << "Some stuff" << '\n';
return EXIT_SUCCESS;
}
我想编写一个简单的程序,根据传递给它的选项,可执行文件将输出打印到屏幕或文件。程序简单
#include<iostream>
int main(int argc, char* argv[]){
... process options...
std::ostream& out = ... // maybe std::cout, maybe a *new* std::ofstream;
out << "content\n";
}
是否有一个好的习惯用法可以在运行时替代地引用 std::cout
或文件流?
我试过用指针,但它很糟糕。我无法避免使用指针(更不用说以后需要更丑陋的代码来删除指针)。
#include<iostream>
#include<ofstream>
int main(int argc, char* argv[]){
std::string file = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
std::ostream* out = (file=="")?&std::cout:(new std::ofstream(file)); // horrible code
*out << "content" << std::endl;
if(out != &std::cout) delete out;
}
我不知道,也许 C++ 流的某些功能允许这样做。也许我必须使用某种类型的擦除。我认为,问题是 std::cout
是 已经 存在的东西(是全局的),但是 std::ofstream
是必须创建的东西。
我设法使用 open
并避免了指针,但它仍然很难看:
int main(int argc, char* argv[]){
std::string file = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
std::ofstream ofs;
if(file != "") ofs.open(file);
std::ostream& out = (file=="")?std::cout:ofs;
out << "content" << std::endl;
}
所需流的运行时绑定非常需要看起来像您已有的那样。
关于指针问题,确定您可以稍微清理一下...也许是这样的?这是假设您只想在参数存在时创建 ofstream
。
int main(int argc, char* argv[]){
std::string file = argc > 1 ? argv[1] : "";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
std::unique_ptr<std::ostream> fp;
if (file == "")
fp = std::make_unique<std::ofstream>(file);
std::ostream& out = (fp && fp->is_open()) ? std::cout : *fp; // not so horrible code
out << "content" << std::endl;
}
如果不需要动态对象,最简单的可能是列出这个;
int main(int argc, char* argv[]){
std::string filename = (argc > 1) ? argv[1] : "";
std::ofstream file(filename);
// if there is no argument (file) it will print to screen
std::ostream& out = file.is_open() ? file : std::cout;
out << "content" << std::endl;
}
也许是参考资料?
#include<iostream>
#include<ofstream>
int main(int argc, char* argv[])
{
auto &out = std::cout;
std::ofstream outFile;
std::string fileName = argc>1?argv[1]:"";
std::clog << "file: " << file << '\n';
// if there is no argument it will print to screen
if(!fileName.empty())
{
outFile.open(fileName);
out = outFile;
}
out<<"one, one, two";
return 0;
}
太多过度设计了。
#include <iostream>
#include <fstream>
int main(int argc, char* argv[]) {
std::ofstream ofs(argc > 1 ? argv[1] : "");
std::ostream& os = ofs.is_open() ? ofs : std::cout;
// use os ...
}
您可以使用指向流的共享指针来实现多态行为:
#include <memory>
#include <fstream>
#include <sstream>
#include <iostream>
void nodelete(void*) {}
std::shared_ptr<std::ostream> out_screen_stream() { return std::shared_ptr<std::ostream>(&std::cout, nodelete); }
std::shared_ptr<std::ostream> out_file_stream() { return std::make_shared<std::ofstream>(); }
std::shared_ptr<std::ostream> out_string_stream() { return std::make_shared<std::ostringstream>(); }
int main ()
{
std::shared_ptr<std::ostream> out;
// case condition:
out = out_screen_stream();
out = out_file_stream();
out = out_string_stream();
*out << "content" << std::endl;
return 0;
}
注意:std::shared_ptr 允许管理不同的可能流,其中一些流不应被删除(例如:std::cout)。
类似,但与 std::unique_ptr:
#include <memory>
#include <fstream>
#include <sstream>
#include <iostream>
class Deleter
{
public:
Deleter(bool use_delete = true) : use_delete(use_delete) {}
template <typename T>
void operator () (const T* p) {
if(use_delete)
delete p;
}
bool nodelete() const { return ! use_delete; }
private:
bool use_delete;
};
using unique_ostream_ptr = std::unique_ptr<std::ostream, Deleter>;
unique_ostream_ptr out_screen_stream() { return unique_ostream_ptr(&std::cout, false); }
unique_ostream_ptr out_file_stream() { return unique_ostream_ptr{ new std::ofstream }; }
unique_ostream_ptr out_string_stream() { return unique_ostream_ptr{ new std::ostringstream }; }
int main ()
{
unique_ostream_ptr out;
// case condition:
out = out_screen_stream();
out = out_file_stream();
out = out_string_stream();
*out << "content" << std::endl;
return 0;
}
我的偏好是使用安装了合适的流缓冲区的流。这是直接输出到文件或 std::cout
:
#include <iostream>
#include <fstream>
int main(int ac, char* av) {
std::ofstream ofs;
if (1 < ac) {
ofs.open(av[1]);
// handle errors opening the file here
}
std::ostream os(file? file.rdbuf(): std::cout.rdbuf());
// use os ...
}
我经常使用类似这样的命令行工具:
int main(int, char* argv[])
{
std::string filename;
// args processing ... set filename from command line if present
if(argv[1])
filename = argv[1];
std::ofstream ofs;
// if a filename was given try to open
if(!filename.empty())
ofs.open(filename);
// bad ofs means tried to open but failed
if(!ofs)
{
std::cerr << "Error opeing file: " << filename << '\n';
return EXIT_FAILURE;
}
// Here either ofs is open or a filename was not provided (use std::cout)
std::ostream& os = ofs.is_open() ? ofs : std::cout;
// write to output
os << "Some stuff" << '\n';
return EXIT_SUCCESS;
}