return statement in Recursion: C++ - c++

I am trying to implement binary search tree and trying to implement searching the value from a node.
The book implements it through recursion.
To understand the procedure better, I am trying to apply the logic on an array.
Consider below code:
#include <iostream>
#include "BST.h"
using namespace std;
char Array[]={'A','B','C','D','E','F','G','H','I','J'};
char fn(int i,int x)
{
if( i == x)
{
cout << "Case : 1 " << endl;
return Array[x];
}
else if( i > x)
{
cout << "Case : 2 " << endl;
fn(--i,x);
}
else if(i < x)
{
cout << "Case : 3 " << endl;
fn(++i,x);
}
}
int main()
{
cout << fn(2,7) << endl ;
system("Pause");
return 0;
}
What I am trying to achieve is fn(int i,int x): from index i , search index x and return the value at index x.
The output is:
Case : 3
Case : 3
Case : 3
Case : 3
Case : 3
Case : 1
H
Press any key to continue . . .
The recursion logic works fine. But while compilation, it shows warning as main.cpp(28): warning C4715: 'fn' : not all control paths return a value
So if I modify my code as:
char fn(int i,int x)
{
if( i == x)
{
cout << "Case : 1 " << endl;
return Array[x];
}
else if( i > x)
{
cout << "Case : 2 " << endl;
return fn(--i,x);//added return here
}
else if(i < x)
{
cout << "Case : 3 " << endl;
return fn(++i,x);//added return here
}
}
There is no compilation warning and output is exactly the same. My question is what purpose does return in each 'else if test condition' serve, I am returning from my base condition i.e. return Array[x]; and this is what I wanted my function to return. Why to put return in all the test conditions?
EDIT
Just realized, second version of function still giving compilation warning main.cpp(30): warning C4715: 'fn' : not all control paths return a value
What should be done? How to resolve?

My question is what purpose does return in each 'else if case' serve, I am returning from my base condition i.e. return Array[x]; and this is what I wanted my function to return. Why to put return in all the test conditions?
This returns the value from the base case ultimately to the top level of the recursive calls.
To understand this better, remember that return simply gives execution back to the function which called fn(). When fn() is called recursively, the caller and callee are both copies of the fn() function. You may call fn() recursively many times and each recursive call must return the result to its parent and ultimately back to the function which originally called fn().
I suggest you get a piece of paper and a pencil and work manually through an example input. Trace each recursive call of fn() and what happens when you return from each of these. After you do this by hand, use a debugger to step through your code to check that it works the way that you expect.

Without the return before fn(--i, x), and fn(++i, x), the function does not return from those statements. It tries to run any other statements that function might have. However, there aren't any. It reaches the end of the function without encountering a return statement.
A function whose return type is not void must have a valid return statement. Otherwise, the behavior of the code is undefined. You can read more about that at https://stackoverflow.com/a/1610454/434551.
The compiler is helping you avoid that problem by reporting warnings.

Related

Understanding the Order of Execution of Recursive Functions

