我编写了一个递归回文函数,在第一个代码中只接收一个单词,在第二个代码中接收一个句子。但是出乎意料的是,第二个代码给了我“超出范围”的错误。
在两个代码中都使用了此功能(正常工作):
bool palindrome( string str, int first, int last )
{
if( first == str.size() - 1 ) //if string is a single alphabet.
return true;
if( str[ first ] == str[ last ] )
return palindrome( str.substr( first + 1, last - 1 ), first, last - 2 );
}
在第一个代码中,即使我输入了很长的字符串,它也可以按预期工作:
int main()
{
string str = "madamhelloollehmadam";
palindrome( str, 0, str.size() - 1 ) ? cout << "palindrome!" << '\n' : cout << "not palindrome." << '\n';
}
在第二个代码中,我需要将输入的句子转换为一个单词,还将所有字符都转换为小写(我在其他函数中都做了这些)。我确实在第二个代码中输入了相同的字符串,但在页面底部仍然出现错误:
int main()
{
string str = "madam hello olleh madam"; //this becomes "madamhelloollehmadam" after going to "normalString" function.
palindrome( normalString(str), 0, normalString(str).size() - 1 ) ? cout << "palindrome!" << '\n' : cout << "not palindrome." << '\n';
}
这是我得到的错误(对于第一个得到单词而不是句子的代码,我不会得到此错误,但是两个“回文”功能都相同。我猜“ normalString”功能出了点问题,但我无法无法检测到任何尺寸差异...)
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
Aborted
这也是normalString函数:
string normalString( string str )
{
vector<string> vec;
for( int i = 0; i < str.size(); ++i )
vec.push_back( charToString(str[ i ]) );
for( int i = 0; i < vec.size(); ++i )
{
if( !isAlpha( vec[ i ] ) )
vec[ i ].erase();
if( isupper( stringToChar(vec[ i ]) ) )
vec[ i ] = charToString( tolower( stringToChar( vec[ i ] ) ) );
}
string str2 = vectorToString( vec );
return str2;
}
这是我的第二段代码:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <locale>
using namespace std;
bool palindrome( string, int, int );
bool isAlpha( string );
string charToString( char );
string normalString( string );
char stringToChar( string );
string vectorToString( vector<string> );
int main()
{
cout << "Enter a word or a sentence: ";
string str;
while( cin >> str )
{
palindrome( normalString(str), 0, normalString(str).size() - 1 ) ? cout << str << " is palindrome!" << " (" << normalString(str) << ") "
<< '\n' : cout << str << " is not palindrome!" << " (" << normalString(str) << ") " << '\n';
cout << "Enter a word or a sentence: ";
}
return 0;
}
string vectorToString( vector<string> vec )
{
stringstream ss;
for( int i = 0; i < vec.size(); ++i )
ss << vec[ i ];
string str;
ss >> str;
return str;
}
string charToString( char c )
{
stringstream ss;
string s;
ss << c;
ss >> s;
return s;
}
char stringToChar( string str )
{
stringstream ss;
ss << str;
char c;
ss >> c;
return c;
}
bool isAlpha( string s )
{
return s == "a" || s == "b" || s == "c" || s == "d" || s == "e" || s == "f" || s == "g" || s == "h" || s == "i" || s == "j" || s == "k" || s == "l"||
s == "m" || s == "n" || s == "o" || s == "p" || s == "q" || s == "r" || s == "s" || s == "t" || s == "u" || s == "v" || s == "w" || s == "x"||
s == "y" || s == "z" ||
s == "A" || s == "B" || s == "C" || s == "D" || s == "E" || s == "F" || s == "G" || s == "H" || s == "I" || s == "J" || s == "K" || s == "L"||
s == "M" || s == "N" || s == "O" || s == "P" || s == "Q" || s == "R" || s == "S" || s == "T" || s == "U" || s == "V" || s == "W" || s == "X"||
s == "Y" || s == "Z" ;
}
string normalString( string str )
{
vector<string> vec;
for( int i = 0; i < str.size(); ++i )
vec.push_back( charToString(str[ i ]) );
for( int i = 0; i < vec.size(); ++i )
{
if( !isAlpha( vec[ i ] ) )
vec[ i ].erase();
if( isupper( stringToChar(vec[ i ]) ) )
vec[ i ] = charToString( tolower( stringToChar( vec[ i ] ) ) );
}
string str2 = vectorToString( vec );
return str2;
}
bool palindrome( string str, int first, int last )
{
if( first == str.size() - 1 ) //if string is a single alphabet.
return true;
if( str[ first ] == str[ last ] )
return palindrome( str.substr( first + 1, last - 1 ), first, last - 2 );
}
最佳答案
这段代码有很多问题。
回文功能
首先,让我们稍微重写一下签名。由于palindrome
不需要字符串的副本,因此我们传入const引用。索引也应更改为std::size_t
,因为这是用于索引字符串的类型。
bool palindrome(const std::string &str, std::size_t first, std::size_t last) {
接下来,我们需要处理字符串只有一个字符的情况…,但是处理字符串只有零个字符的情况也很重要。这是原始代码:
// if (first == str.size() - 1) // Wrong!
首先,这并没有按照它说的做。我们正在处理的字符串的长度应该是从
first
到last
,而不是从first
到size() - 1
(否则为什么last
甚至存在?)第二,这是行不通的如果size()
为0。它将溢出!这是更正的代码。 // Empty string, or only one character
std::size_t length = last - first;
if (length <= 1)
return true;
接下来,我们比较第一个和最后一个字符。但是最后一个字符实际上不是
str[last]
,而是str[last-1]
。 if (str[first] == str[last - 1])
因为我们有方便的
first
和last
参数,所以我们使用它们代替调用substr
: return palindrome(str, first + 1, last - 1);
但是,我们必须记住如果条件失败,则要返回...
return false;
}
normalString函数
事实证明,
std::string
具有push_back
,因此您不需要向量,并且可以将isAlpha
更改为在char
而不是string
上进行操作,这使其更加简单。bool isAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
std::string normalString(std::string str) {
std::string result;
for (char c : str) {
if (isAlpha(c))
result.push_back(std::tolower(c));
}
return result;
}
完整代码
也已删除
using namespace std;
#include <iostream>
#include <string>
#include <vector>
#include <locale>
bool palindrome(const std::string &, std::size_t, std::size_t);
std::string normalString(std::string);
int main() {
while (true) {
std::cout << "Enter a word or a sentence: ";
std::string str;
if (!(std::cin >> str))
break;
str = normalString(str);
if (palindrome(str, 0, str.size())) {
std::cout << str << " is palindrome!"
<< " (" << str << ")\n";
} else {
std::cout << str << " is not palindrome!"
<< " (" << normalString(str) << ") \n";
}
}
return 0;
}
bool isAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
std::string normalString(std::string str) {
std::string result;
for (char c : str) {
if (isAlpha(c))
result.push_back(std::tolower(c));
}
return result;
}
bool palindrome(const std::string &str, std::size_t first, std::size_t last) {
// Empty string, or only one character
std::size_t length = last - first;
if (length <= 1)
return true;
if (str[first] == str[last - 1])
return palindrome(str, first + 1, last - 1);
return false;
}