有没有标准的算法可以复制到?
Is There a Standard Algorithm to Copy Until?
我正在使用 istream_iterator<char> it
,所以我无法反向迭代范围(或迭代两次,没有太多麻烦。)
我想复制直到满足条件。在标准库中有没有这样的东西:
copy_until(it, istream_iterator<char>(), ostream_iterator<char>(cout), [](const unsigned char i){ return isalpha(i); })
如果我必须滚动一些东西,我只是希望有一些我无法弄清楚的魔法。
编辑:
我希望从我的 copy_until
函数中得到的行为是:
while(it != istream_iterator<char>()) {
if(!isalpha(static_cast<unsigned char>(*it))) break;
cout << *it++;
}
开箱前没有副本。由于您是从 istream 复制的,因此除了使用带有 break 语句的循环之外别无选择。
http://en.cppreference.com/w/cpp/algorithm 为 C++ 中可用的所有算法提供了非常有用的参考(不仅是 算法库 中的算法,还有 Numeric, Memory, and CStd Libraries.) 以下是复制算法,即它们采用输入迭代器,输出迭代器和 lambda 作为参数:
copy_if
"Copies the elements in the range, defined by [first
, last
)... Only copies the elements for which the predicate pred
returns true"
transform
"Applies the given function to a range and stores the result in another range."
remove_copy_if
"Copies elements from the range [first
, last
), to another range beginning at d_first
, omitting the elements which satisfy specific criteria"
replace_copy_if
"Copies the all elements from the range [first
, last
) to another range beginning at d_first
replacing all elements satisfying specific criteria with new_value
"
unique_copy
"Copies the elements from the range [first
, last
), to another range beginning at d_first
in such a way that there are no consecutive equal elements... Elements are compared using the given binary predicate p
"
partition_copy
"Copies the elements from the range [first
, last
) to two different ranges depending on the value returned by the predicate p
. The elements, that satisfy the predicate p
, are copied to the range beginning at d_first_true
. The rest of the elements are copied to the range beginning at d_first_false
"
merge
需要 2nd 输入范围
set_difference
需要 2nd 输入范围
set_intersection
需要 2nd 输入范围
set_symmetric_difference
需要 2nd 输入范围
set_union
需要 2nd 输入范围
adjacent_difference
"Computes the differences between the second and the first of each adjacent pair of elements of the range [first
, last
)... Differences are calculated using the given binary function op
"
partial_sum
"Computes the partial sums of the elements in the subranges of the range [first
, last
) and writes them to the range beginning at d_first
... To sum up the elements, the second version uses the given binary function op
."
exclusive_scan
"Computes an exclusive prefix sum operation using binary_op
for the range [first
, last
)"
inclusive_scan
"Computes an inclusive prefix sum operation using binary_op
for the range [first
, last
)"
transform_exclusive_scan
"Transforms each element in the range [first
, last
) with unary_op
, then computes an exclusive prefix sum operation using binary_op
over the resulting range"
transform_inclusive_scan
"Transforms each element in the range [first
, last
) with unary_op
, then computes an inclusive prefix sum operation using binary_op
over the resulting range"
因为lambda只是用来修改范围[first
,last
)的1:1赋值到d_first
; transform
、replace_copy_if
和所有 数值库 算法都没有帮助(adjacent_difference
、partial_sum
、exclusive_scan
、 inclusive_scan
、transform_exclusive_scan
和 transform_inclusive_scan
。)
- 如果满足 lambda 条件后,范围 [
it
, istream_iterator<char>()
) 的剩余部分将直接复制到 2nd输出迭代器,partition_copy
可以解决你的问题
- 如果在满足 lambda 条件后 [
it
, istream_iterator<char>()
) 范围的剩余部分将被一个函数迭代,这个函数可以被调用copy_if
(或remove_copy_if
或unique_copy
)满足条件后的每个值
- 但在一般情况下,您的问题的答案是标准算法不提供 "copy_until" 因此您需要使用
while
-loop
只是为了完整性,因为标准没有提供开箱即用的解决方案,这就是我的解决方案:
template<class _InIt, class _OutIt, class _Pr>
inline void copy_until (_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) {
while ((_First != _Last) && _Pred(*_First)) {
*_Dest++ = *_First++;
}
}
这就是我使用它的方式:
copy_until(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(os),
[] (char c) { return <some usefull condition here> });
例如,从输入流中读取一个只有 alnum 字符的字符串:
std::istream& operator>> (std::istream& is, std::string& n) {
std::ostringstream str;
copy_until(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(str),
std::isalnum);
n = str.str();
return is;
}
copy_until
可以用std::find_if
实现,std::copy
.
使用与redleg相同的结构,算法可以先搜索终止符,然后复制范围。
template <class _InIt, class _OutIt, class _Pr>
inline void copy_until(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) {
_InIt _posTerm = std::find_if(_First, _Last, _Pred);
std::copy(_First, _posTerm, _Dest);
}
模板需要 <algorithm>
和 <iterator>
.
这是一个如何使用它的例子:
std::vector<int> source = {1,2,3,4,5,6,7,8};
std::vector<int> dest {};
copy_until(source.begin(),source.end(),
back_inserter(dest),[](int c) {return c == 5;});
输出:
source: 1 2 3 4 5 6 7 8
dest : 1 2 3 4
因为std::copy
定义复制到最后,但不包括最后或其他术语[first,last)
,find_if
的位置不复制。
如果您需要包含 until,意思是 [first,last]
,我们需要做更多检查。如果终止符在 end()
处,则不应推进迭代器。
template <class _InIt, class _OutIt, class _Pr>
inline void copy_until(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred)
{
_InIt _posTerm = std::find_if(_First, _Last, _Pred);
if (_posTerm != _Last ) { _posTerm++; }
std::copy(_First,_posTerm,_Dest);
}
之前的例子现在输出:
source: 1 2 3 4 5 6 7 8
dest : 1 2 3 4 5
我正在使用 istream_iterator<char> it
,所以我无法反向迭代范围(或迭代两次,没有太多麻烦。)
我想复制直到满足条件。在标准库中有没有这样的东西:
copy_until(it, istream_iterator<char>(), ostream_iterator<char>(cout), [](const unsigned char i){ return isalpha(i); })
如果我必须滚动一些东西,我只是希望有一些我无法弄清楚的魔法。
编辑:
我希望从我的 copy_until
函数中得到的行为是:
while(it != istream_iterator<char>()) {
if(!isalpha(static_cast<unsigned char>(*it))) break;
cout << *it++;
}
开箱前没有副本。由于您是从 istream 复制的,因此除了使用带有 break 语句的循环之外别无选择。
http://en.cppreference.com/w/cpp/algorithm 为 C++ 中可用的所有算法提供了非常有用的参考(不仅是 算法库 中的算法,还有 Numeric, Memory, and CStd Libraries.) 以下是复制算法,即它们采用输入迭代器,输出迭代器和 lambda 作为参数:
copy_if
"Copies the elements in the range, defined by [first
,last
)... Only copies the elements for which the predicatepred
returns true"transform
"Applies the given function to a range and stores the result in another range."remove_copy_if
"Copies elements from the range [first
,last
), to another range beginning atd_first
, omitting the elements which satisfy specific criteria"replace_copy_if
"Copies the all elements from the range [first
,last
) to another range beginning atd_first
replacing all elements satisfying specific criteria withnew_value
"unique_copy
"Copies the elements from the range [first
,last
), to another range beginning atd_first
in such a way that there are no consecutive equal elements... Elements are compared using the given binary predicatep
"partition_copy
"Copies the elements from the range [first
,last
) to two different ranges depending on the value returned by the predicatep
. The elements, that satisfy the predicatep
, are copied to the range beginning atd_first_true
. The rest of the elements are copied to the range beginning atd_first_false
"需要 2nd 输入范围merge
需要 2nd 输入范围set_difference
需要 2nd 输入范围set_intersection
需要 2nd 输入范围set_symmetric_difference
需要 2nd 输入范围set_union
adjacent_difference
"Computes the differences between the second and the first of each adjacent pair of elements of the range [first
,last
)... Differences are calculated using the given binary functionop
"partial_sum
"Computes the partial sums of the elements in the subranges of the range [first
,last
) and writes them to the range beginning atd_first
... To sum up the elements, the second version uses the given binary functionop
."exclusive_scan
"Computes an exclusive prefix sum operation usingbinary_op
for the range [first
,last
)"inclusive_scan
"Computes an inclusive prefix sum operation usingbinary_op
for the range [first
,last
)"transform_exclusive_scan
"Transforms each element in the range [first
,last
) withunary_op
, then computes an exclusive prefix sum operation usingbinary_op
over the resulting range"transform_inclusive_scan
"Transforms each element in the range [first
,last
) withunary_op
, then computes an inclusive prefix sum operation usingbinary_op
over the resulting range"
因为lambda只是用来修改范围[first
,last
)的1:1赋值到d_first
; transform
、replace_copy_if
和所有 数值库 算法都没有帮助(adjacent_difference
、partial_sum
、exclusive_scan
、 inclusive_scan
、transform_exclusive_scan
和 transform_inclusive_scan
。)
- 如果满足 lambda 条件后,范围 [
it
,istream_iterator<char>()
) 的剩余部分将直接复制到 2nd输出迭代器,partition_copy
可以解决你的问题 - 如果在满足 lambda 条件后 [
it
,istream_iterator<char>()
) 范围的剩余部分将被一个函数迭代,这个函数可以被调用copy_if
(或remove_copy_if
或unique_copy
)满足条件后的每个值 - 但在一般情况下,您的问题的答案是标准算法不提供 "copy_until" 因此您需要使用
while
-loop
只是为了完整性,因为标准没有提供开箱即用的解决方案,这就是我的解决方案:
template<class _InIt, class _OutIt, class _Pr>
inline void copy_until (_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) {
while ((_First != _Last) && _Pred(*_First)) {
*_Dest++ = *_First++;
}
}
这就是我使用它的方式:
copy_until(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(os),
[] (char c) { return <some usefull condition here> });
例如,从输入流中读取一个只有 alnum 字符的字符串:
std::istream& operator>> (std::istream& is, std::string& n) {
std::ostringstream str;
copy_until(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(str),
std::isalnum);
n = str.str();
return is;
}
copy_until
可以用std::find_if
实现,std::copy
.
使用与redleg相同的结构,算法可以先搜索终止符,然后复制范围。
template <class _InIt, class _OutIt, class _Pr>
inline void copy_until(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) {
_InIt _posTerm = std::find_if(_First, _Last, _Pred);
std::copy(_First, _posTerm, _Dest);
}
模板需要 <algorithm>
和 <iterator>
.
这是一个如何使用它的例子:
std::vector<int> source = {1,2,3,4,5,6,7,8};
std::vector<int> dest {};
copy_until(source.begin(),source.end(),
back_inserter(dest),[](int c) {return c == 5;});
输出:
source: 1 2 3 4 5 6 7 8
dest : 1 2 3 4
因为std::copy
定义复制到最后,但不包括最后或其他术语[first,last)
,find_if
的位置不复制。
如果您需要包含 until,意思是 [first,last]
,我们需要做更多检查。如果终止符在 end()
处,则不应推进迭代器。
template <class _InIt, class _OutIt, class _Pr>
inline void copy_until(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred)
{
_InIt _posTerm = std::find_if(_First, _Last, _Pred);
if (_posTerm != _Last ) { _posTerm++; }
std::copy(_First,_posTerm,_Dest);
}
之前的例子现在输出:
source: 1 2 3 4 5 6 7 8
dest : 1 2 3 4 5