Executando verificação de segurança...
3

bill é diferente de bill_amount, tax é diferente de tax_percent e tip é diferente de tip_percent.

Os nomes dos parâmetros de uma função só existem dentro da função. Fora dela, o que importa é que ela receba uma expressão que resulte em um valor que ela espera receber.

Só para dar um exemplo, eu poderia chamar a função assim:

half(100, 6.25, 18);

Ou seja, em vez de ter variáveis, eu posso muito bem chamar a função passando os valores numéricos diretamente. Claro que para o exercício não serve, mas tecnicamente falando, nada impede que eu faça isso. E ao chamar desta forma, o valor 100 será atribuído ao parâmetro bill_amount, o valor 6.25 será atribuído ao parâmetro tax_percent, e 18, a tip_percent.

Os nomes só existem dentro da função. Fora dela, quem for chamá-la, pode passar qualquer coisa, desde que o resultado seja compatível com os tipos que ela espera.

Tanto que eu também poderia fazer algo assim:

half(valor_batata + valor_cervejas + valor_hamburguer, calcular_taxa_do_dia(), ler_valor_gorjeta());

Assumindo que todas as variáveis valor_batata, valor_cervejas e valor_hamburguer e as funções calcular_taxa_do_dia e ler_valor_gorjeta existam e seus tipos sejam compatíveis com o que a função half espera.

Resumindo, uma coisa são os nomes dos parâmetros, que só existem dentro da função. Outra coisa são os valores dos argumentos que passamos para a função ao chamá-la. Estes podem ser quaisquer expressões (nem precisam ser variáveis), desde que os tipos sejam compatíveis com os respectivos parâmetros. Ou seja, as variáveis que vc leu no main não precisam necessariamente ter os mesmos nomes dos parâmetros definidos na função.


Por fim, a função poderia ser simplificada, pois não vejo a necessidade de tantas variáveis intermediárias:

float half(float bill, float tax, int tip) {
    float tax_multiplier = 1 + (tax / 100);
    float tip_multiplier = 1.0 + (tip / 100.0);
    return (bill * tax_multiplier * tip_multiplier) / 2;
}

No caso do tax_multiplier, como tax é um float, toda a expressão resultará em um float. Já tip é um int, então eu preciso dividir por 100.0 (o .0 no final força que toda a expressão seja float, evitando o arredondamento que ocorreria se eu dividisse por 100, já que este é um literal inteiro).


Ou ainda, caso seja permitido criar funções auxiliares:

// converte um valor de porcentagem para o respectivo multiplicador (ex: 6.5 vira 1.065)
float convert_perc(float perc) {
    return 1.0 + (perc / 100.0);
}

float half(float bill, float tax, int tip) {
    return (bill * convert_perc(tax) * convert_perc(tip)) / 2;
}
Carregando publicação patrocinada...
2

Boa noite, obrigado por responder!

Outra coisa são os valores dos argumentos que passamos para a função ao chamá-la

Então, por exemplo, fatura (ou bill) pode receber mais de um argumento (valor_batata + valor_cerveja + valor hamburguer)? Neste exercício em específico, seria necessário criar uma função que calcule esses três argumentos ou apenas substituindo valor_batata + valor_cerveja + valor hamburguer por algum valor (10.0 + 12.0 + 25.0, por exemplo) no half funcionaria?

Por fim, a função poderia ser simplificada

Isso é mesmo, percebi quando estava dando erro na compilação e precisei pesquisar para ver o que estava errado. Muitos dos códigos estavam mais simplificados que o meu, mas com o tempo irei melhorando. O importante é não desistir e sempre continuar estudando.

Obrigado e bom domingo!

2

pode receber mais de um argumento (valor_batata + valor_cerveja + valor hamburguer)

Não é "mais de um argumento", é um só. Mas vamos por partes.

A função foi definida assim:

float half(float bill, float tax, int tip) {
    // etc...
}

Ou seja, ela possui três parâmetros: o primeiro é um float e o nome é bill, o segundo também é float e o nome é tax, e o terceiro é um int chamado tip.

Agora, de onde vêm esses valores? Isso é algo definido por quem for chamar a função.

Por exemplo, se eu chamo a função assim:

half(100, 6.25, 18);

Repare que os argumentos são separados por vírgula. Ou seja, os três argumentos são os números 100, 6.25 e 18.

E como o primeiro argumento é 100, este é o valor que será colocado em bill.

Agora, se eu chamo a função assim:

half(valor_batata + valor_cervejas + valor_hamburguer, 2.5, 10);

Ainda são três argumentos separados por vírgula. O segundo é 2.5 e o terceiro é 10.

E o primeiro argumento? Ele é toda a expressão valor_batata + valor_cervejas + valor_hamburguer. Não são vários argumentos, é um só. E o resultado desta expressão é o valor que será colocado em bill.

Isso quer dizer que primeiro ele calcula a expressão (no caso, soma os 3 valores), e só depois o resultado é passado para a função. Seria o equivalente a fazer isso:

float total = valor_batata + valor_cervejas + valor_hamburguer;
half(total, 2.5, 10);

Mas neste caso eu optei por não usar a variável total, e em disso passar o resultado da soma diretamente para a função.

Claro, tudo isso assumindo que as variáveis existem e possuem valores adequados. Mas o ponto aqui é que continua sendo um único argumento. Só que não precisa ser necessariamente uma variável: ele pode ser qualquer expressão válida, desde que o resultado seja um valor de um tipo compatível com o que a função espera.

2

Isso quer dizer que primeiro ele calcula a expressão (no caso, soma os 3 valores), e só depois o resultado é passado para a função.

Sua explicação fez sentido para mim, obrigado.

Agora é só continuar praticando...