如何将 istringstream 和 ifstream 分配给 istream 变量?

How to assign istringstream and ifstream to an istream variable?

我想要一个 istream 类型的变量,它可以保存文件内容或字符串。这个想法是,如果没有指定文件,类型 istream 的变量将被分配一个字符串。

std::ifstream file(this->_path)

std::istringstream iss(stringSomething);

std::istream is

我试过将它们分配给 istream 变量,就像我对从同一基础 class 继承的其他对象所做的那样,但这没有用。

如何将 istringstreamifstream 分配给 istream 变量?

Base class 指针可以指向派生的 class 数据。 std::istringstreamstd::ifstream 都派生自 std::istream,所以我们可以这样做:

//Note that std::unique_ptr is better that raw pointers
std::unique_ptr<std::istream> stream;

//stream holds a file stream
stream = std::make_unique<std::ifstream>(std::ifstream{ this->_path });

//stream holds a string
stream = std::make_unique<std::istringstream>(std::istringstream{});

现在您只需使用

提取内容
std::string s;
(*stream) >> s;

从标准库中取出一个页面:不赋值;分配参考。无论如何,这可能就是您想要的。

std::istringstream iss(stringSomething);
std::istream& input(iss);

因为流携带很多状态,复制它们充满了语义问题。例如考虑在原始调用 seekg 之后 tellg 应该在副本中报告什么。相比之下,参考文献清楚地回答了这个问题。

在 C++ 中,您不能将 Child 类型的对象分配给 Parent 类型的变量,即使 Child 继承自 Parent。但是,您可以将 Child 类型的 pointer 分配给 Parent 类型的指针。您可能需要考虑动态分配对象。

在 C++ 中

std::istream is;

是一个实际对象,分配给它会调用复制赋值运算符,它将 iss 的子对象(一个 std::istream 复制到 is 和 slice 中。 LogicStuff 链接的示例将显示您需要为 iss 分配一个引用或指针,如下所示:

std::istream &is_ref = iss;

值、引用和指针之间的区别是 C++ 的基础,我建议深入掌握 them

std::istream can be constructed from a std::streambuf(基本上是生产或消费字符的设备)。所有 i/ostream 个对象都有关联的 std::streambuf 并且可以共享。

std::ifstream file(this->_path); 
std::istringstream iss("str in gSo met hing");

std::istream A(iss.rdbuf());   // shares the same buffer device with iss

std::string str;

//////////////
while(A >> str) std::cout << str << " | "; //read everything from stream (~> iss)
std::cout << std::endl;

A = std::move(file);
while(A >> str) std::cout << str << " | "; //read from file, using same stream (~> file)

您不能分配给 std::istream 但您可以像这样绑定到引用:

#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

std::istringstream test_data(R"~(

some test data here
instead of in an external
file.

)~");

int main(int, char* argv[])
{
    // if we have a parameter use it
    std::string filename = argv[1] ? argv[1] : "";

    std::ifstream ifs;

    // try to open a file if we have a filename
    if(!filename.empty())
        ifs.open(filename);

    // This will ONLY fail if we tried to open a file
    // because the filename was not empty    
    if(!ifs)
    {
        std::cerr << "Error opening file: " << filename << '\n';
        return EXIT_FAILURE;
    }

    // if we have an open file bind to it else bind to test_data
    std::istream& is = ifs.is_open() ? static_cast<std::istream&>(ifs) : test_data;

    // use is here
    for(std::string word; is >> word;)
    {
        std::reverse(word.begin(), word.end());
        std::cout << word << '\n';
    }
}