Reputation:
I wrote the following to check if text is palindrome, I run it on leetcode and I am getting errors:
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
while (!isalpha(s[r]))
{
--r;
}
while (!isalpha(s[l]))
{
++l;
}
if (tolower(s[r])!=tolower(s[l]))
return false;
--r;
++l;
}
return true;
}
};
Line 1061: Char 9: runtime error: addition of unsigned offset to 0x7ffc7cc10880 overflowed to 0x7ffc7cc1087f (basic_string.h) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1070:9
what's the problem with my code?
Upvotes: 1
Views: 8684
Reputation: 125
As others have said, you are running out of bonds. Here is a simplified solution that will not run out of bonds and also is free of if-then-else spaghetti code:
bool IsPalindrome(const char *s)
{
int forward, totLen, halfLen, backward;
totLen = (int)strlen(s); // Total length
halfLen = totLen / 2; // Half the length, if totLen is odd, will ignore the character in the middle
for (forward = 0; forward < halfLen; forward++) // Index from front of string
{
backward = totLen - (forward + 1); // Corresponding index from back of string
if (s[forward] != s[backward])
return false; // Not a palindrome
}
return true; // Got one!
}
Upvotes: -1
Reputation: 337
A similar modified approach, where you continue the loop whenever you encounter any non-alphanumeric char solves the problem. Here:
bool isPalindrome(string s) {
int start=0,end=s.length()-1;
while(start<=end){
if(!isalpha(s[start]) && !isdigit(s[start])){
start++;
continue;
}
if(!isalpha(s[end]) && !isdigit(s[end])){
end--;
continue;
}
if(tolower(s[start])!=tolower(s[end])){
return false;
}
start++;
end--;
}
return true;
}
Upvotes: 0
Reputation: 1062
I think you were very close to the solution. The pitfall here are that:
The easy way to fix this kind of issue is to do one single action for every iteration. you can achieve this just using "else".
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
if(!isalpha(s[r]))
{
--r;
}
else if(!isalpha(s[l]))
{
++l;
}
else if (tolower(s[r])!=tolower(s[l]))
{
return false;
}
else
{
--r;
++l;
}
}
return true;
}
};
Upvotes: 0
Reputation: 16453
You're going out of bounds here:
while (!isalpha(s[r]))
and here
while (!isalpha(s[l]))
r
can became negative and l
can become >= s.length()
.
You should add some checks like
while (l < r && !isalpha(s[r]))
and
while (l < r && !isalpha(s[l]))
The same problem in this line
if (tolower(s[r])!=tolower(s[l]))
This should be
if (l < r && tolower(s[r])!=tolower(s[l]))
A different approach is to erase all non-alpha characters from s
with
std::erase_if(s, [](char c) { return !isalpha(c); });
and remove the inner while loops.
Upvotes: 3