为了学习递归,我想计算组成整数的小数位数。因此,出于教学目的,我不想使用math.h
中的函数,如下所示:
我尝试了两种方法,基于假设10
整数除以某个点会产生0
。
第一个正常工作。 count2(1514, 1)
返回4
:
int count2(int n, int i){
if(n == 0)
return 0;
else
return i + count2(n / 10, i);
}
但我想理解这一行为:
int count3(int n, int i){
if(n / 10 != 0)
return i + count3(n / 10, i);
}
例如,从count3(1514, 1);
开始,我希望如此:
1514 / 10 = 151; # i = 1 + 1
151 / 10 = 15; # i = 2 + 1
15 / 10 = 1; # i = 3 + 1
1 / 10 = 0; # Stop!
出乎意料的是,该函数返回13
而不是4
。这个功能不应只递归3次吗?同一类count2()
的基本案例的实际必要性是什么?
答案 0 :(得分:3)
如果您未提供return
语句,则结果不确定。
在大多数架构中,这意味着您的函数会返回恰好存在于堆栈或服务寄存器中的随机数据。
因此,count3()
函数在n / 10 == 0
时返回随机数据,因为没有对应return
语句。
编辑:必须强调的是,大多数现代编译器都能够在类型化函数未覆盖return
语句的所有出口点时发出警告。
例如,GCC 4.9.2将默默接受缺失的return
。但是如果你提供-Wreturn-type
编译器开关,你将收到'警告:控制到达非空函数[-Wreturn-type] '警告消息的结尾。相比之下,Clang 3.5.0 默认会给你一个类似的警告信息:'警告:控件可能会到达非空函数的末尾[-Wreturn-type] ”。我个人尝试使用-Wall -pedantic
,除非有些第三方强迫我禁用某些特定的开关。
答案 1 :(得分:3)
在递归中应该有基本条件,这是递归解决方案的构建块。在n==0
时,您的递归基础不会返回任何值 - 因此返回的值是不确定的。所以你的递归count3
失败了。
答案 2 :(得分:2)
在值返回函数中不返回值是未定义行为。你应该对这种行为发出警告 你的逻辑也错了。当`(n> = 0&& n / 10 == 0)和
时,你必须返回1if(n / 10 != 0)
return i + count3(n / 10, i);
else if (n >= 0) return 1;
else return 0;
答案 3 :(得分:0)
我认为你在递归时不需要 i + count()。只需 1 + count()即可正常工作......
#include <stdio.h>
#include <stdlib.h>
static int count(), BASE=(10);
int main ( int argc, char *argv[] ) {
int num = (argc>1?atoi(argv[1]):9999);
BASE= (argc>2?atoi(argv[2]):BASE);
printf(" #digits in %d(base%d) is %d\n", num,BASE,count(num)); }
int count ( int num ) { return ( num>0? 1+count(num/BASE) : 0 ); }
......似乎对我来说很好。例如,
bash-4.3$ ./count 987654
#digits in 987654(base10) is 6
bash-4.3$ ./count 123454321
#digits in 123454321(base10) is 9
bash-4.3$ ./count 1024 2
#digits in 1024(base2) is 11
bash-4.3$ ./count 512 2
#digits in 512(base2) is 10