Why does the removal of this return statement affect the outcome of the entire recursive function? - c++

I am writing a palindrome checker using recursion.
I am confused to why removing the
return true
Statement at the end of the function affects the return value.
int firstChar = 0;
int lastChar = 0;
// These two variables are used to transverse the string from both ends
// eventually meeting
Code #1:
bool palindromeCheck (string text, int firstChar, int lastChar)
{
string tempCleanText = text;
// Removes all punctation and space
if (firstChar == 0)
{
// Cleans text, ignore.
tempCleanText = cleanString(tempCleanText);
// Sets this variable to the end of the string
lastChar = tempCleanText.size() - 1;
}
// Base Case
if (firstChar >= lastChar)
{
return true;
}
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
return true; // Keeping this in works
}
This returns true, as it should for all palindromes, and false for all non-palindromes.
Code #2:
bool palindromeCheck (string text, int firstChar, int lastChar)
{
string tempCleanText = text;
// Removes all punctation and space.
if (firstChar == 0)
{
// Cleans text, ignore.
tempCleanText = cleanString(tempCleanText);
// Sets this variable to the end of the string
lastChar = tempCleanText.size() - 1;
}
// Base Case
if (firstChar >= lastChar)
{
return true;
}
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
// there is no return true here, and so the output is no longer correct
}
This returns true, for only some of the palindromes, and false for all non-palindromes.
Palindromes, such as,
amanaplanacanalpanama <- size length 21
Returns false, when it should return true.
Through testing, it is shown that the base case is entered using the last palindrome, meaning that the function sees it as a valid palindrome. But, I'm assuming the program then unwinds the call stack and as it goes through all the previous function calls, something makes the function return false.

For starters the function is in any case incorrect. For example for the string "1231" the function returns true. I hope you can check this yourself.
This part of the function
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
return true; // Keeping this in works
should be at least substituted for the following code snippet
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
return palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
That is this return statement
return true; // Keeping this in works
shall be entirely removed.
As for your question then without the last return statement the function have undefined behavior because it returns nothing after the if statement. That is the if statement
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
successfully was executed provided that
tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
and what does the function return after executing the sub-statement of the if statement? Nothing! :)
Also it does not make sense to declare two additional parameters (indices) apart from the string itself because in any case the string is passed by value and you always can get its size by calling the member function size().
I can suggest the following implementation of the function Similarly to your function this function implementation returns true in case when an empty string is passed.
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
bool palindromeCheck( std::string s )
{
if ( s.size() < 2 )
{
return true;
}
else if ( ispunct( ( unsigned char )s.front() ) || isspace( ( unsigned char )s.front() ) )
{
return palindromeCheck( s.substr( 1 ) );
}
else if ( ispunct( ( unsigned char )s.back() ) || isspace( ( unsigned char )s.back() ) )
{
return palindromeCheck( s.substr( 0, s.size() - 1 ) );
}
else if ( s.front() == s.back() )
{
return s.size() == 2 ? true : palindromeCheck( s.substr( 1, s.size() - 2) );
}
else
{
return false;
}
}
int main()
{
std::cout << std::boolalpha << palindromeCheck( "" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1 1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1,2,2,1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1 2 3 2 1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "12341" ) << '\n';
return 0;
}
The program output is
true
true
true
true
true
false

may be
// ...
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
return palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
return false;
// ...

Returning from a non-void function without explicitly returning a value via the return keyword invokes undefined behavior. Per the C++ spec, a program that invokes undefined behavior is free to do literally anything at all, and all blame for any resulting weirdness will be placed at the feet of the programmer that wrote the code that invoked the undefined behavior.
What's likely actually happening in this case is that when your function returns by dropping off the end of the function (and doesn't do a return false), the location where the function's return-value was stored simply never gets written to -- which means that, as far as the calling code is concerned, the value returned by your function will be equal to whatever value happened to be present at that location when your function returns. The pre-existing value at that location will be arbitrary and hard-to-predict, since it is a result of various details regarding how the program executes, and therefore the behavior of the program will be arbitrary and hard-to-predict as well.
The solution is to be sure to always explicitly return a value; enabling warnings in your compiler will allow it to help you in that task by warning you if you ever forget to return a value in some code-path.

