Is there any way to clean this up?

I had an assignment where we had to create a program that used a recursive function to test whether a string is a palindrome. We had to have a value-returning recursive function that returns true if the string is a palindrome and false otherwise and the recursive function "needs to take ONLY ONE parameter." I was wondering if there was any way I could clean this up or if you think this is good the way it is?

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
#include <iostream>
#include <fstream>
#include <string>

using namespace std;
bool palindrome (string str) //declare string 
{
    char first = str.front(); char last = str.back(); //declare first and last to coresponding functions

    if (first == last)
    {
        str.pop_back(); 
        str.erase(str.begin());  //get first and last char of string

        if (str.length() <= 1)
        {
            return true;  //if string length is less than or equal to 11 return as true
        }
        else
            return palindrome(str); //otherwise return string palindrome
    }
    else 
    {
        return false; //if string is not palindrome return false
    }
}

int main()
{
  string value;
  ifstream input("c:\\temp\\input.txt");
    while (!input.eof())
    {
        input >> value;
        if (palindrome(value))
            cout << "The value: " << value << " is palindrome" << endl;
        else
            cout << "The value: " << value << " is not palindrome" << endl;
    }
    input.close();
    return 0;
}
Last edited on
What if I call palindrome("")? Is that safe?
I wrote this program around the main that my professor is using (which is how he told us to do it) so I'm not sure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
using namespace std;

bool pal(string s)
{
    return s.size() < 2
           ? true
           : s.front() != s.back()
             ? false
             : pal(s.substr(1, s.size() - 2));
}

int main()
{
    string line;
    while (getline(cin, line))
    {
        cout << pal(line) << '\n';
    }
}

I know what you confuse. Discouraged use nest function like palindrome(string),you can ues iterator to ergodic string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool palindrome(string str) 
{
    auto first = str.begin();
    auto last = str.end() - 1;

    for (auto i = 0; i != str.length()/2; i++)
    {
        if (*(first + i) != *(last - i))
        {
            return false;
        }
    }
    return true;
}
Last edited on
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
#include <iostream>
#include <string>
#include <cctype>

// recursive function: str contains only lower case alphanumeric characters
static bool palindrome_helper( const std::string& str )
{
    if( str.size() < 2 ) return true ; // less than two chars: ergo palindrome

    // return true if a. first char == last char and b. the remaining middle substring is a palindrome
    else return str.front() == str.back() && palindrome_helper( { str.begin()+1, str.end()-1 } ) ;
}

bool palindrome( const std::string& str )
{
    std::string clean_str ; // a string containing alphanumeric characters in str converted to lower case
                            // (ie. ignore case, punctuation, and word boundaries in str)
    for( unsigned char c : str ) if( std::isalnum(c) ) clean_str += std::tolower(c) ;

    return palindrome_helper(clean_str) ; // str is a palindrome if and only if clean_str is a palindrome
}

int main()
{
    std::cout << std::boolalpha << palindrome( "A man, a plan, a canal -- PANAMA!!" ) << '\n'  ; // true
}

http://coliru.stacked-crooked.com/a/bd4ae92fe05cf837
LOL, your professor doesn’t know how to write code. That main is a mess on wheels.

    1 • Don’t loop on EOF.
          It doesn’t work like you think it does. 

    2 • Use pipes, my man. No need to open “input.txt” from some random C: drive directory!
          (Some of your students might not actually use Windows, and even if they do, they 
          might not have rights to that directory!) 

    3 • Don’t teach students to using namespace std;.
          It’s been nearly 20 years now of people saying “don’t do that”... 

Here’s how you open a file stream and use it:

1
2
3
4
5
6
7
8
9
10
int main()
{
  std::ifstream input( "input.txt" );  // assume file is in same directory as exe, tyvm.
  std::string s;
  while (input >> s)  // loop on success or failure of attempt to read data from file!
  {
    if (palindrome( s )) std::cout << "\"" << s << "\" is a palindrome.\n";
    else                 std::cout << "\"" << s << "\" is NOT a palindrome.\n";
  }
}

But, like I said, you should totally prefer to pipe input. This allow you to use files OR type things in by hand.

