【问题标题】:How do I pass a specific number of characters from an istream to an ostream如何将特定数量的字符从 istream 传递到 ostream
【发布时间】:2014-04-21 02:57:54
【问题描述】:

我有一个 istream(在这种情况下是 ifstream),我想将特定数量的字符从它写入一个 ostream(具体来说是 cout)。

我可以看到使用 istream.get() 之类的方法可以做到这一点,但这会创建一个中间缓冲区,这是我希望避免的。

类似:

size_t numCharacters = 8;
ostream.get(istream, numCharacters);

有人能指出正确的方向吗?

感谢阅读:)

编辑:添加了 c++ 标签 编辑:固定标题:/

新编辑:

非常感谢各位的回答。作为旁注,任何人都可以解释 copy_n 的这种奇怪行为吗?基本上它似乎不消耗从输入流复制的最后一个元素,即使该元素出现在输出流中。下面的代码应该说明:

string test = "testing the weird behaviour of copy_n";
stringstream testStream(test);

istreambuf_iterator<char> inIter( testStream );
ostream_iterator<char> outIter( cout );

std::copy_n(inIter, 5, outIter);
char c[10];
testStream.get(c,10);
cout << c;

我得到的输出是:

测试w

我期望的输出是:

测试我们

cppreference.com 的文档中没有提到这种行为。任何进一步的帮助将不胜感激:)

我目前的解决方法是在复制后寻找 1 个额外元素 - 但这显然不理想。

【问题讨论】:

  • @JoachimPileborg:你肯定是指std::istreambuf_iterator&lt;char&gt;std::ostreambuf_iterator&lt;char&gt;。尤其是输入端很重要,因为std::istream_iterator&lt;char&gt; 会跳过空格。此外,...buf... 版本更高效,因为它们不会为每个对象创建 sentry
  • 谢谢大家 - 这似乎对我有用 :) 如果你们中的某个人想把它作为答案发布,我很乐意给你打勾。
  • 回复。您的编辑,检查get 是否成功。
  • 您注意到的问题似乎是标准中的规范不足:标准声明 n 元素被复制,但它没有声明输入和输出迭代器需要增加n 次!例如,查看 libstdc++ 中的实现表明源代码没有增加n 次!对于 InputIterator 以外的其他迭代器类别,这无关紧要,但对于 InputIterator 却是。

标签: c++ stl istream ostream


【解决方案1】:

如果你想限制字符数你想提高效率,你将无法避免复制字节。对于没有缓冲区的慢版本,您可以使用std::copy_n()

std::copy_n(std::istreambuf_iterator<char>(in),
             std::istreambuf_iterator<char>(),
             std::ostreambuf_iterator<char>(out),
             n);

我很确定这比读取缓冲区或其序列并写入缓冲区要慢很多(顺便说一句,请确保调用std::ios_base::sync_with_stdio(false),否则执行任何操作都可能非常慢std::cout)。

您还可以创建一个过滤流缓冲区,即从std::streambuf 派生的类,使用另一个流缓冲区作为其数据源。过滤器将在n 字符之后指示没有更多字符。它在内部仍会使用缓冲区,因为单独处理字符很慢。然后它可以用作:

limitbuf buf(in, n);
out << &buf;

【讨论】:

  • 为什么会慢一些?
  • @Etherealone:我不确定 this 是什么。但是,处理单个字符比处理批量字符要慢。当在概念上使用std::copy_n() 时,每个字符都是单独处理的,相当于:检查是否有字符,获取它,调整流缓冲区以指示已消耗,检查输出中是否有空间粘贴字符,把它粘在那里,调整流缓冲区以指示还有一个字符。对于缓冲区,这些检查对字符序列进行一次,CPU 将复制字符组。
  • 原则上,对于分段序列,实现可以为std::copy_n() 做一些花哨的事情:从 streambuf 迭代器获取流缓冲区的缓冲区并直接在它们之间复制。但是,我知道的唯一实现是我创建的那个实现了一些优化,它没有对std::copy_n() 进行这种优化。我现在无法准确测量差异,但我不会感到惊讶的是,明确使用缓冲区的速度要快一个数量级(对于内存中的源和目标流)。
  • 非常感谢您的回答@DietmarKühl!这主要为我工作。如果您有时间,可以看看我对上述问题的编辑。我从 copy_n 看到了一些奇怪的行为。
猜你喜欢
  • 2013-09-16
  • 1970-01-01
  • 2020-11-24
  • 2013-10-10
  • 2011-05-11
  • 2011-05-03
  • 2018-04-25
  • 2011-02-22
  • 1970-01-01
相关资源
最近更新 更多