【问题标题】:How to assign istringstream and ifstream to an istream variable?如何将 istringstream 和 ifstream 分配给 istream 变量?
【发布时间】:2016-12-12 09:28:06
【问题描述】:

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

std::ifstream file(this->_path)

std::istringstream iss(stringSomething);

std::istream is

我尝试将它们分配给 istream 变量,就像我对从同一基类继承的其他对象所做的那样,但这不起作用。

如何将istringstreamifstream 分配给istream 变量?

【问题讨论】:

标签: c++ ifstream istream istringstream


【解决方案1】:

基类指针可以指向派生类数据。 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::unique_ptr&lt;std::istream&gt; stream_owner;,然后使用std::istream&amp; stream = *stream_owner;,允许使用熟悉的stream &gt;&gt; s 语法。
  • make_unique() 调用可以稍微简化:stream = std::make_unique&lt;std::ifstream&gt;(_path);stream = std::make_unique&lt;std::istringstream&gt;(); 另请注意 std::unique_ptr 是 C++11 中的新功能,但 std::make_unique 是 C++ 中的新功能14.
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      在 C++ 中

      std::istream is;
      

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

      std::istream &amp;is_ref = iss;

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

      【讨论】:

        【解决方案5】:

        std::istream 可以是 constructed 来自 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)
        

        【讨论】:

        • 第二种情况,不应该调用A.rdbuf(file.rdbuf());共享缓冲区而不是转让所有权吗?
        【解决方案6】:

        您不能分配给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';
            }
        }
        

        【讨论】:

        • 这正是我所寻找的:如果未提供文件,则选择默认流(例如std::cin)并将其分配给std::istream 类型的变量的完整示例.
        猜你喜欢
        • 2011-01-10
        • 2016-05-27
        • 2018-03-29
        • 1970-01-01
        • 2019-12-03
        • 1970-01-01
        • 2014-01-15
        • 1970-01-01
        相关资源
        最近更新 更多