使用std :: istream_iterator限制std :: copy的范围 [英] Limiting the range for std::copy with std::istream_iterator

查看:171
本文介绍了使用std :: istream_iterator限制std :: copy的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我构建了一个最小的工作示例,以显示我在使用STL迭代器时遇到的问题。我正在使用 istream_iterator std中读取浮动 s(或其他类型): :istream

I have constructed a minimal working example to show a problem I've encountered using STL iterators. I'm using istream_iterator to read floatss (or other types) from a std::istream:

#include <iostream>
#include <iterator>
#include <algorithm>

int main() {
   float values[4];
   std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(), values);
   std::cout << "Read exactly 4 floats" << std::endl; // Not true!
}

这将读取所有可能的浮动 s,直到EOF进入,这是固定大小,4,所以现在显然我想限制范围以避免溢出并准确读取/最多4个值。

This reads all possible floatss, until EOF into values, which is of fixed size, 4, so now clearly I want to limit the range to avoid overflows and read exactly/at most 4 values.

使用更多普通迭代器(即RandomAccessIterator),提供 begin + 4 未超过结束你会这样做:

With more "normal" iterators (i.e. RandomAccessIterator), provided begin+4 isn't past the end you'd do:

std::copy(begin, begin+4, out);

准确读取4个元素。

如何使用 std :: istream_iterator 执行此操作?显而易见的想法是将对 std :: copy 的调用更改为:

How does one do this with std::istream_iterator? The obvious idea is to change the call to std::copy to be:

std::copy(std::istream_iterator<float>(std::cin), std::istream_iterator<float>(std::cin)+4, values);

但是(相当可以预见)这不能编译,没有 operator + :

But (fairly predictably) this doesn't compile, there are no candidates for operator+:

g++ -Wall -Wextra test.cc
test.cc: In function ‘int main()’:
test.cc:7: error: no match for ‘operator+’ in ‘std::istream_iterator<float, char, std::char_traits<char>, long int>(((std::basic_istream<char, std::char_traits<char> >&)(& std::cin))) + 4’

有什么建议吗?是否有正确的STLified前C ++ 0x方法来实现这一目标?显然我可能只是把它写成for循环,但我想在这里学习一些关于STL的东西。我一半想知道滥用 std :: transform std :: merge 等以某种方式实现此功能,但我我不太明白该怎么做。

Any suggestions? Is there a correct, "STLified" pre-C++0x way to achieve this? Obviously I could just write it out as a for loop, but I'm looking to learn something about the STL here. I half wondered about abusing std::transform or std::merge etc. to achieve this functionality somehow, but I can't quite see how to do it.

推荐答案

正如您所要求的非C ++ 0x解决方案,这里有另一种选择使用 std :: generate_n 和生成器函子而不是 std :: copy_n 和迭代器:

As you requested a non-C++0x solution, here's an alternative that uses std::generate_n and a generator functor rather than std::copy_n and iterators:

#include <algorithm>
#include <string>
#include <istream>
#include <ostream>
#include <iostream>

template<
    typename ResultT,
    typename CharT = char,
    typename CharTraitsT = std::char_traits<CharT>
>
struct input_generator
{
    typedef ResultT result_type;

    explicit input_generator(std::basic_istream<CharT, CharTraitsT>& input)
      : input_(&input)
    { }

    ResultT operator ()() const
    {
        // value-initialize so primitives like float
        // have a defined value if extraction fails
        ResultT v((ResultT()));
        *input_ >> v;
        return v;
    }

private:
    std::basic_istream<CharT, CharTraitsT>* input_;
};

template<typename ResultT, typename CharT, typename CharTraitsT>
inline input_generator<ResultT, CharT, CharTraitsT> make_input_generator(
    std::basic_istream<CharT, CharTraitsT>& input
)
{
    return input_generator<ResultT, CharT, CharTraitsT>(input);
}

int main()
{
    float values[4];
    std::generate_n(values, 4, make_input_generator<float>(std::cin));
    std::cout << "Read exactly 4 floats" << std::endl;
}






如果你愿意,然后,您可以将此生成器与 boost :: generator_iterator 将生成器用作输入迭代器。


If you wanted to, you could then use this generator in conjunction with boost::generator_iterator to use the generator as an input iterator.

这篇关于使用std :: istream_iterator限制std :: copy的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