1
2
3
4
5
6
7
8
9
int main()
{
  std::string s;
  while (std::cin >> s)
  {
    if (palindrome( s )) std::cout << "\"" << s << "\" is a palindrome.\n";
    else                 std::cout << "\"" << s << "\" is NOT a palindrome.\n";
  }
}
C:\Users\Fonzie\prog\hw1> copy con input.txt
apple
madam
racecar
11/11/11
not a palindrome
aibohphobia anyone?
^Z

C:\Users\Fonzie\prog\hw1> pal.exe < input.txt
"apple" is NOT a palindrome.
"madam" is a palindrome.
"racecar" is a palindrome.
"11/11/11" is a palindrome.
"not" is NOT a palindrome.
"a" is a palindrome.
"palindrome" is NOT a palindrome.
"aibohphobia" is a palindrome.
"anyone?" is NOT a palindrome.

C:\Users\Fonzie\prog\hw1> pal.exe
deified
"deified" is a palindrome.
hannah montana
"hannah" is a palindrome.
"montana" is NOT a palindrome.
^Z

C:\Users\Fonzie\prog\hw1> _


Since he is only expecting you to matching over individual words, you can easily do a recursive function. You have the right idea: compare the first and last characters, then recurse on everything between. You can do it much more succinctly though. Also, don’t forget to watch out for letter case:

1
2
3
4
5
6
bool palindrome( std::string s )
{
  if (s.size() < 2) return true;
  if (std::tolower( s.front() ) != std::tolower( s.back() )) return false;
  return palindrome( s.substr( 1, s.size()-2 ) );
}


Normally in the real world, however, palindromes:

  • ignore everything except letters and digits, and
  • may consist of entire phrases.

You can improve things by updating main() to use getline() and fixing the palindrome function to ignore everything but alpha-numerics:

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
#include <cctype>
#include <ciso646>
#include <iostream>
#include <string>

bool palindrome( std::string s )
{
  // zero or one characters → yes
  if (s.size() < 2) return true;

  // both front and back must be alphanumeric  
  if (!std::isalnum( s.front() )) return palindrome( s.substr( 1 ) );
  if (!std::isalnum( s.back()  )) return palindrome( s.substr( 0, s.size()-1 ) );
  
  // if front != back → no
  if (std::toupper( s.front() ) != std::toupper( s.back() )) return false;
  
  // yes?
  return palindrome( s.substr( 1, s.size()-2 ) );
}

int main()
{
  std::string s;
  while (getline( std::cin, s ))
  {
    if (palindrome( s )) std::cout << "\"" << s << "\" is a palindrome.\n";
    else                 std::cout << "\"" << s << "\" is NOT a palindrome.\n";
  }
}
C:\Users\Fonzie\prog\hw1> pal.exe
Aibohphobia
"Aibohphobia" is a palindrome.
Taco cat
"Taco cat" is a palindrome.
A man, a plan, a canal, PANAMA!
"A man, a plan, a canal, PANAMA!" is a palindrome.
yep
"yep" is NOT a palindrome.
^Z

C:\Users\Fonzie\prog\hw1> _

Hope this helps.
Last edited on
Thank you all for your input I really appreciate it! @Duthomas thank you for the lesson/info!!
or using iterators:

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
#include <cctype>
#include <iostream>
#include <string>

using Fitr = std::string::const_iterator;
using Ritr = std::string::const_reverse_iterator;

bool palindrome(const Fitr b, const Ritr e) {
	if (e.base() - b < 2)
		return true;

	if (!std::isalnum(*b))
		return palindrome(b + 1, e);

	if (!std::isalnum(*e))
		return palindrome(b, e + 1);

	if (std::toupper(*b) != std::toupper(*e))
		return false;

	return palindrome(b + 1, e + 1);
}

int main() {
	std::string s;

	for (std::string s; getline(std::cin, s); )
		if (palindrome(s.cbegin(), s.crbegin()))
			std::cout << "\"" << s << "\" is a palindrome.\n";
		else
			std::cout << "\"" << s << "\" is NOT a palindrome.\n";
}

Topic archived. No new replies allowed.