流对象来表示文件输入,然后是标准输入?

Stream object to represent file input and then standard input?

本文关键字:然后 标准输入 输入 对象 表示 文件      更新时间:2023-10-16

作为一个菜鸟C++项目,我正在构建一个依赖于用户输入的游戏循环的 CLI 游戏。出于测试目的,我希望能够将文件名作为命令行参数传递给程序,该程序将被视为"标准输入",直到被通读为止。

因此,我需要一种方法来封装一个表示文件内容的对象,然后在文件被通读后std::cin- 基本上将文件的内容预置到标准输入中。至少,这看起来会非常好,这样我就可以避免有类似的东西

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};
}

用某种自定义类替换它是好方法吗?或者我可以以某种方式弄乱std::cin以将我的文件内容添加到其中吗?


澄清一下:我的游戏循环可能会说,20 次迭代。如果我传递一个包含五行的文件,我想在游戏循环的前五次迭代中使用这五行,然后在其余十五行中回退到标准输入。我知道如何在很多条件下做到这一点,但我认为一定有一种方法可以在课堂上很好地拥有这种行为。我的问题是 - 它应该从什么继承?std::streambuf?这在原则上是个好主意吗?

我的(可能是糟糕的尝试(

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;
};

下面的方法行得通吗?打开文件,重定向std::cin从文件中读取。对std::cin使用std::getline,以便它从文件流中读取。在程序结束前一段时间,或者如果文件完成读取,请将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;
}

您始终可以通过 argv 从文件重定向。从一开始就将整个事情视为std::cin。

以下示例是您要查找的吗?

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 ("anbncn");
for(int i = 0; i < 5; ++i)
{
auto line = readNextLine(ss);
std::cout << "got: " << line << std::endl;
}
return 0;
}

字符串流可以替换为 fstream 或任何其他实现 std::istream 的类型。

您可以在此处进行测试 http://cpp.sh/5iv65