简体   繁体   中英

Checking reversed text on C++ (doesn't work with a -1 index?)

I was making a simple palindrome checker and can't understand why the iterator works with index 0, but won't work with index -1, you can see that both codes print the SAME text, but not the same boolean.

Can anyone explain me what's the logic behind this?

The only different part on both codes is this:

for(int i=text.size();i>= -1 ;i--) Not Working
for(int i=text.size() -1 ;i>= 0 ;i--) Working

WORKING:


#include <iostream>

// Define is_palindrome() here:
std::string is_palindrome(std::string text){
  std::string reverse= "";
  for(int i=text.size()-1;i>=0;i--){
    reverse += text[i];
  }
  if(reverse == text){

    return text + " IS palindrome (reverse text: " + reverse +")";
  } else {

    return text + " NOT palindrome (reverse text: " + reverse + ")";
  }
}

int main() {
  
  std::cout << is_palindrome("madam") << "\n";
  std::cout << is_palindrome("ada") << "\n";
  std::cout << is_palindrome("lovelace") << "\n";
  
}

output

madam IS palindrome (reverse text: madam)
ada IS palindrome (reverse text: ada)
lovelace NOT palindrome (reverse text: ecalevol)

NOT WORKING

#include <iostream>

// Define is_palindrome() here:
std::string is_palindrome(std::string text){
  std::string reverse= "";
  for(int i=text.size();i>=-1;i--){
    reverse += text[i];
  }
  if(reverse == text){

    return text + " IS palindrome (reverse text: " + reverse +")";
  } else {

    return text + " NOT palindrome (reverse text: " + reverse + ")";
  }
}

int main() {

  std::cout << is_palindrome("madam") << "\n";
  std::cout << is_palindrome("ada") << "\n";
  std::cout << is_palindrome("lovelace") << "\n";

}

output

madam NOT palindrome (reverse text: madam)
ada NOT palindrome (reverse text: ada)
lovelace NOT palindrome (reverse text: ecalevol)

C++ uses 0-based indexing, ie valid indices of a N sized container are 0,1,2...N-1 . If you try to use an index out of bounds your code invokes undefined behavior.

Look at the output of this code:

#include <iostream>
#include <string>

void foo(const std::string& text){
    for(int i=text.size();i>=-1;i--){
        std::cout << i << "\n";
    }
}
int main() {
    foo("madam");
}

It is

5
4
3
2
1
0
-1

Both -1 and 5 are not elements of the string, because it has only 5 characters. (For 5 I am allowing myself to simplify the matter a bit, because strings have some oddities for accessing the one past last character null terminator. As -1 definitely is out of bounds and with std::string you usually need not deal with the null terminator explicitly, this is ok for this answer).

Now look at the output of this code:

#include <iostream>
#include <string>

void foo(const std::string& text){
    for(int i=text.size()-1;i>=0;i--){
        std::cout << i << "\n";
    }
}
int main() {
    foo("madam");
}

It is

4
3
2
1
0

It iterates all characters of the input string. Thats why this is correct and the other is wrong.

When your code has undefined behavior anything can happen. The results may appear to be correct or partially correct. Wrong code does not necessarily produce obviously wrong output.

Note that for(int i=text.size()-1;i>=0;i--) is a problem when the size of the string is 0 , because size() returns an unsigned which wraps around to result in a large positive number. You can avoid that by using iterators instead. There are reverse iterators that make a reverse loop look the same as a forward loop:

#include <iostream>
#include <string>

int main() {    
    std::string text("123");
    for (auto i = text.rbegin(); i != text.rend(); ++i) std::cout << *i;
}

Output

321

In addition to the answer by 463035818_is_not_a_number, you can also construct a string from another string using iterators:

#include <iostream>
#include <string>

int main() {    
    std::string text("123");
    std::string rev(crbegin(text), crend(text));
    std::cout << rev << '\n';
}

And there's std::reverse

#include <iostream>
#include <string>
#include <algorithm>

int main() {    
    std::string text("123");
    reverse(begin(text), end(text));
    std::cout << text << '\n';
}

But for a palindrome, you don't have to compare two whole strings. You just need to see of the first half of the string is equal to the reverse of the last half of the string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM