Bool value not retuning false in palindrome function, C++ - c++

I've sadly read every post pertaining to this topic and can't seem to solve my issue. It's driving me mad.
For some reason on my second or third iteration, if (beg != end) won't return false. It returns false properly if I input, for instance, "bool", but not "blob."
I printed beg and end to make sure things are flowing properly, but still can't find where things are going wrong.
Thank you!!!
#include <iostream>
#include <string>
using namespace std;
bool palindrome_check (string str)
{
string return_str;
int length = str.length()-1;
string beg = str.substr(0, 1);
string end = str.substr(length, 1);
if (beg != end)
{
// cout << beg << " " << end << endl;
return false;
}
else if ((str.length() > 2) && (str.length() != 0))
{
string new_str = str.substr(1, length - 1);
// cout << new_str << endl;
palindrome_check(new_str);
}
return true;
}
int main ()
{
string input;
cout << "Enter a string: ";
cin >> input;
bool is_palindrome = palindrome_check (input);
cout << is_palindrome << endl;
}

You should have used the return values of recursive calls:
string new_str = str.substr(1, length - 1);
return palindrome_check(new_str);
}
return true;
And you should have checked the length of the input string before you extract the first and the last character from it.
If you fix the two mistakes, it should be alright then.

Related

(1) Why does it not recognize this is a palindrome & (2) how do I have it print the original input WITH the spaces?

I've searched all over to try to answer my own questions, but I'm hitting a wall here. I've been working on this same exercise for three days and getting frustrated, hence my very first post! This is a school assignment, but I really want to understand why this isn't working. When I use input "bob" it returns "bob is a palindrome" as expected. When I input "bobby" it returns "bobby is not a palindrome" as expected. All good there. It took me forever to figure out how to remove spaces from my input when using the sentence "never odd or even" but I managed to do that successfully, too. But here's the rub: (1) even after the spaces are removed, it seems to think that "neveroddoreven" is NOT a palindrome - why? What am I missing? Additionally, and this is probably a stupid question (but this is my first foray into programming and I'm a total newbie), how do I get it to output the original userInput before I removed the spaces in the final output? Currently the below code outputs "neveroddoreven is not a palindrome". Thanks in advance for any pointers you can give me.
#include <string>
#include <cctype>
using namespace std;
int main() {
string userInput;
int startInput;
bool isPalindrome = true;
getline (cin, userInput);
startInput = userInput.length();
for(int i = 0; i<userInput.length(); i++)
if(userInput[i] == ' ') userInput.erase(i,1);
for (int i = 0; i<(startInput / 2); i++){
if (userInput[i] != userInput[(startInput -1 ) -i])
isPalindrome = false;
}
if (isPalindrome){
cout << userInput << " is a palindrome" << endl;
}
else {
cout << userInput << " is not a palindrome" << endl;
}
return 0;
}
After you erase all the spaces, startInput no longer refers to the actual length of the string. That means this comparison:
if (userInput[i] != userInput[(startInput -1 ) -i])
is not comparing the correct characters.
You can fix this by adding this line:
startInput = userInput.length();
after doing the erasing.
Here's a demo.
Also, in your erase code, this comparison i<userInput.length() is not a good idea, since you are comparing a signed and unsigned value. Also, you don't erase adjacent spaces. A simpler way to do that would be:
userInput.erase(std::remove(std::begin(userInput), std::end(userInput), ' '),
std::end(userInput));
As others have pointed out, the problem is that startInput doesn't take into account that you erase some spaces. So move the the line startInput = userInput.length(); so that it is just after the erase-loop.
An alternative solution that will not change the original input could be:
#include <iostream>
#include <string>
int main()
{
std::string userInput;
std::string userInputNoSpace; // Use one more string
int startInput;
bool isPalindrome = true;
std::getline(std::cin, userInput);
// Copy all characters that are NOT space to the new string
for (auto c : userInput)
{
if (c != ' ')
{
userInputNoSpace += c;
}
}
startInput = userInputNoSpace.length();
for (int i = 0; i<(startInput / 2); i++)
{
if (userInputNoSpace[i] != userInputNoSpace[(startInput -1 ) -i])
{
isPalindrome = false;
break;
}
}
if (isPalindrome)
{
std::cout << userInput << " is a palindrome" << std::endl;
}
else
{
std::cout << userInput << " is not a palindrome" << std::endl;
}
return 0;
}
Input:
never odd or even
Output:
never odd or even is a palindrome

