【问题标题】:C++ ifstream::read() and C arraysC++ ifstream::read() 和 C 数组
【发布时间】:2011-07-09 08:40:17
【问题描述】:

似乎普遍认为 C 数组不好,使用更智能的替代方法,如向量或 C++ 字符串是要走的路。这里没问题。

话虽如此,为什么ifstream 的read() 成员将数据输入到char*... 问题是:我可以单独使用 STL 以某种方式输入字节向量吗?

一个相关的额外问题:您是否经常检查ios::badbit 和ios::failbit,尤其是当您在该范围内使用动态分配的C 字符串时?你会在catch()'s 中释放 C 字符串吗?

感谢您的阅读。

【问题讨论】:

    标签: c++ arrays ifstream


    【解决方案1】:

    您可以直接读入分配的向量(我无法从这里编译它,因此可能存在拼写错误或转置参数等......)但这个想法是正确的。

    vector<char> data;
    data.resize(100);
    
    // Read 100 characters into the storage of data
    thing.read(&data[0], 100);
    

    【讨论】:

    • 您还可以在创建过程中使用explicit vector ( size_type n, const T&amp; value= T(), const Allocator&amp; = Allocator() ); 指定向量的大小。注意最后两个有默认值所以你可以做vector&lt;char&gt; data(100);
    • @JohnB 看起来很老套,但后来我记得[] 超载了。感谢您的回复。
    • 是的,我知道你的意思 :) 但这是获取指向数据开头的指针的正确方法 :)
    • ifstream 的构造函数也有类似的情况,它接受一个 const char* 文件名,而不是你所期望的一个 const std::string&。我的猜测是 STL 的设计者不想在库之间引入太多的依赖关系。
    • 这是 a 获取指向数据开头的指针的正确方法。有些人更喜欢&amp;data.front(),并且有相当不错的美学论据。
    【解决方案2】:

    说了这么多,为什么ifstream的read()成员输入数据到char*...

    这是一个设计选择。不一定是最聪明的。

    问题是:我能以某种方式输入字节向量吗

    std::vector&lt;char&gt; 的底层存储保证连续(即单个内存块),所以是的。要使用ifstream::read,您必须(a)确保向量的大小足够大(使用.resize() - not .reserve()!这是因为向量无法知道数据您正在读取其未使用的capacity 并更新其size),然后(b)获取指向向量开始元素的指针(例如&amp;v.front() 或&amp;(v[0]))。

    如果您不想预先确定向量的大小,则可以使用更高级的技术,包括迭代器类型和标准库算法。它们的优点是您可以轻松地将整个文件读入向量,而无需先检查文件长度(检查文件长度的标准技巧可能不像您想象的那么可靠!)。

    它看起来像:

    #include <iterator>
    #include <algorithm> // in addition to what you already have.
    // ...
    std::ifstream ifs;
    std::vector v;
    // ...
    std::istreambuf_iterator<char> begin(ifs), end;
    std::copy(begin, end, std::back_inserter(v));
    

    当然,字节向量不是字符串。但是你可以用std::string 做同样的事情——std::back_inserter 函数足够聪明,可以为提供.push_back() 的任何提供的类型创建适当的迭代器类型,string 和vector 都可以这样做。这就是模板的魔力。 :)

    单独使用 STL?

    我很困惑。我以为我们在谈论 C++ 标准库。你说的这个 STL 是什么?

    一个相关的额外问题:你是否经常检查 ios::badbit 和 ios::failbit

    没有;我通常以可以直接检查读取操作结果的方式编写代码。有关示例/讨论,请参见 http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.4。

    特别是如果您在该范围内使用动态分配的 C 字符串?

    一般来说这是个坏主意。

    你会在 catch() 中释放 C 字符串吗?

    不得不处理这类事情是主要原因之一。这并不容易做到正确。但我希望你意识到捕获异常和检查 ios::bits 是两件完全不同的事情。虽然您可以将流对象配置为抛出异常,而不仅仅是设置标志位 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 2012-05-06
      • 1970-01-01
      • 2014-06-01
      • 2015-05-20
      • 1970-01-01
      相关资源
      最近更新 更多