[英]Stream object to represent file input and then standard input?
As a noob C++ project, I am building a CLI game with a game loop that relies upon user input. 作为一个noob C ++项目,我正在构建一个具有依赖用户输入的游戏循环的CLI游戏。 For the purpose of testing, I would like to be able to pass a file name as a command line argument to the program, which will be treated "like standard input" until it is read through.
为了进行测试,我希望能够将文件名作为命令行参数传递给程序,在将其读入之前,将其视为“标准输入”。
Consequently, I need a way to encapsulate an object that represents a file's contents and then std::cin
once the file has been read through - basically prepending a file's contents to standard input. 因此,我需要一种方法来封装表示文件内容的对象, 然后在读取文件后封装
std::cin
基本上将文件的内容置于标准输入之前。 At least, this seems like it would be very nice, so that I can avoid having something like 至少,这看起来会很好,这样我就可以避免出现类似
std::istringstream retrieve_input(std::ifstream &file) {
std::string line;
if (std::getline(file, line))
return std::istringstream{line};
std::getline(std::cin, line);
return std::istringstream{line};
}
Is replacing this with some kind of custom class a good approach? 用某种自定义类替换它是一种好方法吗? Or can I mess with
std::cin
somehow to prepend my file contents to it? 或者我可以以某种方式弄乱
std::cin
来添加我的文件内容吗?
To clarify : My game loop might have say, 20 iterations. 澄清一下:我的游戏循环可能有20次迭代。 If I pass a file with five lines, I want to use those five lines for the first five iterations of my game loop, and then drop back to standard input for the remaining fifteen.
如果我传递的文件有五行,我想在我的游戏循环的前五次迭代中使用这五行,然后在剩下的十五行中返回到标准输入。 I understand how to do this with a bunch of conditions, but I think there must be a way to nicely have this sort of behavior in a class.
我了解如何在很多条件下执行此操作,但是我认为必须有一种方法可以在类中很好地具有这种行为。 My problem is - what should it inherit from?
我的问题是-它应该继承什么?
std::streambuf
? std::streambuf
吗? Is this a good idea in principle? 原则上这是个好主意吗?
My (probably bad attempt) 我(可能是错误的尝试)
class InputGrabber {
public:
virtual std::istringstream retrieve_line() = 0;
virtual ~InputGrabber() {}
};
class BaseInputGrabber : public InputGrabber {
public:
BaseInputGrabber(std::istream &_in): in{_in} {}
std::istringstream retrieve_line() override {
std::string line;
std::getline(in, line);
return std::istringstream{line};
}
private:
std::istream ∈
};
class VarInputGrabber : public InputGrabber {
public:
VarInputGrabber(std::istream &_in, const std::string &f_name) :
in{_in}, init{std::ifstream(f_name)} {}
std::istringstream retrieve_line() override {
std::string line;
if (std::getline(init, line)) {
return std::istringstream{line};
}
std::getline(in, line);
return std::istringstream{line};
}
private:
std::istream ∈
std::ifstream init;
};
Would the below work? 以下工作吗? You open the file, redirect
std::cin
to read from the file. 您打开文件,重定向
std::cin
以从文件中读取。 Use std::getline
on std::cin
so that it reads from the file stream. 在
std::cin
上使用std::getline
,以便它从文件流中读取。 Some time before the program ends or if the file is finished being read, restore std::cin
back to its original state. 在程序结束之前的某个时间,或者如果文件读取完成,请将
std::cin
恢复到其原始状态。
#include <iostream>
#include <fstream>
int main(int argc, const char * argv[]) {
std::fstream file("/users/Brandon/Desktop/testingInput.txt", std::ios::in);
//Redirect cin to a file.
std::streambuf* cinBuffer = std::cin.rdbuf();
std::cin.rdbuf(file.rdbuf());
//Read line from std::cin (which points to the file) with std::getline.
std::string line;
std::getline(std::cin, line);
std::cout<<"INPUT LINE: "<<line<<std::endl;
//Redirect cin to standard input.
std::cin.rdbuf(cinBuffer);
//Read some line from the user's input..
std::getline(std::cin, line);
std::cout<<"USER INPUT LINE: "<<line<<std::endl;
std::cin.get();
return 0;
}
You could always redirect from file via argv. 您始终可以通过argv从文件重定向。 Treat the whole thing as std::cin from the beginning.
从一开始就将整个事物视为std :: cin。
Is the following example that what you are looking for? 以下示例是您所寻找的吗?
std::string readNextLine(std::istream& is)
{
std::string line;
if(!std::getline(is, line))
std::getline(std::cin, line);
return line;
}
int main()
{
std::stringstream ss ("a\nb\nc\n");
for(int i = 0; i < 5; ++i)
{
auto line = readNextLine(ss);
std::cout << "got: " << line << std::endl;
}
return 0;
}
The stringstream can be replaced with fstream or any other type that implements std::istream. 可以用fstream或实现std :: istream的任何其他类型替换stringstream。
You can test it here http://cpp.sh/5iv65 您可以在这里进行测试http://cpp.sh/5iv65
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.