Related

C++ “add explicit braces to avoid dangling else”

bool isPalindromeIterative(const char *s1){
int len=strlen(s1)-1;
if(len>0)
if(s1[0]==s1[len]){
len-=2;
isPalindromeIterative(s1+1);
}
else
return false;
return true;
}
I am writing about Palindrome.
And when I run it, it appears warning like this:
":79:13: warning: add explicit braces to avoid dangling else
[-Wdangling-else]"
Please help me ! Thanks!
There is formally nothing wrong with the code, unless you wanted the else to match the outer if. A common mistake.
If you add braces everywhere, it will be clear what you intended:
if(len>0)
{
if(s1[0]==s1[len])
{
len-=2;
isPalindromeIterative(s1+1);
}
else
{
return false;
}
}
When you write,
if(len>0)
if(s1[0]==s1[len]){
// This has no effect on the recursive call.
len-=2;
// You missed the return in your post.
return isPalindromeIterative(s1+1);
}
else
return false;
it's most likely that you meant to associate the else with the second if.
if(len>0)
{
if(s1[0]==s1[len])
{
return isPalindromeIterative(s1+1);
}
else
return false;
}
However, the compiler does not use the indent to figure that out. It's possible that, from the compiler writer's point of view, you meant to associate the else with the first if:
if(len>0)
{
if(s1[0]==s1[len])
{
return isPalindromeIterative(s1+1);
}
}
else
{
return false;
}
Since this is common mistake made by developers, the compiler warns you and hopes that you will update the code so that it's less likely to turn into a runtime error.
I want to point out that the recursion logic you are using to detect whether a string is palindrome is wrong.
Let's say your string is "abxba".
In the first iteration, you compare 'a' with 'a'.
In the next iteration, you compare 'b' with 'a', which is incorrect. You end up with the wrong answer.
You have to change your strategy a bit. Use:
bool isPalindromeIterative(const char *s1, int start, int end)
{
if ( start >= end )
{
return true;
}
if ( s1[start] == s1[end] )
{
return isPalindromeIterative(s1, start+1, end-1)
}
return false;
}
The start of the iterative call has to be made as:
isPalindromeIterative(s1, 0, strlen(s1)-1);
It is a style warning against reading the if clauses wrong.
if(len>0) {
if(s1[0]==s1[len]){
len-=2;
isPalindromeIterative(s1+1);
}
} else {
return false;
}
is better to read and less error-prone.
We have similar coding guidelines in our company; for an if, which has bracket clauses, all else branches and all other ifs within the if of the highest order have to have brackets.
Else your example could too easily be misread as e.g.
if(len>0)
if(s1[0]==s1[len]){
len-=2;
isPalindromeIterative(s1+1);
}
else
return false;
Your original post headline mentioned iterative, and 'Iterative' is still part of your function name (even though it is recursive).
You marked this post as c++, but did not use classes.
The other answers addressed your specific questions about your error messages.
For your consideration, and because you have already selected a recursive answer, here is a possible C++ iterative solution and tail-recursive solution using std::string&.
#include <iostream>
#include <string>
class T589_t
{
public:
int exec(int argc, char* argv[])
{
if (argc < 2)
{
std::cerr << "\n please provide one or more string(s) to test"
<< std::endl;
return -1;
}
for (int i = 0; i < argc; ++i)
{
std::string s = argv[i];
{
std::string yesno = (isPalindromeIterative(s) ? " is" : " is not");
std::cout << "\n '" << s << "'" << yesno << " a palindrome (iterative)" << std::flush;
}
std::cout << std::endl;
{
std::string yesno = (isPalindromeRecursive(s) ? " is" : " is not");
std::cout << " '" << s << "'" << yesno << " a palindrome (recursive)" << std::endl;
}
} // for 0..argc
return 0;
}
private: // methods
bool isPalindromeIterative(const std::string& s1)
{ // ^^^^^^^^^
bool retVal = false; // guess s1 is not palindrome
int left = 0; // index of left most char
int right = static_cast<int>(s1.size()) - 1; // index of right most char
do { // iterative loop
if (s1[left] != s1[right]) break; // when not equal, is not palindrome
left += 1; right -= 1; // iterate!
if (left >= right) // all chars tested?
{
retVal = true; // confirm palindrome
break; // exit
}
} while (true);
return retVal;
}
// Notes './dumy589' // odd length 9
// ^-------^ [0] vs [8]
// ^-----^ [1] vs [7]
// ^---^ [2] vs [6]
// ^-^ [3] vs [5]
// ^ [4] == [4] // left >= right, break
// Notes 'abccba' // even length 6
// ^----^ [0] vs [5]
// ^--^ [1] vs [4]
// ^^ [2] vs [3]
// [3] vs [2] // left >= right, break
// Notes 'abcba' // odd length 5
// ^---^ [0] vs [4]
// ^-^ [1] vs [3]
// ^ [2] vs [2] // left >= right, break
// and bonus: tail recursion based on above iterative
// vvvvvvvvv
bool isPalindromeRecursive(const std::string& s1)
{
// index of left most char
int left = 0;
// index of right most char
int right = static_cast<int>(s1.size()) - 1;
return (isPalindromeRecursive(s1, left, right));
}
bool isPalindromeRecursive(const std::string& s1, int left, int right)
{
if (s1[left] != s1[right]) return false;
left += 1; right -= 1;
if ( left >= right ) return true;
return (isPalindromeRecursive(s1, left, right));
}
}; // class T589_t
int main(int argc, char* argv[])
{
T589_t t589;
return t589.exec(argc, argv);
}
On Linux, argv[0] is the executable name.
environment:
Lubuntu 17.10,
g++ (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0
With invocation:
./dumy589 aba abccba tx s
This code reports:
'./dumy589' is not a palindrome (iterative)
'./dumy589' is not a palindrome (recursive)
'aba' is a palindrome (iterative)
'aba' is a palindrome (recursive)
'abccba' is a palindrome (iterative)
'abccba' is a palindrome (recursive)
'tx' is not a palindrome (iterative)
'tx' is not a palindrome (recursive)
's' is a palindrome (iterative)
's' is a palindrome (recursive)

What is the return value of the given function on encountering an exception?

checkUsername() checks the username's length, and returns true when length is greater than or equal to 5. Otherwise it returns false.
The function checkUsername() should return false on BadLengthException(), but it doesn't seem to appear as none of the code within checkUsername() and BadLengthException::what() returns false. But still the program is working fine when it encounters a username of length less than 5. What's going on here? How is the return value passed false?
class BadLengthException: public exception{
public:
int n;
BadLengthException(int x) { n=x; };
virtual int what() throw() {
return n;
}
};
/*
This function checks the username's length,
and returns true when length is greater than or equal to 5.
Otherwise it returns false.
*/
bool checkUsername(string username) {
bool isValid = true;
int n = username.length();
if(n < 5) {
throw BadLengthException(n); //the problem
}
for(int i = 0; i < n-1; i++) {
if(username[i] == 'w' && username[i+1] == 'w') {
isValid = false;
}
}
return isValid;
}
int main() {
int T; cin >> T;
while(T--) {
string username;
cin >> username;
try {
bool isValid = checkUsername(username);
if(isValid) {
cout << "Valid" << '\n';
} else {
cout << "Invalid" << '\n';
}
} catch (BadLengthException e) {
cout << "Too short: " << e.what() << '\n';
}
}
return 0;
}
A function can either return a value or throw an exception, it can't do both, they're mutually exclusive. If it successfully returns a value that means the code didn't throw an exception, and if an exception was thrown then it means it didn't make it to the point of returning a value.
Further to that, capturing the return value is also interrupted, the code jumps right to the catch block you've defined. It's like a hard goto in concept, if you ignore things like automatic object destruction and finally type implementations which will happen in the process of an exception bubbling up.
When the exception is thrown in checkUsername(), it stops processing in that function and returns to the calling function which is main(). Because the call was made in a try block the exception is handled by the catch block.
The if() statement is completely ignored and the catch doesn't care about what happened in that function and just prints "Too short: "

The Difference Between Calling and Returning a Recursive Function in C++

Can someone please explain with a simple example what precisely is the difference between calling and returning a recursive function in c++?
Here is my code which seeks to find a character in a string recursively. It works fine when I just call find(); the function displays an integer value, But, when I code return find(letter,word), it gives the correct result as either a 1 or 0. Thanks
bool find(char f,string str)
{
static int len = str.length() - 1;
static int count = 1;
if (len<0)
{
return false;
}
else
{
if (str[len] == f)
{
return true;
}
else
{
len--;
return find(f, str);
}
}
}
You don't return the function you return the result of the call.
Here a basic example of recursion :
unsigned int factorial(unsigned int n)
{
if (n == 0)
return 1;
return n * factorial(n - 1);
}
If we call the function with n == 2 the program will do:
1) factorial (2) => return 2 * factorial(1); // It calls factorial with n == 1, do the multiplication and then return the result.
2) factorial(1) => return 1 * factorial(0); // same here with n == 0
3) factorial(0) => return 1; // from here the program will come back from the calls with the results
4) factorial(1) => return 1 * 1; => return 1;
5) factorial(2) => return 2 * 1; => return 2;
Few other things : be aware that your code will only work once as you use static int len, and count is a useless variable.
The function signature indicates a return value, so you need to embed the function call in a return statement for a value to be returned by the function, especially when neither of the if-conditionals are true.
Consider the following code (a variant of what the OP provided):
#include <iostream>
using namespace std;
int find(char f,string str) {
static int len = str.length() - 1;
static int count = 1;
int temp = 0;
if (len < 0) {
cout << count << "\n";
return -99;
}
else
if ( str[len] == f) {
return len;
}
len--;
count++;
temp = find( f, str );
cout << temp << "\n";
return temp;
}
int main() {
char ch = 'z';
int res = find(ch,"I");
if (res < 0) {
cout << "Letter '" << ch << "' was not found";
}
return 0;
}
See demo
Note that find() has a return value of -99 when the letter is not found. That value is captured by temp in find() and the function then returns the value of temp.
Now, consider main() -- its signature also indicates a return value, although it is discarded. If you attempt to execute the code without returning some kind of an integer in main(), the execution will be flawed.
So, whether you use a function recursively or not, if the function's signature indicates a return value then you need to return a value of the expected type. Since find() may return -99 or the position of the found letter, when it executes it will evaluate as one of those two values which will be returned by means of the return statement.

