2017-10-10 36 views
2

在给定签名的函数中,我希望以这种方式重新排列序列[first,last)的元素,使所有满足谓词的元素都放在不需要的元素之前,并将迭代器返回给第一个不满足给定谓词的元素。通过使用迭代器的谓词重新排列

我的算法是

  • 开始遍历序列上
  • 如果存在元素不满足谓词再次与最后一个
  • 检查更换,如果在同一位置的新元素满足它
  • 如果不是用(last-1)替换它,如果是,请继续进一步
  • 重复,直到我们到达我们已经替换的元素之一

我的代码

template<class Iterator, class Predicate> 
Iterator Rearrange(Iterator first, Iterator last, Predicate pred) { 
    auto res = first; 
    if (first == last) { 
    ; 
    } 
    else { 
    auto run = first; 
    auto end = last; 
    auto tmp = *first; 
    while (run != end) { 
     if (pred(*run) == false) { 
     again: tmp = *(--end); 
    *end = *run; 
    *run = tmp; 
    if (pred(*run) == false) { 
     goto again; 
    } 
     } 
     ++run; 
    } 
    } 
    return res; 
} 

它给了我

terminate called after throwing an instance of 'std::range_error' 
    what(): dereferencing end of sequence 
Aborted 

,我无法找到和理解。也就是说,我可以读取某个地方,我试图在容器外取消引用元素,但在我的程序中看不到它。任何人都可以帮助我解决编码错误或改进算法的逻辑吗?

+1

我希望18年前,当工作从VB6转移到C++和C#时,我再也不用再处理goto了。 – Steve

回答

3

如果输入范围非空,且其中没有元素满足谓词,则代码将卡在goto循环中,并且不会再次到达while。最后,--end将在first之前采取end

如果这是一个学习练习,我建议你摆脱goto;你不想学习不好的做法,虽然goto可以有罕见的合法用途,替换循环不是其中之一。此外,与tmp跳舞可以替换为std::swap

如果这不是一个学习练习,只需使用std::partition,它完全符合您的需求。