[英]How can I fix the 'end of non-void function' for my minimum coins owed in change?
问题是,假设找回的硬币数量为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));
}
processChange
中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();
来通知编译器__builtin_unreachable();
作为函数中的最后一条语句。 这告诉编译器,程序中各种情况的组合都无法在逻辑上达到代码中的这一点。 (如果不是真的,控件无法到达该位置,则使用此编译器功能将破坏程序。)
注意,由于上述原因,控件无法离开for
循环这一事实意味着centsChange == 1
基本情况是不必要的。 必须在某些时候满足remainder == 0
的事实,这意味着它可以作为基本情况。
尽管此分析按原样讨论了代码,但是经验丰富的程序员将对代码进行重组,以使上述解决方案都不是必需的。 有时,各种复杂性会促使我们使用代码,而编译器无法推断出执行中从未达到某个特定点,但我们知道确实如此,在这种情况下可以使用上述变通方法。 但是,这不是其中之一。 该代码非常简单,可以进行重组,以使控制流对于编译器而言更加简单和明显。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.