2022 CS50 Cash贪心算法硬币计数与手动计算结果不符问题
问题原因
你所有计算单种硬币数量的函数都误用了do...while循环,这是结果偏大的核心原因。do...while的执行逻辑是先跑一次循环体内的代码,再判断循环条件是否成立:哪怕传入的剩余金额已经小于当前硬币面值,也会先扣减一次面值、给硬币计数+1,再判断要不要退出循环,相当于每种硬币都平白多算了1枚。
我们可以拿你给的两个测试用例验证逻辑:
- 输入5美分时:
- 计算25美分硬币:初始值5<25,但do-while会先扣25得到-20,计数1个quarter,再判断不满足循环条件退出
- 后续计算10美分、5美分、1美分的时候,同样因为do-while的特性各多算1枚,最终总和1+1+1+1=4,和你实际输出一致
- 输入160美分时:
- 计算25美分硬币:160最多能换6个25(共150),剩10的时候本应停止,但do-while会再扣一次25得到-15,计数7个quarter
- 后续10美分、5美分各多算1枚,1美分阶段剩余值已经是负数不会触发多算,最终总和7+1+1+0=9,和你实际输出一致
修复方案
二选一即可:
- 把所有计算硬币的
do...while循环改成普通while循环,先判断剩余金额够不够兑换当前硬币,够的话再扣减、计数,避免多算。
以25美分计算函数为例,修改后代码:
int calculate_quarters(int cents) { int quarters = 0; // 先判断金额是否足够,再执行循环逻辑 while (cents >= 25) { cents = cents - 25; quarters++; } return quarters; }
其余calculate_dimes、calculate_nickels、calculate_pennies函数按同样逻辑修改,判断条件分别对应>=10、>=5、>=1即可。
2. 更简洁的写法:不需要写循环,直接用C语言整数除法的特性计算硬币数量——整数相除会自动向下取整,直接返回cents / 硬币面值就是可兑换的最大硬币数,代码更短也不会出现循环逻辑错误。
比如25美分的计算可以直接写成:
int calculate_quarters(int cents) { return cents / 25; }
额外小问题:你的get_cents函数循环条件写的是cents <=0,输入0的时候会被判定为无效值要求重新输入,按照题目要求找零为0时应该返回0枚硬币,建议把条件改成cents < 0。
内容的提问来源于stack exchange,提问作者traveelta
相关产品推荐
相关产品推荐

