我有一个初学者问题:
bool _isPalindrome(const string& str)
{
return _isPalindrome(str.begin(), str.end()); // won't compile
}
bool _isPalindrome(string::iterator begin, string::iterator end)
{
return begin == end || *begin == *end && _isPalindrome(++begin, --end);
}
我在这里做错了什么?为什么str.begin()
未将类型检查为string::iterator
?
更新:更好的版本:
bool BrittlePalindrome::_isPalindrome(string::const_iterator begin, string::const_iterator end)
{
return begin >= end || *begin == *(end - 1) && _isPalindrome(++begin, --end);
}
答案 0 :(得分:5)
str.begin()
是非const,而参数str
是 const。
您可以更改迭代器接受方法以接受const_iterator
,也可以更改字符串接受方法以接受非常量string
。
或者你可以抛弃str
的常数,但那将是专利Bad Idea TM 。
(我还会在迭代器接受方法上对你的return语句加以括号,以使你的意图更清晰,但这既不在这里也不在那里。)
答案 1 :(得分:5)
假设您在第一个函数之前有第二个函数的声明,主要问题是您通过const
引用传递字符串。
这意味着您有权访问的begin()
和end()
的唯一重载是返回std::string::const_iterator
而不是std::string::iterator
的const版本。
迭代器的约定是结束迭代器指向超出范围末尾的一个并且不可解除引用 - 当然如果您将str.end()
作为end
参数传递。这意味着*begin == *end
无效,您需要先减少结束。对于具有奇数个元素的范围,您也会遇到问题。通过执行++begin
和--end
而不进一步检查,迭代器可能会在递归中交叉,而不是触发begin == end
条件。
另请注意,为了获得最大的可移植性,全局标识符不应以下划线开头。
答案 2 :(得分:2)
如前所述,您的迭代器需要是常量迭代器,但您的算法还有其他问题。如果你有一个奇数长度的字符串,它可以正常工作,但你看到当你的字符串是偶数长度会发生什么?考虑回文:
AA
您的算法将传入指向前端和末尾的迭代器。一切都很好,然后它会进入下一个级别,一切都会很好,但它不会结束。因为你的第一个条件永远不会成真。您不仅要检查begin == end,还要检查begin + 1 == end或begin == end-1(如果您愿意)。否则你的迭代器会很难过。
答案 3 :(得分:1)
你得到什么错误?
你试过这个吗?
bool _isPalindrome(string :: const_iterator begin,string :: const_iterator end)
答案 4 :(得分:1)
iterator
替换为const_iterator
end
代码:
bool isPalindrome(string::const_iterator begin, string::const_iterator end)
{
return (begin == end || begin == --end ||
*begin == *end && isPalindrome(++begin, end));
}
bool isPalindrome(const string& str)
{
return isPalindrome(str.begin(), str.end());
}
答案 5 :(得分:0)
在第一个函数中调用它之前,你没有声明第二个函数。编译器找不到它,因此尝试将str.begin()(string :: iterator)转换为const字符串&amp ;.您可以移动第二个函数后面的第一个函数。