找到Palindromes的这两个功能之间的区别

时间:2011-01-10 16:43:08

标签: c++

我写了一个函数来检查一个单词是否是回文,但是“意外地”,这个函数失败得非常严重,这里是:

bool isPalindrome (const string& s){
 string reverse = "";
 string original = s;
 for (string_sz i = 0; i != original.size(); ++i){
  reverse += original.back();
  original.pop_back();
 }

 if (reverse == original)
  return true;
 else
  return false;
}

当你传入一个只包含一个字符的字符串时,它给了我“字符串迭代器偏移超出范围错误”,即使我们传入一个空字符串也返回true(虽然我知道它是因为反向变量的初始化)并且当您传入未分配的字符串时,例如:

string input;
isPalindrome(input);

后来,我发现了一个更好的功能,它可以像你期望的那样工作:

bool found(const string& s)
{
 bool found = true;
 for (string::const_iterator i = s.begin(), j = s.end() - 1; i < j; ++i, --j) {
  if (*i != *j)
   found = false;
 }
 return found;
}

与第一个函数不同,当你给它一个未赋值的字符串变量或一个空字符串并且适用于单个字符等时,这个函数会正确失败...

所以,堆栈溢出的好人请指出我为什么第一个功能如此糟糕......

谢谢。

5 个答案:

答案 0 :(得分:5)

for (string_sz i = 0; i != original.size(); ++i) {
    reverse += original.back();
    original.pop_back();
}
当你从后面弹出元素时,

original.size()会发生变化。实际上,您继续递增i并递减original.size();他们可能永远不会平等。

if (reverse == original)

这永远不会成立,因为您刚刚从original中删除了所有元素,并将它们以相反的顺序添加到reverse。此时original将始终为空。

答案 1 :(得分:1)

这可能不是您想要的,但reverse已在STL中作为算法实现:

bool isPalindrome( const std::string & str )
{
   std::string rev( str );
   std::reverse( rev.begin(), rev.end() );
   return str==rev;
}

正如@James McNellis指出的那样,通过在原始字符串上使用反向迭代器直接构造反向字符串,可以进一步压缩(无需任何算法):

bool isPalindrome( const std::string & str )
{
   return str == std::string( str.rbegin(), str.rend() );
}

答案 2 :(得分:1)

你发现函数很可能依赖于STL std :: compare函数和字符串的begin()/ end()rbegin()/ rend()函数。并且可以是一行功能:

return std::equal(s.begin(), s.end(), s.rbegin());

std::equal()函数比较两个相同长度的范围。

begin()/ end()函数提供前向迭代器,而rbegin()提供reverse iterator,即从字符串末尾开始并到达开头的迭代器。

答案 3 :(得分:0)

声称要反转字符串的循环实际上并没有这样做。当您从列表中删除项目时,您也在递增i。在某些情况下,我认为i可以跳过当前size并永远迭代。

您可以使用reverse

代替循环

std::reverse(original.begin(), original.end());

然后完成剩下的工作。如果空字符串是回文符号,则符合您的要求。

答案 4 :(得分:0)

你的解决方案太复杂了;)

bool is_palindrome(std::string const& s) {
    if (s.empty()) return false; // if this is required.
    return !lexicographical_compare(s.begin(), s.end(), s.rbegin(), s.rend());
}

编辑:或者,正如Etienne所说,只需使用std :: equal ...

bool is_palindrome(std::string const& s) {
    if (s.empty()) return false; // if this is required.
    return equal(s.begin(), s.end(), s.rbegin());
}