2
\$\begingroup\$

I need to remove all occurrences of a digit from a number in a recursive function with this prototype:

unsigned rem(unsigned num, unsigned dig);

This is my solution:

#include <stdio.h>

// just returns 10 to the power of n
int power(int n)
{
    if (n==0)
        return 1;

    int res=1;

    for (int i=0; i<n; i++)
        res *= 10;

    return res;
}

static int i=0;

unsigned rem(unsigned num, unsigned dig)
{ 
    int tmp = power(i);

    if (num == 0)
        return 0;
    else 
    {
        if (num%10 != dig)
        {
            i++;
            return (num%10)*tmp + rem(num/10, dig);
        }
        else
            return rem(num/10, dig);
    }

}

int main()
{   
    unsigned n, res;

    scanf("%u", &n);

    res = n;

    for (int j=2; j<10; j+=2)
    {
        res = rem(res, j);
        // reset
        i=0;
    }


    printf("%u without even numbers: %u\n", n, res);
    return 0;
}

It works but I've read a lot about how a global static variable is not a good solution, so I was thinking if there is a way without it.

I've had other solutions (with a local static variable), but all fail when I need to call the function more than once.

Also, the only reason for using a static variable, is to keep tract of what the weight of the next digit of the result.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Yes, the code can be simplified quite a bit, and in the process the static/global variable eliminated.

At least to me, an obvious implementation would be something like this:

unsigned rem(unsigned num, unsigned dig)
{
    if (num == 0)
        return num;

    unsigned digit = num % 10;

    unsigned temp = rem(num / 10, dig);

    if (digit != dig)
        temp = temp * 10 + digit;

    return temp;
}

So we basically split the number into the least significant digit, and everything else. We do the recursive call on the "everything else" part. Then we look at the least significant digit. If it's to be removed, we just leave it off the result. If it's not to be removed, we multiply the return value by 10, then add our digit on as the least significant again.

Of course, variations in syntax are possible. For example, you could use something like:

temp = rem(num / 10, dig);

return dig != digit ? temp * 10 + digit : temp;

That makes it shorter in terms of the number of lines of code, but it's essentially identical in terms of the real work being done.

\$\endgroup\$
1
  • \$\begingroup\$ Wow, so simple! Thanks. I knew I overcomplicated :) Recursions can be so exhausting when you have the wrong idea. I'm slowly getting the handle on it, but still I sometimes miss the obvious. You just had a typo (in the description you wrote we multiply temp with 10, but in the code you wrote temp*temp). \$\endgroup\$
    – smrdo_prdo
    Commented Apr 18, 2016 at 22:34
1
\$\begingroup\$

The rem() method could be improved by putting the guard condition if (num == 0) to the very top of it. There is no need to call power(i) if num ==0.


I would like to encourage you to always use braces {}. Although they might be optional they will help to make your code less error prone.

\$\endgroup\$
1
  • \$\begingroup\$ Points one and two noted. Thanks. I usually put braces everywhere, if anything it is easier to add something later. \$\endgroup\$
    – smrdo_prdo
    Commented Apr 18, 2016 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.