template <typename T>
T sum(stack<T>& s){
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}
}
The code above is designed to recursively sum the elements of any given stack of type T with the only condition being that the integrity of the stack must be restored at the end of the function. Meaning, I am allowed to make changes to the stack to sum the elements as long as it is in the same state as it was before it was passed when the function terminates.
As you will observe the given code works however I do not understand the control flow or execution sequence of the recursive calls and return statements. When I see this code I understand how the elements are summed, however I do not understand how the call to "s.push(first)" adds all of the elements back on to the stack. I'm having a hard time wrapping my head around why it wouldn't solely push the last element of the stack and then return the total.
My current understanding of why this works is incomplete and likely flawed and is as follows: because each return statement returns to the most recent caller, when the recursion hits the base case and terminates, the return statements will work their way back up the recursive call stack until it gets to the original caller and therefore executing "s.push()" at each movement back up the stack.
What is causing confusion for me is the execution sequence once the stack is empty and I think it is due to a lack of understanding the way the function recurses back up the call stack. If someone could lay out the execution sequence and explain the way recursion works with operations underneath the recursive call that would me much appreciated.
Thanks!
Your overall understanding is correct. You're only missing connecting the final dots.
The key point to remember is when a function returns, it returns to wherever it was called from. Recursive functions are no different in that fundamental respect. Recursive function calls work exactly the same way.
It will help to understand if you label each recursive call. Let's call the initial invocation of the recursive function "A". When the recursive function calls itself, recursively, call that invocation of the recursive function "B". Then it calls again, and that's "C". Followed by "D", and so on.
The key point to understand is that when a function returns, it returns to wherever it was called from. So, "D" returns to "C", which returns to "B", and it returns to "A".
Now look at your recursive function. When the stack had one value left, let's call it "D", it removes the "D" value from the stack and makes the recursive call "E", which discovers that the stack is empty.
So it returns to "D", which pushes the "D" value back to the stack, which now has one value again. Then it returns to "C", which pushes the "C" value back to the stack, which now has the two original, last, values on the stack, in the same order.
In this fashion, the function calls unwind in reverse order from their original calling sequence, restoring the stack to exactly what it was, originally.
Your function looks something like this:
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}
To kind of see how this works, let's pretend that this is actually a macro, and expand the function into what would generally get executed:
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}+first;
s.push(first);
return total;
}
This is of course, just an example. Since it is not a macro,this isn't what really happens. It is just to illustrate.
However, the point is that the code in your function will get executed every time you call the function similarly to the second code snippet. Thus, what ends up happening is that the innermost function pushes to the stack, and then the calling function pushes to the stack, etc.. until everything gets pushed back on to the stack. So, even though there is one call to push on the stack, it will still get executed every time the function executes.
"If someone could lay out the execution sequence ... "
It is always allowed to add (removable) cout's to the executing code. The following illustrates one approach.
Note 1: To simplify, I removed template issues. The demo uses int.
Note 2: dumpStack is not recursive.
Note 3: m_stck is data attribute of the class, so it need not be passed from sumStack to sumStack.
#include <iostream>
using std::cout, std::endl; // c++17
#include <iomanip>
using std::setw, std::setfill;
#include <string>
using std::string, std::to_string;
#include <stack>
using std::stack;
#ifndef DTB_PCKLRT_HH
#include "../../bag/src/dtb_pclkrt.hh"
using DTB::PClk_t;
#endif
class StackW_t // stack wrapper UDT (user defined type)
{
private:
int m_N; // max elements
stack<int> m_stck; // default ctor creates an empty stack
public:
StackW_t(int N = 10) // simple default size
{
m_N = N; // capture
assert(m_N > 1); // check value
for (int i=0; i<m_N; ++i)
m_stck.push(N - i); // simple fill
}
~StackW_t() = default; // dtor default deletes each element of m_stck
// recurse level-vvvv
int sumStack(int rLvl = 1)
{
if (m_stck.empty())
{
cout << "\n" << setw(2*rLvl) << " " << setw(4) << "<empty>";
return 0;
}
else
{
int first = m_stck.top(); // top element
m_stck.pop(); // remove top element
cout << "\n" << setw(2*rLvl)
<< " " << setw(4) << first; // recurse report
// use first value then recurse into smaller stack with next rLvl
int sum = first + sumStack(rLvl+1);
cout << "\n" << setw(2*rLvl) // decurse report
<< " " << setw(3) << "(" << first << ")";
m_stck.push(first); // restore element after use
return sum;
}
}
void dumpStack(string lbl, int rLvl = 1)
{
stack<int> l_stck = m_stck; // for simplicity, use copy of
cout << "\n dumpStack " << lbl << setw(2*rLvl);
while (!l_stck.empty())
{
cout << " " << " " << l_stck.top();
l_stck.pop(); // remove displayed member
}
cout << "\n";
}
}; // class StackW_t
// Functor 829
class F829_t // use compiler provided defaults for ctor and dtor
{
PClk_t pclk; // posix clock access
public:
int operator()(int argc, char* argv[]) { return exec(argc, argv); }
private:
int exec(int , char** )
{
int retVal = 0;
// create, auto fill with value 1..10
StackW_t stk;
stk.dumpStack("before"); // invoke display
cout << "\n stk.sumStack(): ";
uint64_t start_us = pclk.us();
// invoke recursive compute, start at default rLvl 1
int sum = stk.sumStack();
auto duration_us = pclk.us() - start_us;
cout << "\n sum: " << sum << endl;
stk.dumpStack("after"); // invoke display
cout << "\n F829_t::exec() duration "
<< duration_us << " us (" << __cplusplus << ")" << std::endl;
return retVal;
}
}; // class F829_t
int main(int argc, char* argv[]) { return F829_t()(argc, argv); }
Note 4: during recurse, rLvl increases, so the value shifts to the right for each line
Note 5: during decurse, rLvl is restored upon function return, thus output is also restored to alignment
Note 6: before and after of stack shows successful restore of stack
Output:
dumpStack before 1 2 3 4 5 6 7 8 9 10
stk.sumStack():
1
2
3
4
5
6
7
8
9
10
<empty>
(10)
(9)
(8)
(7)
(6)
(5)
(4)
(3)
(2)
(1)
sum: 55
dumpStack after 1 2 3 4 5 6 7 8 9 10