Program Won't Continue to Run When Testing for Palindromes (C++)

I'm a beginner in coding with C++. I'm trying to make a program that completes a specific set of tasks:
opens a data file,
takes each line of the file,
processes each line by removing all whitespace and punctuation,
converts the string into all lowercase,
uses a recursive method to test if the string is a palindrome,
finds a position within the string where characters can be added to make it a palindrome if it isn't already,
then adds the characters needed to make it a palindrome in the position specified in (6).
I'm only allowed to use 4 user-defined functions with specific parameters. So far I've got about 80% of the program to work, but there's an error when it detects a non-palindrome. I'm hoping someone can find out why. Here's my code:
// Read file data, check for palindromes, and process strings to palindromes.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
string process(string);
bool is_palindrome(string);
int palindrome_fix_location(string);
string palindrome_addition(string, int);
int main()
{
ifstream inFile;
inFile.open("data");
string preString;
int palinLoc = 0;
while(getline(inFile, preString))
{
cout << "\nOriginal line: " << preString << endl;
cout << "Processed line: " << process(preString) << endl;
if (is_palindrome(preString) == true)
cout << "Line is palindrome." << endl;
else
cout << "Line is NOT a palindrome." << endl;
palindrome_fix_location(preString);
palindrome_addition(preString, palinLoc);
}
inFile.close();
return 0;
}
// Return a string that is lowercase with no punctuation or spacing.
string process(string preString)
{
string procString;
for (size_t i = 0; i < preString.length(); i++)
{
if (isalnum(preString[i]))
procString += tolower(preString[i]);
}
return procString;
}
// Uses a recursive method to determine if the processed string is a palindrome.
bool is_palindrome(string procString)
{
string temp = process(procString);
int length = temp.length();
string firstChar = temp.substr(0, 1);
string lastChar = temp.substr((length - 1), 1);
if (firstChar == lastChar)
{
temp = temp.substr((0 + 1), (length - 2));
if (temp.length() <= 1) // Base case.
return true;
return is_palindrome(temp); // Recursion.
}
else
return false;
}
// Return a location where text can be added to the non-palindrome to make it a palindrome.
int palindrome_fix_location(string procString)
{
string temp = process(procString);
if (is_palindrome(temp) == false)
{
int palinLoc;
int firstChar = 0, lastChar = temp.length() - 1;
while (firstChar < lastChar)
{
if (temp[firstChar] != temp[lastChar])
{
palinLoc = firstChar;
cout << "Characters to insert at location "
<< palinLoc << " are ";
return palinLoc;
}
}
}
return 0;
}
// Return the text that needs to be added at the "palinLoc" location.
string palindrome_addition(string procString, int palinLoc)
{
string temp = process(procString);
string addedChars;
string finalString;
if (is_palindrome(temp) == false)
{
int firstChar = 0, lastChar = temp.length() - 1;
while (firstChar < lastChar)
{
do {
addedChars += temp[lastChar];
} while (temp[firstChar] != temp[lastChar]);
firstChar++;
lastChar--;
}
finalString = temp.insert(palinLoc, addedChars);
cout << addedChars << endl;
cout << "Final word: " << finalString << endl;
return finalString;
}
else
return finalString;
}
And here's the output I get:
Original line: lappal
Processed line: lappal
Line is palindrome.
-
Original line: lapal
Processed line: lapal
Line is palindrome.
-
Original line: A man, a plan, a canal, Panama!
Processed line: amanaplanacanalpanama
Line is palindrome.
-
Original line: lap
Processed line: lap
Line is NOT a palindrome.
Right there when it says "Line is NOT a palindrome," it's supposed to follow up with something that looks like this:
Characters to insert at location 0 are pa
Final line: palap
It just stops at "Line is NOT a palindrome." Can anyone see where I went wrong with this?
Any help would be greatly appreciated.
your loop here (in palindrome addition) is bugged
do {
addedChars += temp[lastChar];
} while (temp[firstChar] != temp[lastChar]);
it never ends
so you should move either lastchar or firstchar change inside, like this for example
while (firstChar < lastChar)
{
do {
addedChars += temp[lastChar];
lastChar--;
} while (temp[firstChar] != temp[lastChar])
firstChar++;
}
some run here
Original line: lap
Processed line: lap
Line is NOT a palindrome.
start palindrom fix
Characters to insert at location 0 are
start palidrome addition
pa
Final word: palap
Original line: lapin
Processed line: lapin
Line is NOT a palindrome.
start palindrom fix
Characters to insert at location 0 are
start palidrome addition
nipa
Final word: nipalapin
Original line: lapal
Processed line: lapal
Line is palindrome.