How to use boost::optional

I am trying to use boost::optional as below.
#include <iostream>
#include <string>
#include <boost/optional.hpp>
struct myClass
{
int myInt;
void setInt(int input) { myInt = input; }
int getInt(){return myInt; }
};
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5)
{
// If greater than 5 length string. Set value to 10
value.get().setInt(10);
}
else if (str.length() < 5)
{
// Else set it to 0
value.get().setInt(0);
}
else
{
// If it is 5 set the value to 5
value.get().setInt(5);
}
return value;
}
int main()
{
boost::optional<myClass> v1 = func("3124");
boost::optional<myClass> v2 = func("helloWorld");
boost::optional<myClass> v3 = func("hello");
if (v1)
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
if (v2)
std::cout << "v2 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
if (v3)
std::cout << "v3 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
return 0;
}
I get following error
prog.exe:
/usr/local/boost-1.55.0/include/boost/optional/optional.hpp:631:
boost::optional::reference_type boost::optional::get() [with T =
myClass; boost::optional::reference_type = myClass&]: Assertion
`this->is_initialized()' failed.
Presumably, the optional variable is not initialized properly. How to do it the correct way?
EDIT:: Got some very good answers, just couple of more questions 1. Is it a good idea to use make_optional at the end of 'func' function and return it? Also 2. I was thinking of assigning boost::none to emphasize that I have no value to assign and that's why boost::none. But not sure if that is valid?
A default-constructed boost::optional is empty - it does not contain a value, so you can't call get() on it. You have to initialise it with a valid value:
boost::optional<myClass> value = myClass();
Alternatively, you can use an in-place factory to avoid copy initialisation (but the copy will most likely be elided anyway); however, I have no experience with that, so I can't provide an example.
As a side note, you can use -> in place of get(), like this:
value->setInt(10);
But that's just a matter of stylistic preference, both are equally valid.
How to do it the correct way?
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return myClass{5};
}
As a side note, this code doesn't need boost::optional, because there is no code branch that returns an empty object (it is semantically equivalent to returning a myClass instance).
To return an empty optional, use this:
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return boost::none; // return empty object
}
Idiomatic client code (don't pre-initialize your values):
int main()
{
if (auto v1 = func("3214"))
// use *v1 to access value
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
return 0;
}
Two easy approaches:
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
else // If it is 5 set the value to 5
value = 5;
return value;
}
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5) // If greater than 5 length string. Set value to 10
return 10;
else if (str.length() < 5) // Else set it to 0
return 0;
else // If it is 5 set the value to 5
return 5;
}
note that returning an optional from a function that never returns an empty optional is a bad idea.
optional behaves like a pointer on read access -- you can only read the value from it if you have already verified there is something there to read. You can check if there is something to read by doing bool something_to_read = opt;.
You can, however, write to it whenever. If there is nothing there, it creates something. If there is something there, it overwrites it.
.get() is a reading, not a writing, operation. (it "reads" the reference) It is only safe to use when the optional is engaged and has data. Confusingly, you can write to the "read access" .get() return value, as it is a non-const reference.
So maybe "read" and "write" are bad words to use. :)
It is sometimes helpful to think of optional as a value-and-pointer mixed together. There is a possibly null pointer to an owned buffer of memory that may, or may not hold a copy of the type.
If the pointer inside the optional is null, then the buffer is uninitialized. If it points at the buffer, then the buffer is initialized.
.get() dereferences that pointer and returns the resulting reference without checking. = checks the pointer, if it is null, it does a copy-construct from the rhs into the buffer and sets the pointer. If not, it just assigns to the buffer.
(The pointer is conceptual: usually implemented as a bool flag).
I find using *optional to be better than optional.get(), as the "you must check before you dereference" is more obvious with the dereference operator.
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value; //not init is invalid
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
return value;
}
v1 is valid
v2 is valid
v3 is not valid
according to boost,optional default ctor will create an optional obj as invalid
optional<T> def ; //not initalize with a obj T
assert ( !def ) ;

C++ returning boolean as 95

Problem with returning booleans in c++..
bool find( const TrieNode &node, const string word )
{
if (word.length() == 0)
{
if (node.isWord)
{
cout << "TRUE" << endl;
return true;
}
else
{
cout << "FALSE" << endl;
return false;
}
}
char firstletter = word.at(0);
int index = firstletter - 'a';
if (node.letters[index] == NULL)
{
return false;
}
else
{
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
}
in my main I have
cout << find(*mynode,"word") << endl;
would yield to :
FALSE
95
clearly, a cout of FALSE means that the function returns false.. However, when I print out the result of the function, I get 95 which evaluates to true.. Any reason why it could be doing this?
thanks
Your missing a final return statement, so your getting whatever is in the low byte of EAX, which is random garbage. your probably want return true; at the very end of your function.
Your should pump the warning level of your compiler as it should be telling you this (something along the lines of "not all control paths return a value").
The problem is with your final if statement:
if (node.letters[index] == NULL) {
return false;
}
else {
//if execution gets here, the return value of the function is undefined
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
...perhaps try:
if (node.letters[index] == NULL) {
return false;
}
else {
return find (*node.letters[index],word.substr(1,(word.length() - 1)));
}