I am challenging myself to write a Palindrome tester using only SL algorithms, iterators etc. I also want to program to work with raw strings. Below, I use the raw pointer pal
in the copy_if
algorithm, but instead, how could I define an iterator to go here, i.e. by using something like begin(pal)
and 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;
}
Bonus Question: Is it possible to eliminate the need to copy_if()
by incrementing the iterators 'in place' from within equal()
i.e. when !isalpha(item)
?
Iterators implement the concept of pointers, when it comes to C++ library algorithms. And, as you've discovered, C++ library algorithms that take iterators are perfectly happy to also take pointers. It's the same concept.
And when you already have pointers to begin with there is no iterator, of some kind, that the pointers can be converted to.
It is true that
std::begin(arr)
and
std::end(arr)
are defined on flat arrays. But, guess what: they return a pointer to the beginning and the end of the array, and not an iterator class of some kind.
However, you cannot use std::begin()
, and std::end()
because by the time you need to use it, inside your function, the array was already decayed to a char *
. std::begin()
and std::end()
works on real arrays, and not decayed pointers.
If you insist on using iterators, you should pass a std::string
to your palindrome function, instead of a char *
. std::string
implements a begin()
and an end()
method that return a std::string::iterator
, that you can use.