【问题标题】:C++ std::istream to read from fileC++ std::istream 从文件中读取
【发布时间】:2022-01-05 12:26:09
【问题描述】:

我对 c++ 完全陌生,但我在管理输入方面遇到了问题。我有一个程序,我希望可以从控制台读取输入,也可以从文件中读取。 我有一个带有私有字段std::istream &input_stream; 的类,在构造函数中我将此input_stream 设置为std::cin,但是当我的程序使用标志-i-FILENAME 运行时,我希望input_stream 成为那个文件。

class FlagsParser
{
private:
    std::istream &input_stream;

public:
    FlagsParser() : input_stream(std::cin){}
    void ParseFlags(int count,char *flags[]) -> arguments I get from main
    {
        for(int i =1;i<count;++i){
            std::string flag = flags[i];
            if(flag.rfind("-i",0) == 0){ // check if the arg starts with -i
                std::ifstream readFile(flag.substr(2)); 
                -> Here i want to set input_stream to readFile and I have no idea how.
                ...


我该怎么办?感谢您的任何帮助。 (也许我做错了?)

【问题讨论】:

标签: c++ file ifstream istream


【解决方案1】:

有可能,但需要谨慎编程。

由于input_stream 必须是一个引用,它必须引用一个现有的对象。 std::cin 没有问题,它是标准库定义的众所周知的对象。为了让它引用一个文件流,那个该死的文件流应该存在于某个地方,并且可能不同的FlagParser 对象可能有不同的流。解决这个问题的一个简单方法是在类中添加一个辅助 std::ifstream(一个真正的对象而不是一个引用)并声明它 before input_stream 以便能够用它初始化 input_stream .然后,如果它是开放流,您可以决定使用它,如果不是,则使用 std::cin

如果ifstream的初始化不简单,可以委托给成员函数:

class FlagsParser
{
private:
    std::ifstream inner_stream;
    std::istream &input_stream;

    // this method is expected to be called before full construction
    // of the object. It is not required to be static but it SHALL NOT
    // use any non static member. Making it static guarantees that.
    /* static */ std::ifstream build_stream(int count,char *flags[]) {
        std::ifstream ifs;
        // compute the file path from the args
        if (...) {
            ifs.open(path);
        }
        return ifs;
    }
public:
    Parser(int count, char *argv[]) :
            inner_stream(build_stream(count, argv),
            input_stream(inner_stream.is_open() ? inner_stream : std::cin) {
        // further initialization if required...
    }
};

然后您可以在 main: 中定义您的 FlagParser

int main(int argc, char *argv[]) {
    FlagParser parser(argc, argv);
    ...
}

【讨论】:

  • 为了安全起见,将成员函数build_stream设为静态。
【解决方案2】:

更新: 对不起,我误解了这个问题。以下是您可以执行的操作:

在堆上创建流(使用运算符new)并将其分配给智能指针,这样您就不必手动释放它。稍后,检查指针是否为空,并返回 std::cin 或指针的内容,如下所示:

#include <iostream>
#include <fstream>

class FlagsParser {
    std::unique_ptr<std::istream> streamPtr;

public:
    FlagsParser() {
    }

    void ParseFlags(int count, const char* flags[]) {
        for( int i = 1; i < count; ++i) {
            std::string flag = flags[i];
            if (flag.rfind("-i", 0) == 0) {
                streamPtr.reset(new std::ifstream(flag.substr(2)));
            }
        }
    }

    std::istream& GetStream() {
        return (streamPtr.get() == nullptr) ? std::cin : *streamPtr.get();
    }
};

class Worker {
public:
    Worker() {
    }

    void Work(std::istream& stream) {
        // Do something with the stream
        std::istreambuf_iterator<char> begin(stream), end;
        std::string s(begin, end);
        std::cout << s;
    }
};

int main(int argc, const char * argv[]) {

    FlagsParser parser;
    parser.ParseFlags(argc, argv);

    Worker worker;
    worker.Work(parser.GetStream());

    return 0;
}

【讨论】:

  • auto_ptr 在 C++11 中已弃用并在 C++17 中删除
  • 感谢您指出,使用 unique_ptr 或现在推荐的任何内容。
  • unique_ptr,这需要 C++11 的语言更改,做了 auto_ptr 应该做的事情(但不能)
猜你喜欢
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 2012-06-17
  • 2010-11-21
  • 2014-01-05
相关资源
最近更新 更多