Reversing char array

When I print out text2 I see that it is definitely not the reverse of the string I gave it and I'm not sure why that is. When I put in "test" I get stuff like "ȍ\2200+". Can I use strncpy on char arrays? Maybe it needs to be done with a loop - not sure. Any help would be appreciated. :)
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char text[79], text2[79];
bool input = true;
while (input) {
cout << "Please give me a line of text to examine: ";
cin.getline(text, 79);
for(int i = 0; i < strlen(text); i++ )
cout << text[i];
// test to see if it is a palindrome
strncpy(text, text2, 80);
reverse(text2, text2 + strlen(text2));
printf("%s", text2); `// when I print this out I get something odd`
if (strcmp(text, text2) == 0)
cout << " is a palindrome!" << endl;
else
cout << " is not a palindrome." << endl;
if (strcmp(text, "END") == 0)
input = false;
else
cout << "\ntype END to exit the program" << endl;
} // end while loop
} // end main
It seems you're using strncpy in a wrong way: you probably want to copy text into text2, not the other way around.
There's a much simpler way to test whether a string is a palindrome, namely:
bool is_palindrome(const char* s, size_t n) {
size_t i, j;
i = 0, j = n-1;
while (i < j && s[i++] == s[j--])
;
return i >= j;
}
Why not use std::vector<char> and std::reverse from <algorithm> to handle your problem?
I would do something like below: (note that I'm using C++11 range-based for loop and auto which you can change to a regular for loop and use std::string line if you don't have a compiler supporting this).
int main()
{
cout << "Please give me a line of text to examine: ";
auto line = ""s;
getline(cin, line);
// Push back every character to the vector
vector<char> vtext;
for (const auto &elem : line)
vtext.push_back(elem);
// Create a copy of the vector<char> and reverse the copy
vector<char> vtext_reversed{vtext};
reverse(begin(vtext_reversed), end(vtext_reversed));
// Print the line reversed
cout << "\nThis is the line reversed: ";
for (const auto &elem : vtext_reversed)
cout << elem;
}
Typically you'll see this reversal technique for char*:
void reverse(char* s) {
if(!s) return;
size_t n = strlen(s);
for(size_t i = 0; i < n/2; ++i) {
char tmp = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = tmp;
}
}
This will not work, however, with non-ASCII characters. The reason is that non-ASCII characters require multiple bytes to represent.
You will need to use wide characters to handle multi-byte codepoints, but the logic should follow above.

process is terminated due to StackOverflowException from bool function C++

I am trying to make a bool function that will allow an input of a string and the input of a substring to be searched in that string's input. The bool function should search recursively for a match, then return true if there is a match inside of the string. For example: 'word' is entered as the string, then 'or' is the substring I am looking for inside the string. The function should then return true since 'or' is inside 'word'. When I run the code, on the command line it will say, "process is terminated due to StackOverFlowException" I am confused as to what this error means and how it relates to my code.
#include <iostream>
#include <string>
using namespace std;
bool find(string s, string t)
{
if(s.length() <= 1){
return false;
}
int t_len = t.length() - 1;
string se = s.substr(0, t_len);
if(se == t){
return true;
}
else
s.erase(0,0);
return find(s, t);
}
int main()
{
string s;
string t;
cout << "Enter string s: " << endl;
cin >> s;
cout << "Enter string t: " << endl;
cin >> t;
bool is_found = find(s, t);
if(is_found = true)
{
cout << "Found: " << t << " in " << s << endl;
}
system("pause");
return 0;
}
Your call to erase is not deleting any characters. The definition of erase is:
erase( size_type index = 0, size_type count = npos );
So you want to erase 1 character, not 0 characters.
Additionally, your test at the end should read:
if(is_found == true)
as otherwise, you're trying to assign is_found the value true and test that value (which will always be true in that case.
Additionally, you have:
string se = s.substr(0, t_len);
where t_len is incorrect (off by one), so the string comparison will not work.
Fundamentally, it looks like you've not understood the definitions of erase or substr, which would be essential to getting this to work properly.

