C++ 有没有一个好的习惯用法来处理可选的输出流?

C++ 有没有一个好的习惯用法来处理可选的输出流?,c++,iostream,ostream,C++,Iostream,Ostream,我想写一个简单的程序,根据传递给它的选项,可执行文件将输出打印到屏幕或文件。程序很简单 #include<iostream> int main(int argc, char* argv[]){ ... process options... std::ostream& out = ... // maybe std::cout, maybe a *new* std::ofstream; out << "content\n"; } 我不知道,

我想写一个简单的程序,根据传递给它的选项,可执行文件将输出打印到屏幕或文件。程序很简单

#include<iostream>
int main(int argc, char* argv[]){
    ... process options...

    std::ostream& out = ... // maybe std::cout, maybe a *new* std::ofstream;
    out << "content\n";
}
<>我不知道,也许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;
}
intmain(intargc,char*argv[]){
std::string file=argc>1?argv[1]:“”;

std::clog所需流的运行时绑定几乎需要看起来像您已经拥有的一样

关于指针问题,请确定您可以稍微清理一下…可能是这样的?假设您只想在参数存在时创建流的

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;
}
intmain(intargc,char*argv[]){
std::string file=argc>1?argv[1]:“”;
std::阻塞可能是参考

#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;
}
#包括
#包括
int main(int argc,char*argv[])
{
auto&out=std::cout;
std::出流管;
std::string fileName=argc>1?argv[1]:“”;

std::阻塞太多了

#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 ...
}
#包括
#包括
int main(int argc,char*argv[]){
流的标准::(argc>1?argv[1]:“”);
std::ostream&os=ofs.is_open()?ofs:std::cout;
//使用操作系统。。。
}

对于多态行为,可以使用指向流的共享指针:

#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;
}
#包括
#包括
#包括
#包括
void节点节点(void*){}
std::shared_ptr out_screen_stream(){返回std::shared_ptr(&std::cout,nodelete);}
std::shared_ptr out_file_stream(){return std::make_shared();}
std::shared_ptr out_string_stream(){return std::make_shared();}
int main()
{
std::共享输出;
//病例情况:
out=out_screen_stream();
out=out_文件_流();
out=out_字符串_流();

*out我的首选是使用安装了适当流缓冲区的流。这里有一种直接输出到文件或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 ac、char*av){
std::ofs流;
如果(1
我经常在命令行工具中使用类似的东西:

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;
}
intmain(int,char*argv[]
{
std::字符串文件名;
//args处理…从命令行设置文件名(如果存在)
if(argv[1])
filename=argv[1];
std::ofs流;
//如果给定了文件名,请尝试打开
如果(!filename.empty())
打开(文件名);
//坏ofs表示尝试打开但失败
如果(!ofs)
{

std::cerr指针不一定意味着动态分配。可能有点不对劲,但如果它是命令行程序,则应始终输出到
std::cout
,并让用户决定是否要将输出重定向到文件中。此问题的可能重复可能会引起兴趣:引用不能重新分配,流也不能。尼斯。但是很可怕。流的
会尝试打开
还是无法自动打开?。此外,如果流的
由于其他原因(不可写文件)失败,它会做一些意想不到的事情。(别误会,我喜欢解决方案+1)@alfC,请阅读
std::basic_of stream
的文档,以了解如何准确识别您提到的问题。您的设计真的太过份了。@alfC,“打开
”是什么意思意思是?你怎么能打开一个没有名字的文件?你有没有尝试过创建一个文件名为空的文件?如果你试图打开一个不可写的文件进行写入,你认为会发生什么?提示:它不会做任何意外的事。学会使用你的工具,而不是编写大量脆弱的代码来处理非问题。1)如果没有文件系统或者它是不可写的,我想知道
std::ofstreamofs(“”;
是否仍会尝试执行某些操作。2)如果'argv[1]=“/readonlylocation”,程序将打印到屏幕上,而不是仅仅因为无法在写模式下打开文件而给出错误(这是令人惊讶的结果).1)当然不是!2)啊,好吧,对用户来说出乎意料,是的,这是真的。迪特玛的回答很好,可以很容易地检查。你根本不需要动态分配。你试图通过
std::unique_ptr
的自动存储来绕过它,但这只是多余的。我知道,OP在最初的帖子中有它,也许他出于某些原因需要它关于…他的更新似乎说可能不是…这显然是最好的答案,但我是唯一投票的人!这很好。很容易忘记流的缓冲区方面。
#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;
}
#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;
}