问题是,假设找回的硬币数量为25c,10c,5c和1c,则找到找零给定金额的硬币的最小数量。
我用C实现了递归的解决方案,但是不知何故它不断抛出“错误:控件可能到达非void函数的结尾”。我是C语言的新手,所以我不太清楚发生了什么。 任何帮助是极大的赞赏!这是我的代码:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int processChange(float change){
int centsChange = round(change*100);
int arr[4] = {25,10,5,1};
for(int i=0;i<4;i++){
int numCoins =0;
int remainder = centsChange%arr[i];
if(remainder==0){
numCoins = (centsChange - remainder)/arr[i];
return numCoins;
}
if(centsChange ==1){return 1;}//base case
if(centsChange>=arr[i]){
numCoins = (centsChange - remainder)/arr[i]+ processChange(remainder/100);
return numCoins;
}
}
}
int main(){
float change;
do
{
change = get_float("Enter the changed owed\n");
}while (change<0);
printf("Minimum number of coins returned is %d\n", processChange(change));
}
答案 0 :(得分:3)
for
中processChange
循环中的代码执行以下操作:
remainder
为零,请进行计算并返回。centsChange
为1,则返回。centsChange
至少为arr[i]
,请进行计算并返回。for
循环的结尾并继续进行迭代。据编译器所知,i
的值将达到4,并且控制将离开for
循环。那时,控制将流到该函数的末尾,那里没有return
语句。因此,编译器警告您控件将到达非空函数的末尾。 (“非无效函数”是返回类型不是void
的函数。processChange
的返回类型是int
。)
解决此问题的一种方法是在函数末尾插入return
语句。
另一种方法是针对这种情况禁用编译器警告,您可以使用-Wno-return-type
命令行开关对GCC和Clang进行此操作。
我们可以看到控件实际上无法离开for
语句,因为当i
为3时,arr[i]
为1,因此centsChange % arr[i]
必然产生零,并对其进行赋值到remainder
,导致代码流入上述第一种情况。使用GCC和Clang,您可以通过在函数的最后一条语句中插入__builtin_unreachable();
来通知编译器。这告诉编译器,程序中各种情况的组合都无法在逻辑上达到代码中的这一点。 (当控件不是正确的位置时使用此编译器功能,将破坏程序。)
请注意,由于上述原因,控制无法离开for
循环这一事实意味着centsChange == 1
基本情况是不必要的。 remainder == 0
必须必须满足的事实意味着它可以作为基本情况。
尽管此分析按原样讨论了代码,但是经验丰富的程序员将对代码进行重组,因此上述解决方案都不是必需的。有时,各种复杂性会促使我们使用代码,而编译器无法推断出执行中从未达到某个特定点,但我们知道确实如此,在这种情况下可以使用上述变通方法。但是,这不是其中之一。该代码非常简单,可以进行重组,从而使控制流对于编译器而言更加简单和明显。