Problems with palindrome...still

I have posted thins one once before, but It seems I am not able to resolve a couple of problems with my program.

1. Palindrome option is not working in the sense that:
when user enter option 2 (find if it is palindrome)
user enter: Madam
result is: This is not a palindrome

2. when user chooses option 2 three times in row:
input:2
in put: Madam
output: is not a palindrome
do you want to try again?
input: yes
The program goes into an infinite loop of the following:
Enter a word or sentence I will check if it is a palindrome:
input:2
input: Madam
output: is not a palindrome
do you want to try again?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  #include<iostream>
#include<string>
#include<ctype.h>
#include<stdio.h>
using namespace std;

//prototype of functions
bool is_palindrome(string&, int, int);
string Reverse(string, string);
string remove_char(string);

int main()
{

//variable declarations
string userInput;
string sentence2;
int first = 0;
size_t last = string::npos;
int userchoice;
string reversed,r;
locale loc;
string answer;

//Loop to keep program running until user quits
do
{
//Reverse function
cout<< "Do you want to reverse a string (1), determine if it is a palindrome(2) or quit:" << endl;
cin >> userchoice;
cout<< userchoice<< endl;
cin.ignore(80,'\n');


if (userchoice ==1)
{
cout<< " Please enter a word or sentence, I will reverse it:" <<endl;
getline(cin, userInput);


cout<< Reverse(userInput, reversed) << " is reversed." << endl;
}

//palindrome function
if (userchoice ==2)
{
cout<< " Please enter a word or sentence, I will determine if it is a palindrome or not:" <<endl;
cin>>userInput;


// the upper to lowercase
string str= userInput;
for (size_t i=0; i<str.length(); ++i)
     str[i] = tolower(str[i]);

sentence2 = remove_char(str);

cout<< (is_palindrome(sentence2, first, last) ? " is a palindrome." : " is not a palindrome.") << endl;
cin.get();
}
cout<< "Do you want to try again ('yes' or 'no'): " << endl;
cin>> answer;

}while (answer == "yes");
return 0;
}


//Functions

// remove non letters
string remove_char(string userInput)
{
        string sentence2;

        for (unsigned int x=0; x < userInput.length(); x++)
        {
                if (isalnum(userInput[x]))
                {
                        sentence2 += userInput[x];

                }
        }
        return sentence2;
}


// return true if palindrome
bool is_palindrome(string& sentence2, int first = 0, int last = string::npos)
{
if(last == string::npos)
{
last = (sentence2.length()-1);
}
if (sentence2[first] == sentence2[last])
{
if ((first-last)== 0)
{
return true;
}
else if (first ==(last-1))
{
return true;
}
else
{
return is_palindrome(sentence2, first+1, last-1);
}
}
else
{
return false;
}
}


// reverse string
string Reverse(string word, string reversed)
{
if(word.length() == 0)
{
return reversed;
}
else
{
string temp;
reversed = word.substr(0,1) + reversed;
temp = word.substr(1);
return Reverse(temp, reversed);
}
}


**sorry the indentation didn't transfer over properly
Last edited on
Does "madam" return true even if "Madam" does not?

I admit that I was hesitant to answer this one as chains of if-elseif-else statements make me nauseous. This type of programming is very prone to typos or un-considered cases which will really kill you. If possible, it's best to use a single statement that will do the work for you.

Your is_palindrome() function will be so easy if it uses the Reverse() function:
1
2
3
4
5
6
7
8
9
10
11
12
std::string Reverse(std::string str)
{
    if (str.size() == 0)  return str;

    // Return the last letter   + reverse( string without last letter )
    return str.at(str.size()-1) + Reverse( str.substr(0, str.size()-1) );
}

bool is_palindrome(const std::string str)
{
    return str == Reverse(str);
}


Hold on while I try to simplify your main, and make this case insensitive
Here's what I managed to get for you. I re-implemented toupper() from <cctype> because I was having troubles with the const-correctness. Otherwise, I kept each function with as small of a scope as possible. And I used Reverse() in the is_palidrome() function.

I've checked palindrome sentences such as "rise to vote sir" and "loin oil" and this all checked out ok.

I tried to keep with your recursive theme, but strayed from this in the "RemoveSpaces" function which was added to support sentences. For your problems with infinite loops, these I think were caused by using cin >> instead of getline. Honestly, I don't use cin in any of my applications, but the >> operator assumes that you know exactly what is coming in which can mess up when you press enter or spacebar.

I also kept your variables in as small a scope as possible. I suppose that's a matter of personal preference. In C, we had to declare everything at the start, but in C++ it can be done in a smaller scope. Some people are used to declaring it at the start, but I HATE scrolling up to figure out how something what declared. I also find that people add variables, forget about them, then eventually remove the usage without removing the variable. Lots of garbage ends up at the top of each function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <string>
#include <cstdlib>
#include <iostream>
using namespace std;

char toupper(char c)
{
    if(c >= 'a' && c <= 'z')   c += ('A' - 'a');
    return c;
}

string ToUpper(string str)
{
    if (str.size() == 0) return str;
    return toupper(str.at(0)) + ToUpper( str.substr(1, str.size()-1) );
}

string RemoveSpaces(string str)
{
    string::iterator it = str.begin();

    while (it != str.end())
    {
        if (*it == ' ' || *it == '\t' || *it == '\n' || *it == '\r')
            it = str.erase(it);
        else
            ++it;
    }
    return str;
}

string Reverse(string str)
{
    if (str.size() == 0)  return str;
    return str.at(str.size()-1) + Reverse( str.substr(0, str.size()-1) );
}

bool is_palindrome(string str)
{
    str = ToUpper(str); // Case insensitive
    str = RemoveSpaces(str); // removes whitespace for the sentences
    return str == Reverse(str);
}

int main()
{
    string again;
    do
    {
        string input;

        cout<< "Do you want to reverse a string (1), determine if it is a palindrome(2) or quit:" << endl;
        getline(cin,input);
        int choice = atoi(input.c_str());

        if (choice ==1)
        {
            cout<< " Please enter a word or sentence, I will reverse it:" <<endl;
            getline(cin, input);

            cout<< "The reverse of " << input << " is " << Reverse(input) << endl;
        }
        else if (choice ==2)
        {
            cout<< " Please enter a word or sentence, I will determine if it is a palindrome or not:" <<endl;
            getline(cin, input);

            cout<< input << (is_palindrome(input) ? " is" : " is not") << " a palindrome." << endl;
        }

        cout<< "Do you want to try again ('yes' or 'no'): " << endl;
        getline(cin, again);

    }while (again[0] == 'y' || again[0] == 'Y');
    return 0;
}
Last edited on
Thanks so much for you help on this one. I really appreciate it.
Topic archived. No new replies allowed.