Palindrome program isn't comparing properly

I'm currently learning about vectors and trying to make a palindrome program using them. This is a simple program and so far, I'm trying to make it identify "I am what am I." as a palindrome properly. This is my program so far:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
vector <string> sentVec;
void getSent(string sent);
void readBackwards(string sent);
int main()
{
string sent;
getSent(sent);
readBackwards(sent);
return 0;
}
void getSent(string sent)
{
cout << "Enter your sentence:" << endl;
getline (cin,sent);
string currentWord, currentLetter;
for (int i = 0; i < sent.length(); i++)
{
currentLetter = sent[i];
if (currentLetter == " ") // inserts word
{
currentWord += sent[i];
sentVec.push_back(currentWord);
currentWord = "";
}
else if (currentLetter == ".") // inserts period
{
sentVec.push_back(currentWord);
currentWord = sent[i];
sentVec.push_back(currentWord);
}
else
{
currentWord += sent[i];
}
}
}
void readBackwards(string sent)
{
string sentForwards, sentBackwards;
// create sentence forwards and backwards without the period.
for (int i = 0; i < sentVec.size() - 1; i++)
{
sentForwards += sentVec[i];
}
for (int j = sentVec.size() - 2; j >= 0; j--)
{
sentBackwards += sentVec[j];
if (j == sentVec.size() - 2)
{
sentBackwards += " ";
}
}
cout << "Sentence forwards is: " << sentForwards << endl;
cout << "Sentence backwards is: " << sentBackwards << endl;
if (sentForwards == sentBackwards)
{
cout << "This sentence reads the same backwards as forwards." << endl;
}
else
{
cout << "This sentence does not read the same backwards as forwards." << endl;
}
}
When I run this program, it prints:
Enter your sentence:
I am what am I.
Sentence forwards is: I am what am I
Sentence backwards is: I am what am I
This sentence does not read the same backwards as forwards.
Why does this not trigger the if loop when comparing the two sentences?
Because sentBackwards isn't the same as sentForwards, because sentBackwards has a trailing whitespace at the end, and thus they aren't the same.
I am unsure how your program detects palindromes, but here is a simple iterative method:
#include <string>
bool isPalindrome(std::string in) {
for (int i = 0; i < in.size() / 2; i++) {
if (in[i] != in[in.size() - 1 - i]) {
return false;
}
}
return true;
}
It returns true if the string passed as an argument is a palindrome
You should not only learn about vector, but also the STL algorithm functions such as std::reverse.
As the other answer given pointed out, one vector has a trailing whitespace. You could have avoided all of that by simply taking the original vector, copying it to another vector, and calling std::reverse. There is no need to write a loop:
void readBackwards()
{
// copy the vector
std::vector<std::string> sentBackwards = sentVec;
// reverse it
std::reverse(sentBackwards.begin(), sentBackwards.end());
// see if they're equal
if (sentVec == sentBackwards)
cout << "This sentence reads the same backwards as forwards." << endl;
else
cout << "This sentence does not read the same backwards as forwards." << endl;
}
This works, since std::vector has an overloaded operator == that compares the items in each of the two vectors and returns true if all items are the same.
In addition to this, reading into a vector can be accomplished much more easily than what you attempted.
#include <sstream>
#include <algorithm>
//...
void getSent(string sent)
{
// remove the periods(s)
auto iter = std::remove_if(sent.begin(), sent.end(), [] (char ch) { return ch == '.';});
sent.erase(iter, sent.end());
// copy the data to a vector
std::istringstream iss(sent);
string currentword;
while ( iss >> currentword)
sentVec.push_back(currentword);
}
Note that we use the std::istringstream to serve as the space delimited parser, alleviating the need to write a loop looking for the space. Also, the std::remove_if algorithm is used to remove any period characters from the string before we start to store the individual strings into a vector.
So basically, the only loop in this whole setup is the while to read from the stream into the vector. Everything else is accomplished by using the algorithm functions, and taking advantage of the various member functions of std::vector (like the overloaded ==)