Vamos escrever uma nova versão do programa de cálculo do IMC. Desta vez queremos algo ligeiramente mais sofisticado, que permite calcular o IMC de várias pessoas. O utilizador terá que introduzir o peso e a altura de cada pessoa e o programa indicará, para além do IMC, uma mensagem indicando se o pesso está com excesso de peso ou não. Este programa é evidentemente um pretexto para rever a matéria vista até agora.
Para cada pessoa, o programa deve dar uma dessas quatro indicações conforme o valor do IMC :
- Peso baixo = IMC inferior a 18.5
- Peso normal = IMC entre 18.5 e 24.9
- Peso a mais = IMC entre 25 e 29.9
- Obesidade = IMC igual a 30 ou mais
O programa deverá funcionar da seguinte maneira :
> ./imc
Indique o peso da pessoa : 45
Indique a altura da pessoa : 1.60
Indice de Massa Corporal: 17.578125 Peso baixo.
Quer continuar ? (s/n) : s
Indique o peso da pessoa : 79.5
Indique a altura da pessoa : 1.80
Indice de Massa Corporal: 24.537039 Peso normal.
Quer continuar ? (s/n) : n
>
O objectivo é de mostrar como deve racocinar para desenvolver um programa. A primeira regra é que não deve tentar resolver todos os problemas de uma vez. Deve proceder de forma progressiva ou, mais precisamente de forma iterativa. Deve começar com um programa extremamente simples e verificar logo que funciona. Este programa resolverá apenas uma pequena parte do problema mas uma vez esta parte resolvida poderá concentrar-se numa outra parte do problema.
A ideia é velha como o mundo : dividir para reinar. Partindo o problema em problemas mais pequenos, mais simples que resolverá um a um é uma estratégia vencedora. Em cada iteração acrescenta-se uma nova funcionalidade ao programa. É muito importante testar o programa após cada incremento. O teste significa que vamos verificar que o programa funciona como é suposto, que os resultados (mesmo parciais) são correctos.
Uma coisa que o programador deve aprender é a humildade ! deve aprender a desconfiar dele próprio e verificar que cada passo do programa funciona como previsto. Com a experiência uma pessoa ganha confiancia mas sempre encontrará uma situação onde precisará de humildade para por exemplo encontrar a causa de um erro.
Vamos, usando o exemplo do programa de cálculo do IMC expor todas as iterações que nos vão levar até o programa final. É aconselhado executar esses passos no seu computador, editando, compilando e testando o programa como está descrito aqui.
Para começar, vamos usar como base o programa dado na secção Estrutura de programas básicos :
int main (void) {
return 0;
}
e compila-lo :
> gcc imc.c -o imc
Pode executar o programa para verificar que o executável foi efectivamente gerado :
> ./imc
Se chegou até aqui sem obter nenhuma mensagem de erro significa que já sabe editar um programa, que tem o
gcc correctamente instalado e que sabe como compilar o programa e executa-lo. Em caso de problema num dos passo anteriores, pode : consultar a secção para ver como editar e compilar um programa.
Sabemos que vamos precisar de imprimir uma mensagem no ecrã para indicar ao utilisador quais são os valores que deve introduzir. Podemos acrescentar uma instrução printf :
int main (void) {
printf("Indique o peso da pessoa : ");
return 0;
}
e compilar o programa :
> gcc imc.c -o imc
imc.c: In function 'main':
imc.c:2: warning: incompatible implicit declaration of built-in function 'printf'
Um primeiro erro ! Se obteve este erro é que não esteve atento à todas as indicações da secção sobre
a função printf ! Pode procurar a mensagem de erro
aqui.
Uma vez corrigido o erro o programa deve escrever as duas mensagens :
> ./imc
Indique o peso da pessoa :
Podemos agora tratar da leitura do valor, usando a função scanf :
1 #include <stdio.h>
2
3 int main (void) {
4 int peso = 0.0;
5 printf("Indique o peso da pessoa : ");
6 scanf("%f", &peso);
7 printf("peso = %f\n", peso);
8 return 0;
9 }
Note na linha 7 o
printf que tem como único objectivo de verificar se a leitura do valor do peso funcionou.
Sempre que for necessário, deve acrescentar temporariamente instruções para verificar o funcionamento do programa.
Agora testamos o programa :
> gcc imc.c -o imc
> ./imc
Indique o peso da pessoa : 67.2
peso = -0.016688
Isto não é o resultado esperado. Olhando atentamente para o programa podemo ver que tem um erro. A variável
peso está declarada como
int mas as instruções
scanf e
printf esperam um
double ou um
float. É preciso aprender com os erros :
- É preciso prestar especial atenção ao tipo das variáveis. Um engano relativamente ao tipo de uma variável pode dar resultados errados que são à primeira vista inexplicaveis.
- Os erros de tipo não são sempre detectados pelo compilador.
- Pode haver erros nas instruções que são supostas permitir verificar o bom funcionamento do programa (aqui no
printf) !
O leitor atento terá notado que não usamos as opções da linha de comando recomendadas na secção Compilar e executar para a compilação. Usando essas recomendações teriamos obtido avisos relativaos ao problema do tipo da variável peso :
> gcc imc.c -o imc -ansi -Wall
imc.c: In function 'main':
imc.c:6: warning: format '%f' expects type 'float *', but argument 2 has type 'int *'
imc.c:7: warning: format '%f' expects type 'double', but argument 2 has type 'int'
Conclusão : se não usar a opção
-Wall pode perder muito tempo com erros triviais.
Vamos resolver o problema usando o tipo float para representar o peso :
#include <stdio.h>
int main (void) {
float peso = 0.0;
printf("Indique o peso da pessoa : ");
scanf("%f", &peso);
printf("peso = %f\n", peso);
return 0;
}
Compilação e teste :
> gcc imc.c -o imc -ansi -Wall
> ./imc
Indique o peso da pessoa : 67.2
peso = 67.199997
O programa funciona correctamente (quem estiver surpreendido pelo facto de aparecer 67.199907 e não 67.2 pode consultar
esta secção).
Neste ponto foi resolvido o problema da leitura dos dados. Extender à leitura da altura da pessoa é agora trivial :
#include <stdio.h>
int main (void) {
float peso = 0.0;
float altura = 0.0;
printf("Indique o peso da pessoa : ");
scanf("%f", &peso);
printf("peso = %f\n", peso);
printf("Indique a altura da pessoa : ");
scanf("%f", &altura);
printf("altura = %f\n", altura);
return 0;
}
Compilação e teste :
> gcc imc.c -o imc -ansi -Wall
> ./imc
Indique o peso da pessoa : 67.2
peso = 67.199997
Indique a altura da pessoa : 1.78
altura = 1.780000
Podemos agora incluir o cálculo do IMC :
#include <stdio.h>
int main (void) {
float peso = 0.0;
float altura = 0.0;
printf("Indique o peso da pessoa : ");
scanf("%f", &peso);
printf("Indique a altura da pessoa : ");
scanf("%f", &altura);
printf("Indice de Massa Corporal: %f\n",
peso / (altura * altura));
return 0;
}
Compilação e teste :
> gcc imc.c -o imc -ansi -Wall
> ./imc
Indique o peso da pessoa : 67.2
Indique a altura da pessoa : 1.78
Indice de Massa Corporal: 21.209443
O objectivo do programa é indicar se a pessoa está com excesso de peso. Conforme o valor do IMC a mensagem a imprimir no ecrã será diferente. Isto é uma indicação que é necessário usar a instrução if. Os diferentes casos são :
- Peso baixo = IMC inferior a 18.5
- Peso normal = IMC entre 18.5 e 24.9
- Peso a mais = IMC entre 25 e 29.9
- Obesidade = IMC igual a 30 ou mais
Podemos traduzir essas condições em C :
if (imc < 18.5) printf("Peso baixo.\n");
if ((imc >= 18.5) && (imc < 25)) printf("Peso normal.\n");
if ((imc >= 25) && (imc < 30)) printf("Peso a mais.\n");
if (imc >= 30) printf("Obesidade.\n");
O programa fica portanto assim:
#include <stdio.h>
int main (void) {
float peso = 0.0;
float altura = 0.0;
printf("Indique o peso da pessoa : ");
scanf("%f", &peso);
printf("Indique a altura da pessoa : ");
scanf("%f", &altura);
float imc = peso / (altura * altura);
printf("Indice de Massa Corporal: %f ", imc);
if (imc < 18.5) printf("Peso baixo.\n");
else if ((imc >= 18.5) && (imc < 25)) printf("Peso normal.\n");
else if ((imc >= 25) && (imc < 30)) printf("Peso a mais.\n");
else if (imc >= 30) printf("Obesidade.\n");
return 0;
}
Note que agora para testar o programa temos que prever os quatro casos. Torna-se fastidioso entrar ao teclado tantas informações cada vez que queremos testar o programa. Felizmente existe uma maneira de simplificar o processo. Basta escrever num ficheiro as entradas (ou seja o que aparece em azul nas interacções com o programa). Por exemplo podemos gravar :
67.2
1.78
num ficheiro chamado
entrada1.txt. A seguir, o teste do programa pode ser feito assim :
> ./imc < entrada1.txt
Indique o peso da pessoa : Indique a altura da pessoa : Indice de Massa Corporal: 21.209442 Peso normal.
As mensagens emitidas pelo programa aparecem todas seguidas dado que as entradas são tiradas do ficheiro
entrada1.txt. A vantagem de preceder assim é que basta uma linha para realizar um teste do programa. Podemos ter vários ficheiros de entrada para testar vários casos. Ao ficheiro
entrada2.txt100
1.60
corresponderá uma situação de obesidade. Ao ficheiro
entrada3.txt50
1.80
uma situação de peso baixo e à
80
1.78
(
entrada4.txt) um peso a mais. O programa pode agora ser testado facilmente :
> ./imc < entrada1.txt
Indique o peso da pessoa : Indique a altura da pessoa : Indice de Massa Corporal: 21.209442 Peso normal.
> ./imc < entrada2.txt
Indique o peso da pessoa : Indique a altura da pessoa : Indice de Massa Corporal: 39.062500 Obesidade.
> ./imc < entrada3.txt
Indique o peso da pessoa : Indique a altura da pessoa : Indice de Massa Corporal: 15.432099 Peso baixo.
> ./imc < entrada4.txt
Indique o peso da pessoa : Indique a altura da pessoa : Indice de Massa Corporal: 25.249338 Peso a mais.
O programa está por enquanto a dar resultados correctos.
O cálculo do IMC deve ser repetido para várias pessoas até que o utilizador indique que quer terminar o programa. Repetição implica uma instrução de ciclo. O número de repetições é desconhecido (depende do utilizador) portanto o ciclo de tipo for está excluído. Temos de decidir entre o ciclo do .. while e o ciclo while .... Podemos assumir que o utilizador quer calcular o IMC pelo menos uma vez (caso contrário porque usar o programa ?). Se o cálculo do IMC reside no corpo do ciclo e é sempre feito pelo menos uma vez a instrução de ciclo mais adaptada é o ciclo do ... while.
Temos de decidir qual será a condição de paragem do ciclo. Como vimos será o utilizador a decidir quando o programa termina. Temos portanto que perguntar ao utilizador, após cada calculo de IMC se quer continuar. A resposta será colocada numa variável (chamada continuar) de tipo char e o seu valor será 's' (sim) ou 'n'(não). O ciclo será portanto do tipo :
do {
...
} while (continuar == 's');O programa está agora assim :
1 #include <stdio.h>
2
3 int main (void) {
4 float peso = 0.0;
5 float altura = 0.0;
6 char continuar = '?';
7
8 do {
9 printf("Indique o peso da pessoa : ");
10 scanf("%f", &peso);
11 printf("Indique a altura da pessoa : ");
12 scanf("%f", &altura);
13 float imc = peso / (altura * altura);
14 printf("Indice de Massa Corporal: %f ", imc);
15 if (imc < 18.5) printf("Peso baixo.\n");
16 else if ((imc >= 18.5) && (imc < 25)) printf("Peso normal.\n");
17 else if ((imc >= 25) && (imc < 30)) printf("Peso a mais.\n");
18 else if (imc >= 30) printf("Obesidade.\n");
19 printf("Quer continuar ? (s/n) : ");
20 scanf("%c", &continuar);
21 } while (continuar == 's');
22 return 0;
23 }
Após compilação o teste dá o seguinte :
> ./imc
Indique o peso da pessoa : 55
Indique a altura da pessoa : 1.6
Indice de Massa Corporal: 21.484375 Peso normal.
Quer continuar ? (s/n) : >
O programa terminou sem aceitar um valor a seguir à pergunta «Quer continuar ?». O que é que aconteceu ? A função scanf é chamada a seguir ao printf (linha 20) mas o programa ternimou sem aceitar um valor.
Aconteceu um erro que já foi analisado na secção sobre a função scanf. Substituindo a linha 20 por :
scanf(" %c", &continuar);
o programa funciona correctamente.