Program works when executed in C++ Tutor, but not anywhere else

I'm writing a rather simple program following Euclidean algorithm (we have to write it using recursion). It works really well when executed in C++ Tutor but when I compile the program in the terminal, it already gives me:
warning: control may reach end of non-void function [-Wreturn-type]
When I try to execute it in the terminal, it throws:
runtime error: execution reached the end of a value-returning function without returning a value
(But I am returning a value?)
Why does it work with c++ tutor but not in the Linux terminal (using clang compiler)?
I tried to use a bunch of extra variables in the function to make the process clearer to me, but I still don't get why it thinks that there would be a case where I would not return a value.
#include <iostream>
using namespace std;
int ggt(int a, int b){
int rest{0};
int zaehler{0};
int divisor{0};
if(a>=b){
zaehler=a;
divisor=b;
if(a%b==0){
return b;
}
else{
rest=a%b;
divisor=rest;
zaehler=b;
ggt(zaehler, divisor);
}
}
else{
zaehler=b;
divisor=a;
if(b%a==0){
return a;
}
else{
rest=b%a;
divisor=rest;
zaehler=a;
::durchlaeufe--;
ggt(zaehler, divisor);
}
}
}
int main(){
int a{40}, b{12};
cout << "Bitte Zaehler eingeben: ";
cin >> a;
cout << "\n";
cout << "Bitte Nenner eingeben: ";
cin >> b;
cout << "\n";
if(ggt(a, b)==0){
cout << "ERROR\n";
}
else {
cout << "Der groesste gemeinsame Teiler ist: " << ggt(a, b) << "\n";
}
return 0;
}
In this example, with a=40 and b=12, the result should be 4. And that's exactly what C++ tutor says...
the actual answer (missing return at recursion call) was already given.
i'd like to add a simpler version for you to compare and maybe learn something :)
int ggt(int a, int b)
{
if (a < b)
{
std::swap(a, b);
}
if (a%b == 0)
{
return b;
}
return ggt(b, a%b);
}
short explanation:
the "swap" when a < b ensures b contains the smaller value.
the "rest" (a%b) is calculated directly when calling the recursion (this avoids storing intermediate values)
as you see the control flow is simpler, so it is easier to reason about each step of the execution.

C++ Recursive Function Infinite Loop

I have a function which takes an int value from another function. When I type a wrong int value it works as intended (calls the same function recursively & lets me enter a new number) but when I type anything other than an int (a, %, etc) it calls the function recursively but gets stuck in an infinite loop. Any help/insight would be great as I am in the learning stages of C++ Programming.
Here is my Full code snippet (49 Lines)
To summarize what I am asking is how would I properly go about displaying an error and returning back to the Main Menu without triggering the infinite loop when a non-int value is given.
int MainMenu();
void MainMenuSelection(int x);
int main()
{
MainMenuSelection(MainMenu());
return 0;
}
int MainMenu() {
int selection;
std::cout << "C++ Tutorials Main Menu\n";
std::cout << "----------------------------------------------\n";
std::cout << "1 - Chapter #1\n";
std::cout << "2 - Chapter #2\n";
std::cout << "3 - Chapter #3\n";
std::cout << "----------------------------------------------\n";
std::cout << "Please enter a cooresponding value: ";
std::cin >> selection;
if (std::cin.fail()) {
std::cout << "Input must be an integer";
}
else {
return selection;
}
}
void MainMenuSelection(int x) {
if (x == 1) {
std::cout << "\nChapter #1 is unavailable.\n";
std::cout << std::string(22, '\n');
MainMenuSelection(MainMenu());
}
else if (x == 2) {
std::cout << std::string(2, '\n');
ChTwoMenuSelection(ChTwoMenu());
}
else if (x == 3) {
std::cout << std::string(2, '\n');
ChThreeMenuSelection(ChThreeMenu());
}
else {
std::cout << "\nThere was an incorrect value submitted.";
std::cout << std::string(22, '\n');
MainMenuSelection(MainMenu());
}
}
The function MainMenuSelection( int x ) requires an int. The function call in the main function thinks it gets this by calling a function which should return an int namely int MainMenu(). But this function does not do what you should expect from a function which has been declared in this way. You should make sure that a function should ALWAYS return the value (except for a void of course).
There are static code analyzers like Cppcheck which can help you to analyse your code and find possible problems like the one you stated above.
Another tip would be to think about what happens when you execute the code. Especially when your code is still quite small you can manually go through the statements to see what path it takes, so you can find out where the program fails.

