Reputation: 35
Is there a way to code a recursive function that prints the number of the digits in a number such that:
-It is a void function
-The "if" condition is if(num==0), return
-The "else" will call the recursion.
I saw 2 different types of codes, one of them is where the "if" condition has the recursive call and the else is for "return". But thats not what I want.
I am pretty bad with recursion and trying to understand it by coding myself, but unsuccessfully.
This is my code(I understand why it prints 122 instead of 3 but I dont really know how code it differently. Help anyone?)
#include <iostream>
#include <string.h>
using namespace std;
void numOfDigits(unsigned int num);
int main(){
int num = 994;
numOfDigits(num);
}
void numOfDigits(unsigned int num)
{
int size = 1;
if (num==0)
return;
else
{
if (num / 10 != 0)
size++;
numOfDigits(num / 10);
}
cout << size;
}
Upvotes: 1
Views: 4806
Reputation: 76245
A quick hack that makes this code work is to make size
static, that is, change
int size = 1;
to
static int size = 1;
But that only works the first time you call the function.
For a more robust solution, in each call to the function you have to pass the count so far:
void numOfDigits(unsigned int num, int countSoFar = 0) {
if (num == 0)
std::cout << countSoFar << '\n';
else
numOfDigits(num / 10, countSoFar + 1);
}
Upvotes: 1
Reputation: 694
numOfDigits is a void function
The "if" condition is if(num==0), return
The "else" will call the recursion.
Here:
void numOfDigits(unsigned int num) {
if (num == 0)
return;
// The "else" will call the recursion.
else {
static int size = 1;
if (num / 10 != 0) {
size++;
numOfDigits(num / 10);
}
else {
cout << size << '\n';
size = 1;
}
}
}
Upvotes: 0
Reputation: 66
The problem with using a void
return type on recursive functions is that it's not possible for the nested calls to return any information back to the method which invoked them. If we want to print the value at the first (outer) call, that first call can't gain any information from it's recursive call.
As you've observed, it's not possible to simply print the value as we go, since there isn't a one-to-one mapping from recursive calls to characters of the output (if we use Base 10... see the appendix). If we relax the condition that the if
condition must return immediately, we can avoid this problem by passing the information as parameters to the recursive call and then printing the value at the deepest level of recursion. For example:
// The accumulator starts at 0, then increases by 1 for each recursive call
void numOfDigits(unsigned int num, unsigned int accumulator = 0) {
if (num == 0) {
if (accumulator == 0) cout << 1; // Special case: numOfDigits(0) = 1
else cout << accumulator;
} else numOfDigits(num / 10, accumulator + 1);
}
Side-note: This is now a tail-recursive method: it makes the recursive call as its last action. This is useful, since it allows the compiler to reduce the space complexity of the method (see explanation). Essentially, the compiler transforms the method to simple iteration, eliminating the need for accumulating stack frames.
Appendix: The only way I can see to keep constraint (2) is to print the number of digits in Base 1, since each digit taken from the argument corresponds directly to a single character in Base 1). This probably isn't what you meant, but here's a solution:
// The accumulator starts at 0, then increases by 1 for each recursive call
void numOfDigits(unsigned int num) {
if (num == 0) return;
else {
cout << 1
numOfDigits(num / 10);
}
}
N.B. This method will not print anything for numOfDigits(0)
, which is necessary if we want to keep the line if (num == 0) return;
Upvotes: 0
Reputation:
You can pass a value by reference and make use of it, initialize ans=0
every time you call this function
void recursive(unsigned int num,int &ans){
if(num == 0){
return;
}
else{
ans++;
recursive(num/10,ans);
}
}
Upvotes: 1
Reputation: 356
You have a number of mistakes in the numOfDigits() function.
As you are printing size at the end of the function, it simply gives the value of the size variable after that function is run. Even if you set size as static, you will also print the intermediate values of size. An easy way to fix this is to allow the function to return size, and you would have to simply print the value of the function in the main function.
#include <iostream>
#include <string.h>
using namespace std;
int numOfDigits(unsigned int num);
int main(){
int num = 994;
cout<<numOfDigits(num);
}
int numOfDigits(unsigned int num)
{
static int size = 1;
if (num==0)
return 0;
else
{
if (num / 10 != 0)
size++;
numOfDigits(num / 10);
}
return size ;
}
Make sure to put the case with (num == 0) as you want; in this case it prints 0 as the answer.
PS: Always put a space after printing numbers. Otherwise you might think that 1 2 2 (which are the numbers actually printed) is the number 122.
Upvotes: 1
Reputation: 774
try this code :
int numOfDigits(unsigned int num)
{
int size = 1;
if (num!=0)
{
if (num / 10 != 0)
size+= numOfDigits(num / 10);
}
return size;
}
use the return value in your main function
Upvotes: 0
Reputation: 3902
I think your misunderstanding is that you assume that size
is one single variable. However, in every call of your function, you have a different one. Also, every call of your function will print it again.
The cout
in your main does nothing, since it prints a void, which has no content.
Usually, you'd give it a return parameter that is the accumulated number, like
int numOfDigits(unsigned int num);
void main(){
cout << numOfDigits(994) << endl;
}
If you don't want that for some reason, you could do it by reference:
int numOfDigits(unsigned int num, unsigned int& digits);
void main(){
unsigned int digits;
numOfDigits(994,digits);
cout << digits << endl;
}
but that is not that good.
That said, in terms of style, what I would do is either making it a loop (idea is that you want to avoid recursion most times):
unsigned int numOfDigits(unsigned int num){
if(num == 0) { return 1; }
unsigned int size = 0;
while(num != 0){
size++;
num /= 10;
}
return size;
}
which can be also done with a call by reference return value. But again, that is somewhat strange if not necessary.
You might even make it a one-liner by using mathematics, cout << floor(log_10(num)) << endl;
(not accounting for the special case if num is zero)
One solution that would also work is to make size a global variable. However, I'd advice against that. Global variables should be avoided in general. Just wanted to mention it if somebody else recommends it.
Lastly, you could go with a class, like DigitsCounter
that is usually short lived and does the recursive call on methods, with the size variable being a class member. That is overkill in your case, though.
Upvotes: 0
Reputation: 1123
#include <iostream>
#include <string.h>
using namespace std;
void numOfDigits(unsigned int num);
void main(){
int num = 994;
int size = 1;
cout << numOfDigits(num, size);
}
void numOfDigits(unsigned int num, int &size)
{
if (num==0)
cout<<size;
else
{
if (num / 10 != 0)
size++;
numOfDigits(num / 10, size);
}
}
Upvotes: 0
Reputation: 1413
try declaring size globally because it was intialized every time when the funtion executes
int size = 1;
void numOfDigits(unsigned int num)
{
if (num==0)
return;
else
{
if (num / 10 != 0)
size++;
numOfDigits(num / 10);
}
}
print value of size inside main
Upvotes: 0
Reputation: 1395
Without using any global variable, this code works. Just a little note: you declared unsigned int the argument, but the number you give to the function is a signed integer.
#include <iostream>
#include <string.h>
using namespace std;
void numOfDigits(unsigned int num, unsigned int& digits);
int main(){
unsigned int num = 93934;
unsigned int digits = 1;
numOfDigits(num, digits);
cout <<digits <<endl;
return 0;
}
void numOfDigits(unsigned int num, unsigned int& digits) {
if (num==0){
return;
}else{
if (num / 10 != 0){
++digits;
numOfDigits(num / 10, digits);
}
}
}
Upvotes: 0