繁体   English   中英

使用std :: istream_iterator限制std :: copy的范围

[英]Limiting the range for std::copy with std::istream_iterator

我构建了一个最小的工作示例来显示我使用STL迭代器遇到的问题。 我正在使用istream_iteratorstd::istream读取floats (或其他类型):

#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!
}

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

使用更多“正常”迭代器(即RandomAccessIterator),提供的begin+4不会超过您的结束:

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

准确阅读4个元素。

如何用std::istream_iterator做到这一点? 显而易见的想法是将对std::copy的调用更改为:

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

但(相当可以预见)这不会编译,没有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::transformstd::merge等以某种方式实现这个功能,但我不知道该怎么做。

当您请求非C ++ 0x解决方案时,这里有一个使用std::generate_n和生成器函子而不是std::copy_n和迭代器的替代方法:

#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结合使用,以将生成器用作输入迭代器。

看一下std::copy_n

如果您没有std::copy_n ,那么编写自己的代码非常简单:

namespace std_ext { 
template<class InputIterator, class Size, class OutputIterator>
OutputIterator copy_n(InputIterator first, Size n, OutputIterator result) {
    for (int i=0; i<n; i++) {
        *result = *first;
        ++result;
        ++first;
    }
    return result;
}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM