Greg Brown Greg Brown - 26 days ago 13
C++ Question

Get an iterator from a char pointer (C++)

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)
?

Answer

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.

Comments