Home > Back-end >  How do I get a result from a recursive function without using a global variable?
How do I get a result from a recursive function without using a global variable?

Time:03-07

I wrote a function that reverses an integer (123 becomes 321) with recursion, and I was told that using global variables is bad practice, but I'm having trouble figuring out how to get the result from the function without using one. I tried declaring the variable inside the function, but then I get undesired results.

#include <stdio.h>

int result = 0;

int reverse_num(int num)
{
    int remainder = num % 10;
    
    if (num == 0) return 0;
    
    result *= 10;
    result  = remainder;
    
    reverse_num(num / 10);
    
    return result;
}

int main(void)
{
    int num, reversed_num;
    
    printf("Insert number: ");
    scanf("%d", &num);
    
    reversed_num = reverse_num(num);
    
    printf("Inverted number: %d", reversed_num);
    
    return 0;
}

Thank you for any assistance.

CodePudding user response:

To keep it similar to your original code, only without the global variable, try this:

#include <stdio.h>

int reverse_num(int num)
{
    static int result = 0;
    int remainder = num % 10;

    if (num < 0) {
        result = 0;
        return 0;
    }
    if (num == 0) return 0;
    result *= 10;
    result  = remainder;
    reverse_num(num / 10);
    return result;
}

int main(void)
{
    int num, reversed_num;

    printf("Insert number: ");
    scanf("%d", &num);
    reverse_num(RESET);
    reversed_num = reverse_num(num);
    printf("Inverted number: %d\n", reversed_num);
    return 0;
}

Here, I just make result into a local static variable in the function, which means it keeps its value even when the function returns (like a global variable, except that its scope is only within the function). The catch is that if you want to call it more than once, you need a way to reset the result value; I did this by using a negative value for num as a semaphore to reset.

CodePudding user response:

There are many ways. One way involves finding the most significant decimal digit per each recursion.

Below is an inefficient example.

Works OK for some values 0 to near INT_MAX/10.

#include <stdio.h>

int reverse_num(int num) {
  if (num < 10) {
    return num;
  }
  int pow10 = 10;
  while (num/pow10 >= 10) {
    pow10 *= 10;
  }
  int lead_digit = num/pow10;
  return reverse_num(num % pow10) * 10   lead_digit;
}

int main() {
  printf("%d\n", reverse_num(123456789));
  printf("%d\n", reverse_num(1));
  printf("%d\n", reverse_num(100));
}

Output

987654321
1
1

Fails for others printf("%d\n", reverse_num(123000789)); --> 987321.


Improved: recursive and efficient.

static int reverse_num_helper(int num, int power10) {
  if (power10 < 10) {
    return num;
  }
  return reverse_num_helper(num % power10, power10 / 10) * 10   num / power10;
}

int reverse_num(int num) {
  int pow10 = 1;
  while (num / pow10 >= 10) {
    pow10 *= 10;
  }
  return reverse_num_helper(num, pow10);
}

int main() {
  printf("%d\n", reverse_num(123000789));
  printf("%d\n", reverse_num(123456789));
  printf("%d\n", reverse_num(123));
  printf("%d\n", reverse_num(1));
  printf("%d\n", reverse_num(100));
}

Output

987000321
987654321
321
1
1

CodePudding user response:

int Reverse(int n,int Len) {
    if (n == 0)
        return 0;
    return std::pow(10, Len-1)*(n % 10)   Reverse(n / 10, Len-1);
}



  //inside main
    Reverse(54321,5);

//Output Should be 12345

CodePudding user response:

A somewhat more long-winded version of that given by @chux might be a bit clearer.

#include <stdio.h>

int count_places(int num);
int reverse_by_places(int num, int num_places);
int ipow(int base, int power);

int reverse_num(int num)
{
    return reverse_by_places(num, count_places(num)) / 10;
}

int ipow(int base, int power)
{
    if (power == 0)
        return 1;
    return base * ipow(base, power-1);
}

int count_places(int num)
{
    int i;
    if (num == 0)
        return 1;

    for (i = 0; num > 0; i  ) 
    {
        num /= 10;
    }
    return i;
}


int reverse_by_places(int num, int num_places)
{
    int dividend = num / 10, remainder = num % 10;
    
    if (dividend == 0)
        return remainder * ipow(10, num_places);
    else
        return ((remainder * ipow(10, num_places))   reverse_by_places(dividend, num_places-1));    
}

int main(void)
{
    int num, reversed_num;
    
    printf("Insert number: ");
    scanf("%d", &num);
    
    reversed_num = reverse_num(num);
    
    printf("Inverted number: %d\n", reversed_num);
    
    return 0;
}

CodePudding user response:

The common way to do this is to have another argument just for the accumulated result. It can be accomplished in C by splitting your function into the one called by the user and the one that does all the work.

int reverse_num_helper(int num, int result)
{
    int remainder = num % 10;
    
    if (num == 0) return result;
    
    result *= 10;
    result  = remainder;
    
    return reverse_num_helper(num / 10, result);
}

int reverse_num(int num)
{
    return reverse_num_helper(num, 0);
}

(In C you could combine the two into int reverse_num(int num, int result = 0).)

Notice how your function is essentially unchanged.
We made only two minor modifications:

  • returning result instead of zero when num reaches zero
  • invoking recursion with the modified result value

CodePudding user response:

I think I will use pointer in this situation.

  • Related