我有一个文本文件
,其中包含:1457887541
Madam
Able was I ere I saw Elba
Straw? No, too stupid a fad. I put soot on warts.
Class is cancelled today
当我运行该程序时,我得到所有字符串返回false
并且无法弄清楚为什么会这样。
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cctype>
using namespace std;
bool isPalindrome(string);
int main()
{
string input;
fstream nameFile;
nameFile.open("Xample.txt", ios::in);
if (nameFile)
{
cout << "Now reading from file: " << endl;
// Read an item from the file.
getline(nameFile, input);
// While the last read operation
// was successful, continue.
while (nameFile)
{
cout << input << endl;
//Palindrome function call
if(isPalindrome(input)){
cout << "It is a Palindrome :)/> " << endl;
}
else {
cout << "It is not a Palindrome :'( " << endl;
}
// Read the next string.
getline(nameFile, input);
}
//Close when completed
cout << "Done!" << endl;
nameFile.close();
}
else
{
cout << "ERROR: Cannot open file.n";
}
return 0;
}
bool isPalindrome(string input){
int first = 0;
int last = input.length() - 1;
//begin loop to compare first position with last
while(last > first){
//loop if it is not a number or letter
while(!isalnum(input[first]) && !isalnum(input[last])){
first++;
last--;
}
if(tolower(input[first]) != tolower(input[last])){
return false;
}
last--;
first++;
}
return true;
}
如果不运行/调试您的代码,我认为问题出在您的算法上。代码的这一部分看起来像是为了解决空格和标点符号的问题而设计的。
//loop if it is not a number or letter
while(!isalnum(input[first]) && !isalnum(input[last])){
first++;
last--;
}
不过这行不通。如果当前的第一个和最后一个字符都不是 alphanum 字符,则跳过它们,但大多数时候你应该只跳过一个或另一个,所以你应该把它分成两个 if 语句而不是一个循环。
我只是尝试编辑您的代码并运行它,因为比尔说问题出在您的逻辑上。
while(!isalnum(input[first]) && !isalnum(input[last])){
first++;
last--;
}
如果input[first]不是字母数字,则应仅递增它,最后同时递减。
这是函数的更正版本,看看它会更 clearn
bool isPalindrome(string input){
int first = 0;
int last = input.length() - 1;
while(last > first)
{
if(!isalnum(input[first]))
first++; //Increment only first
else if(!isalnum(input[last]))
last--; //Decrement only last
else if(tolower(input[first]) != tolower(input[last])){
return false;
}
else
{
last--;
first++;
}
}
return true;
}
答案显然是"因为你的代码没有做你的想法或想要的"(并不是说这本身很有帮助)。
除非你真的需要检查"到位"的数据,否则几乎可以肯定的是,复制你关心的数据更容易,更容易理解,然后检查结果是否是回文:
bool is_palindrome(std::string const &input) {
std::string temp;
std::copy_if(input.begin(), input.end(), std::back_inserter(temp), isalnum);
return temp == std::string(temp.rbegin(), temp.rend());
}
如果就地完成工作很重要,我仍然会尝试在逻辑上将"跳过我们不关心的字符"部分与"检查结果是否是回文"部分分开。一种方法是将过滤构建到一个特殊的迭代器中。例如,将过滤封装到 Boost filter_iterator
中仍然可以使代码相对简单易懂。