从char指针获取迭代器(C ++)

时间:2016-11-08 20:15:20

标签: c++ pointers iterator c++-standard-library stl-algorithm

我正在挑战自己只使用SL算法,迭代器等编写Palindrome测试器。我还想编程使用原始字符串。下面,我使用pal算法中的原始指针copy_if,但是,如何定义迭代器到这里,即使用begin(pal)end(pal + size)之类的东西?

#include <algorithm>
#include <iterator>
#include <cctype>

using namespace std;

bool isPalindrome(const char* pal) {
    if (!pal) { return(false); }

    int size = strlen(pal);
    string pal_raw;
    pal_raw.reserve(size);

    // Copy alphabetical chars only (no spaces, punctuations etc.) into pal_raw
    copy_if(pal, pal+size, back_inserter(pal_raw),
        [](char item) {return isalpha(item); }
    );

    // Test if palindromic, ignoring capitalisation
    bool same = equal(begin(pal_raw), end(pal_raw), rbegin(pal_raw), rend(pal_raw),
        [](char item1, char item2) {return tolower(item1) == tolower(item2); }
    );

    return same;
}

int main(){
    char pal[] = "Straw? No, too stupid a fad. I put soot on warts.";
    bool same = isPalindrome(pal);
    return 0;
}

奖金问题:是否可以通过增加迭代器来消除copy_if()的需要&#39;从equal()开始,即何时!isalpha(item)

2 个答案:

答案 0 :(得分:4)

当涉及到C ++库算法时,迭代器实现了指针的概念。而且,正如您所发现的那样,采用迭代器的C ++库算法非常乐意接受指针。这是相同的概念。

当你已经有指针开始时,没有任何迭代器,指针可以转换为。

确实

std::begin(arr)

std::end(arr)

在平面阵列上定义。但是,猜猜是:它们返回一个指向数组开头和结尾的指针,而不是某种迭代器类。

但是,您无法使用std::begin()std::end(),因为在您需要使用它时,在您的函数内部,数组已经衰减为char *std::begin()std::end()适用于实数组,而不是衰减指针。

如果你坚持使用迭代器,你应该将std::string传递给你的回文函数,而不是char *std::string实现了begin()end()方法,返回std::string::iterator,您可以使用。

答案 1 :(得分:2)

如果我这样做并且我想让它适用于不同类型,我会将该方法模板化 - 例如:

template<class ITER_T>
bool isPalindrome(ITER_T begin, ITER_T end) {
   // check for palindrome generically between begin and end
}

这样,它对const char *迭代器,std::stringstd::vector<char>std::map<char>使用相同的代码。如果实现得当,即使是其他类型的向量,映射和其他任何你可以得到迭代器的东西,而且项类型都有一个比较运算符定义。

作为奖励,我还可以检查字符数组,字符串或向量的一部分是否是回文。

顺便说一下,这个:

equal(begin(pal_raw), end(pal_raw), rbegin(pal_raw), rend(pal_raw), ...
如果字符串是回文,那么

会不必要地检查每个字符两次......效率不高。在这种情况下,你可以用“手动”循环做更好的事情(不确定是否有std算法)。

如果你想在重载函数中使begin(arr)/ end(arr)工作,你还是需要对它进行模板化,如下所示:

template<size_t N>
bool isPalindrome(const char (&arr)[N]) {
...

然而,您会为每个不同的数组大小获得单独的实例化。因此,最好使用迭代器进行模板化,并且只为任何char数组大小获取单个实例。

因此,要回答“奖金问题”,通过直接遍历数组,确实可以避免创建临时字符串(即动态内存分配):

template<typename ITER_T>
bool isPalindrome(ITER_T begin, ITER_T end) {
    while (begin < end) {
        if (tolower(*begin++) != tolower(*--end))
            return false;
    }
    return true;
}
bool same = isPalindrome(begin(pal), end(pal));

为了测试isalpha我留给你练习。提示:您可以在相等检查之前执行此操作并适当地增加/减少开始/结束(提示#2:我想到的解决方案将使用continue关键字)。

使其适用于与char不同的任意类型 - 然后类型特征可用于通过模板特化来抽象出isalpha / tolower调用。