avm
avm

Reputation: 399

What could be a better solution to calling a function recursively?

This is a simple function which will take value from user and if value is invalid then the function will call itself recursively until a valid input is provided.

#include<iostream>

using namespace std;

void getnum(){
    int num;
    string strnum;
    getline(cin, strnum);
    try{
        num = stoi(strnum); 
    }
    catch(invalid_argument &ia){
        cout<<"Invalid argument\n";
        getnum();
    }

    cout<<"\n"<<num;
}

int main(){
    getnum();
    return 0;
}
/*output(input: abc,abc,abc,4):
4
2494464
2494464
4201200
*/

Using the recursive approach the program is creating a new instance of the function every time an invalid argument is passed. After receiving a valid argument, function is printing multiple values(garbage values) of num due to multiple instances created.

The problem is that I want only the last value(correct one) to be printed. So I tried setting a 'flag' to control the execution of cout<<"\n"<<num.

#include<iostream>

using namespace std;

void getnum(){
    int flag = 0;
    int num;
    string strnum;
    getline(cin, strnum);
    try{
        flag = 1;
        num = stoi(strnum); 
    }
    catch(invalid_argument &ia){
        flag = 0;
        cout<<"Invalid argument\n";
        getnum();
    }
    if(flag)
    cout<<"\n"<<num;
}

int main(){
    getnum();
    return 0;
}
/*output(input:abc,abc,abc,4)
4 */

It solves my problem but still multiple instances are being created which I think is wastage of memory.

Is there any better way to do this without using a lot of memory(recursion)?

Upvotes: 0

Views: 75

Answers (1)

molbdnilo
molbdnilo

Reputation: 66371

You get multiple outputs because you print outside "the happy path" - move printing inside the try block.
It's even clearer to put the entire "happy path" inside the try:

void getnum(){
    try {
        string strnum;
        getline(cin, strnum);
        int num = stoi(strnum); 
        cout<<"\n"<<num;
    }
    catch(invalid_argument &ia){
        cout<<"Invalid argument\n";
        getnum();
    }
}

The idiomatic solution is to loop rather than recurse:

void getnum(){
    while (true)
    {
        try {
            string strnum;
            getline(cin, strnum);
            int num = stoi(strnum); 
            cout << "\n" << num;
            return;
        }
        catch (invalid_argument &){
            cout<<"Invalid argument\n";
        }
    }
}

Upvotes: 1

Related Questions