A questão mais óbvia do seu código é que todos os while
loops verificam uma variável (por exemplo, $quarter
) que nunca é alterada dentro do loop, portanto a condição de loop nunca pode se tornar falsa e o loop se repete indefinidamente. p>
Vamos dar uma olhada em um dos loops:
while [ $quarter -ge 0 ]
do
qNum=$(( qNum+1 ))
amount=$(( $amount-25 ))
done
Se $quarter
> 0, o fluxo de controle entra no loop, $qNum
é incrementado e $amount
é decrementado, mas $quarter
permanece inalterado, então você está em outra iteração de loop.
Corrigir seu código funciona melhor reestruturando-o:
-
Em vez de confiar em variáveis globais como
amount
, que são definidas como efeitos colaterais de funções, reescreva suas funções para aceitar parâmetros e exibir seus resultados emstdout
(quando possível).-
Resultados para
stdout
: Sua funçãogetamt()
poderiaecho $amount
em vez de depender deamount
estar disponível (e inalterado) para processamento posterior no script. Quaisquer chamadasgetamt
podem capturar essa saída em uma variável comamount=$(getamt)
.
Infelizmente, isso não funciona tão bem quando uma função precisa retornar vários valores - nesse caso, você pode fazer com que a função imprima seus valores de retorno separados por novas linhas ou um caractere que você sabe que não aparecerá nos valores. Você pode até ir para um formato de saída comoquarter=3 dime=1 nickel=4
e avalie essa saída para definir variáveis locais com os valores de retorno da função:
$(yourfunction); echo $quarter
-
Parâmetros: Sua função
change()
poderia receber a quantidade de alterações que deveria calcular como um parâmetro (ou seja, você chamariaamount 2.50
) em vez de lê-la a partir de uma variável global. Você pode acessar parâmetros dados à sua função (ou ao seu script, dependendo do contexto) através de seus índices:$1
para o primeiro parâmetro,$2
para o segundo, etc.
-
-
Você pode evitar algumas chamadas para
bc
apenas cortando as casas decimais uma vez e usando apenas a avaliação aritmética bash depois disso. Sua substituição atual${quarter%???}
também remove qualquer últimos três caracteres, o que produzirá resultados indesejados se os usuários decidirem inserir um valor com mais (ou menos) do que duas casas decimais. Use algo como${quarter%%.*}
para remover tudo após (e incluindo) o primeiro.
. -
Use comentários (iniciado com
#
e continuado até o final da linha):
por exemplo.amount=${amount%%.*} # remove decimal places
A maior parte do seu código parecerá óbvia para você agora, mas pode não ser óbvia para qualquer outra pessoa que esteja olhando para ele, e também não será mais óbvio para você quando você precisar vê-lo novamente em alguns meses . -
Para ser honesto, não sei ao certo como o seu script deve calcular o número de moedas a serem devolvidas no momento. A abordagem mais comum para calcular a mudança seria um algoritmo guloso que começa no valor de moeda mais alto disponível, dispensa tantas moedas desse valor como "adequado" à quantia de alteração 1 , subtrai o valor total dessas moedas do valor da alteração, depois continua com o valor da moeda seguinte (menor) e assim por diante, até que o valor da alteração atinja 0 (ou seja, moedas suficientes foram distribuídas para compensar o valor total da alteração)
1 Para calcular esse número de moedas, você pode consultar modulo operations ou apenas subtrai o valor atual da moeda do valor da mudança em um loop até que a quantia da alteração seja menor que o valor da moeda (ou seja, você retornaria muita alteração se dispensasse outra moeda da corrente valor).