std :: find()向后在C风格数组? [英] std::find() backwards on C-style array?

查看:120
本文介绍了std :: find()向后在C风格数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我需要使用 s

  typedef struct tagSOMESTRUCT //由别人定义C兼容
{
int count;
int elements [256];
} SOMESTRUCT;

SOMESTRUCT s;

并说我有一个函数:

 模板< typename RevFwdIt> 
std :: pair< RevFwdIt,RevFwdIt> some_slice_rev(RevFwdIt rbegin,RevFwdIt rend)
{
RevFwdIt it = basename_rev(rbegin,rend);
RevFwdIt e = std :: find(rbegin,it,5);
return std :: make_pair(e == it?rbegin:e,it);
}

为了使用这个功能,我需要说

  some_slice_rev(& s.elements [s.count-1],& s.elements [-1]); 

其中(IMHO)由于一个错误而是丑陋的并且容易出错。 / p>

一方面,我不能简单地将 some_slice_rev 更改为 some_slice 使用(更好的)

  some_slice(& s.elements [0],& s.elements [ s.count]); 

因为 std :: find



另一方面,代码本身已经对我看起来很坏,因为我看不到 std :: find 会处理作为原始指针的反向迭代器。



在这种情况下修复代码的最好方法是什么?有没有办法使用反向迭代器是原始指针?或者是否有修复此问题的标准重构机制其他,而不是更改 SOMESTRUCT

解决方案

我不太确定我理解这个问题(这可能是从笨拙的混合迭代器的方向,你似乎试图避免),但我会引导你的注意力 std :: reverse_iterator

  #include< iostream> 
#include< iterator>

//例如
模板< typename Iter>
void print_it(Iter first,Iter last)
{
std :: cout<< '|';

for(; first!= last; ++ first)
std :: cout<< ''<< *第一<< |;

std :: cout<< std :: endl;
}

int main()
{
int arr [10] = {1,2,3,4}

int * begin = arr,* end = arr + 4;

print_it(begin,end);
print_it(std :: reverse_iterator< int *>(end),
std :: reverse_iterator< int *>(begin)
}

它们的工作方式类似于双向迭代器, + 在内部 - ,反之亦然。



丑陋。您可能需要一些实用功能:

  #include< iostream> 
#include< iterator>

//例如
模板< typename Iter>
void print_it(Iter first,Iter last)
{
std :: cout< '|';

for(; first!= last; ++ first)
std :: cout<< ''<< *第一<< |;

std :: cout<< std :: endl;
}

template< typename Iter>
std :: reverse_iterator< Iter> make_reverse_iterator(Iter iter)
{
return std :: reverse_iterator< Iter>(iter)
}

int main()
{
int arr [10] = {1,2,3,4}

int * begin = arr,* end = arr + 4;

print_it(begin,end);
print_it(make_reverse_iterator(end),
make_reverse_iterator(begin));
}






这:

 模板< typename ForwardIterator> 
std :: pair< ForwardIterator,ForwardIterator>
some_slice(ForwardIterator begin,ForwardIterator end)
{
typedef std :: reverse_iterator< ForwardIterator> rev_iter;

rev_iter it = basename(rev_iter(end),rev_iter(begin));
rev_iter e = std :: find(rev_iter(end),it,5);

return std :: make_pair(it.base(),e.​​base());
}






,但请注意, s.elements [s.count] 是未定义的行为,如果 s.count 256 ,因为 s.elements [s.count] *(s.elements + s.count)



在实践中,完整的表达式是很好的,因为& ; * x 取消到 x ,但你仍然可能想避免它:

  some_slice(s.elements,s.elements + s.count); 

s.elements [-1] 也是未定义的行为,虽然我认为严格来说它可能是合法的,因为你在数组之前有一个 int 成员。


Say I need to use s:

typedef struct tagSOMESTRUCT   // Defined by someone else; C-compatible
{
    int count;
    int elements[256];
} SOMESTRUCT;

SOMESTRUCT s;

and say I have a function like:

template<typename RevFwdIt>
std::pair<RevFwdIt, RevFwdIt> some_slice_rev(RevFwdIt rbegin, RevFwdIt rend)
{
    RevFwdIt it = basename_rev(rbegin, rend);
    RevFwdIt e = std::find(rbegin, it, 5);
    return std::make_pair(e == it ? rbegin : e, it);
}

In order to use this function, I need to say

some_slice_rev(&s.elements[s.count - 1], &s.elements[-1]);

which (IMHO) is ugly and error-prone due to the off-by-one errors.

On the one hand, I cannot simply change some_slice_rev to some_slice to use the (much better)

some_slice(&s.elements[0], &s.elements[s.count]);

because then std::find would search from the beginning instead of the end.

On the other hand, the code itself already looks broken to me, because I can't see how std::find would handle "reverse iterators" that are raw pointers.

What is the best way to fix the code in situations like this? Is there any way to work with reverse-iterators that are raw pointers? Or is there a standard refactoring mechanism for fixing this, other than changing SOMESTRUCT?

解决方案

I'm not quite sure I understand the question (that may be from the awkward mixing of iterator directions you seem to be trying to avoid), but I'll just direct your attention to std::reverse_iterator:

#include <iostream>
#include <iterator>

// for example
template <typename Iter>
void print_it(Iter first, Iter last)
{
    std::cout << '|';

    for (; first != last; ++first)
        std::cout << ' ' << *first << " |";

    std::cout << std::endl;
}

int main()
{
    int arr[10] = {1, 2, 3, 4};

    int *begin = arr, *end = arr + 4;

    print_it(begin, end);
    print_it(std::reverse_iterator<int*>(end),
                std::reverse_iterator<int*>(begin));
}

They work like bi-directional iterators, except ++ is internally --, and vice versa.

Note that it's a bit ugly. You might want some utility function:

#include <iostream>
#include <iterator>

// for example
template <typename Iter>
void print_it(Iter first, Iter last)
{
    std::cout << '|';

    for (; first != last; ++first)
        std::cout << ' ' << *first << " |";

    std::cout << std::endl;
}

template <typename Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter iter)
{
    return std::reverse_iterator<Iter>(iter);
}

int main()
{
    int arr[10] = {1, 2, 3, 4};

    int *begin = arr, *end = arr + 4;

    print_it(begin, end);
    print_it(make_reverse_iterator(end),
                make_reverse_iterator(begin));
}


So I think you want this:

template<typename ForwardIterator >
std::pair<ForwardIterator, ForwardIterator>
    some_slice(ForwardIterator begin, ForwardIterator end)
{
    typedef std::reverse_iterator<ForwardIterator> rev_iter;

    rev_iter it = basename(rev_iter(end), rev_iter(begin));
    rev_iter e = std::find(rev_iter(end), it, 5);

    return std::make_pair(it.base(), e.base());
}


Relatively off-topic now, but note that s.elements[s.count] is undefined behavior if s.count is 256, because s.elements[s.count] is *(s.elements + s.count), which isn't a valid array element to dereference.

In practice, the full expression is fine because &*x cancels out to x, but you still probably want to avoid it:

some_slice(s.elements, s.elements + s.count);

s.elements[-1] may also be undefined behavior, though I think strictly speaking it might be legal by accident, because you have an int member before the array.

这篇关于std :: find()向后在C风格数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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