C++std::istream从文件中读取



我对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.
...

我该怎么办?谢谢你的帮助。(也许我做错了?(

这是可能的,但需要谨慎编程。

由于input_stream必须是一个引用,所以它必须引用一个现有的对象。std::cin是由标准库定义的众所周知的对象,它没有问题。为了让它引用一个文件流,那个该死的文件流应该存在于某个地方,并且可能不同的FlagParser对象可能有不同的流。解决这个问题的一个简单方法是向类中添加一个辅助std::ifstream(一个真正的对象,而不是ref(,并在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);
...
}

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

在堆上创建流(使用运算符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;
}

最新更新