C++ // Not all control paths return a value

int bounce(int n) {
if (n == 0)
{
cout << "0" << endl;
}
if (n > 0)
{
cout << n << endl;
bounce(n - 1);
cout << n << endl;
}
}
int main()
{
int x;
cout << "Choose a number: ";
cin >> x;
cout << bounce(x) << endl;
system("pause");
return 0;
}
I recently started for my first time with C++ (2 hours ago or so :D ) and the problem i have is "Bounce: not all control paths return a value", I don't know how to fix this, obviously i need return 0; or something somewhere in the function but i can't find out where without ruining how it works.
Example : bounce(5) ==> prints out 5 4 3 2 1 0 1 2 3 4 5
TL DR: Where to place the return in bounce to make it work correctly.
Actually none of your control paths returns a value. As you only use the function to print something on the screen, it does not have to return anything. Just make the return type void:
void bounce(int n) {
/*...*/
}
And then dont cout the result of the function call (once you make it void the function wont return anything anyhow), i.e. instead of:
std::cout << bounce(x) << std::endl;
simply write
bounce(x);
You already print on the screen inside the function.
When you define a function in C++, you specify the return type before the function name.
Your int bounce() function is declared as returning an integer but it does not return any values at all. Therefore, that causes an error.
You can declare your function using void bounce(), which tells the compiler that your function will not return any values. That will eliminate the error.
Note: Although you use cout to display your values, this is different from returning a value in the way we are talking about. Returns values are specified using the return keyword.

why this function is not returning value expected

below is a searchVal function for searching a value in a binary tree. nodes of binary tree are stored in a vector nodeVec with first object in vector as root.
structure of nodes
class bst{
public:
//other functions..//
int searchVal(int)
private:
bst *lLink;
int info;
bst *rLink;
}
calling part in main
cout << "Enter Value to search ";
int val;
cin >> val;
int ret = nodeVec[0].searchVal(val);
if (ret == 2)
cout << "Value Not Found" << endl << endl;
else
cout << "Value Found" << endl << endl;
Function
int bst::searchVal(int val)
{
if (info != val)
{
if (info > val)
{
if (lLink != NULL)
lLink->searchVal(val);
else
return 2;
}
if (info < val)
{
if (rLink != NULL)
rLink->searchVal(val);
else
return 2;
}
}
if (info == val)
return 1;
}
while debugging (using codeBlocks) i observed that after any condition is met for example if the condition info==val is met the execution pointer (arrow in the IDE pointing to line being processed) goes to end of searchVal and after that it go to nearest if(from the end) however it does not go into the block of that condition. It always returns the info stored in root node in ret not 1 or 2
Should be
if(lLink!=NULL)
return lLink->searchVal(val);
^^^^^^
I think the major problem in your code is that you're not returning the result of the sub-tree searches; i.e. you should be doing this:
if(lLink!=NULL)
return lLink->searchVal(val);
You're missing the return keyword. That means that some execution paths go all the way through to the end of the function, and never hit a return, which is potentially very bad. The compiler should be issuing an error or warning about that though.
The searchVal function needs a return value on every code path - everything else has undefined behaviour (which means that anything could happen).
Add a return to your calls to lLink->searchVal and rLink->searchVal.
(And if your compiler didn't warn you about this, you need to enable that warning.)