0

This is a recursive function to find the amount of 2 appearing in a number.

Example Input:

221122

Example Output:

countTwo(): 4

#include <stdio.h>
void countTwo2(int num, int *result);

int main()
{
    int number, result;
    printf("Enter the number: \n");
    scanf("%d", &number);
    countTwo2(number, &result);
    printf("countTwo2(): %d\n", result);
    return 0;
}

void countTwo2(int num, int *result)
{
    if(num > 0) {
       if((num % 10)/2 == 1) {
           *result += 1;
       }
       countTwo2(num/10, result);
    }

}

I can't increment result since it has not been initialised but I also can't initialise result in the recursive function as this will reset the result.

Edit: This is a question given, with all the template written as above except for the code within countTwo. We are supposed to write the code in countTwo such that main() will be able to run.

Edit2: Thanks for the help! This problem has been solved by using static int. I understand that this is not very efficient. I will also ask my teacher pertaining to this question. Once again, Thanks!

Ophitect
  • 543
  • 4
  • 18
  • Why not simply initialize `result` before you call the function? – Some programmer dude Oct 12 '18 at 08:58
  • if you assigned any value to `result` like `*result=1` that should be accessible in `main()` – Mayur Oct 12 '18 at 08:58
  • If this is a recursive function you have to post the code in the function body or we can't help. Normally recursion would pass the value between calls over the stack. A better solution is however not to use recursion, but a plain loop. – Lundin Oct 12 '18 at 09:02
  • 1
    Are you saying you're not allowed to touch and change `main`? Because then you have undefined behavior and undefined behavior is ... well ... undefined. – Lasse V. Karlsen Oct 12 '18 at 09:14
  • @LasseVågsætherKarlsen yes. I'm not allowed to touch and change main. – Ophitect Oct 12 '18 at 09:15
  • use static variable https://stackoverflow.com/questions/572547/what-does-static-mean-in-c – manoliar Oct 12 '18 at 09:15
  • Can you add another method? If so then you could initialize the result variable in `countTwo2`, then call `countTwo3` which would effectively be the recursive one. – Lasse V. Karlsen Oct 12 '18 at 09:15
  • Does it have to be recursive? Implement it with a loop instead and then you can simply assign a new value to `result`, instead of incrementing it. – Lasse V. Karlsen Oct 12 '18 at 09:16
  • There is a way to keep all the oddity of this code. Rewrite your function to have an else-part that sets result to 0 (since value was also 0), then move the call inside the if-then part up above the if-statements that checks if it should increment. This would call the function recursively all the way down to 0, reset the result, then return back up one layer at a time, incrementing the value (which now started at 0). – Lasse V. Karlsen Oct 12 '18 at 09:20
  • 1
    Can you please show us how you solved it using static int? – Lasse V. Karlsen Oct 12 '18 at 09:23
  • Isn't this initial call `countTwo2(number, &result);` not already invoking undefined behaviour by passing in an uninitialised variable: `number`? – alk Oct 12 '18 at 12:18

4 Answers4

3

The way to keep all the oddities of this code:

  • it has to be recursive
  • you cannot change main, so the initial result value will be undefined

is to, as you stated you cannot do, actually reset result inside countTwo2. However, you need to it in the right place, before you start incrementing.

The way to do that is to reorder your function and add the part that resets the value at the right place:

void countTwo2(int num, int* result)
{
    if (num > 0)
    {
        countTwo2(num / 10, result);
        if ((num % 10) / 2 == 1)
        {
            *result += 1;
        }
    }
    else
        *result = 0;
}

Notice that I moved the recursive call up above the if-then block that increments the result, and that when num is 0, we reset. This will call recursively down digits of the input until we're at the end, then reset the result, then return back up one digit at a time and optionally increment the value.

This requires no other changes to your code.

As many have stated, in comments and answers, this is obviously not a good implementation or design but if you have a confined context to work in, this is probably as good as it gets.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • If I may, consider adding `if (num > 0) {...} else if (num < 0) { countTwo2(-num, result); } else...` to take care of negative numbers too. – Bob__ Oct 12 '18 at 09:37
  • I'll leave that as an exercise for the reader or OP, my point was not to make it correctly count the number of 2's, my answer is how to fix the problem with the undefined behavior. – Lasse V. Karlsen Oct 12 '18 at 09:40
1

I can't see any good reason for declaring this as a void function with the result passed back via pointer parameter.

The following would be a lot cleaner, surely?

int countTwo(int num) {
    return (num == 0) ? 0 : (num % 10 == 2) + countTwo(num / 10);
}
r3mainer
  • 23,981
  • 3
  • 51
  • 88
1

For reference, the proper way to write such a function is to not use recursion. It isn't obvious that the compiler will be able to unroll the recursion in this case, as the recursive call would be in the middle of the function, and also conditional.

Thus the only thing gained from recursion is slow execution and higher stack peak use. Why would we want slow execution when we can have fast execution? You should ask your teacher this question, so they can tell you why they are teaching it. I would be most curious to hear their rationale.

For a professional, non-academic programmer, the proper way to write the function would be to use a loop:

int count_n (int input, int n)
{
  int result = 0;

  for(; input>0; input/=10)
  {
    if(input%10 == n)
    {
      result++;
    }
  }

  return result;
}

(This version doesn't work with negative numbers.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

As I mentioned before you may use static variables. You do not need two arguments. Here is a solution: @Lasse Vågsæther Karlsen

#include <stdio.h>
int countTwo2(long int num)
{
    static int m=0;  //static variable is initialized only once.
    if (num==0)
        return m;
    else if (num % 10 ==2)
        m=m+1;
    num=num /10;
    countTwo2(num);
}

int main()
{
    int result; long int number;
    printf("Enter the number: \n");
    scanf("%ld", &number);
    result=countTwo2(number);
    printf("countTwo2(): %d\n", result);
    return 0;
}
manoliar
  • 172
  • 1
  • 8