Você está na página 1de 45

Fundamentos de Programação em C: Uma Abordagem Algorítmica

Capítulo
7 Subprogramas
“ Não se mede o valor de um homem pelas suas roupas ou pelos seus bens, o verdadeiro valor de um
homem é o seu carácter, suas ideias e a nobreza de seus ideais. ”

- Charles Chaplin -

6.1 Conceitos
Entendemos por subprogramas, um segmento de código com uma estrutura
muito semelhante à de um programa, que tem por objectivo resolver um
problema específico, e que é executado quando for acionado po invocado por
um outro programa.

Os subprogramas são utilizados para separar um programa em partes


logicamente coerentes, e devem possuir as seguintes propriedades:

Realizar uma única tarefa;


O seu código deve ser o mais independente e genérico possível;
Possuir um mecanismo de comunicação com o exterior.

Em termos gerais, um programa pode ser constituído por um conjunto de


subprogramas logicamente coerentes, e por um programa principal para juntar
esses subprogramas.

A comunicação entre o programa principal e os restantes subprogramas é feita


da seguinte maneira: o programa principal envia para os subprogramas dados,
com esses dados os subprogramas realizam tarefas, e ao terminarem, devolvem
ao programa principal um resultado que a partida deve estar correcto.

Todo o subprograma deve ser identificado por um nome, que obedece as regras
de construção de identificadores, para além disso, o nome de um subprograma
deve mostrar de forma inequívoca a tarefa que esse subprograma realiza.

Segundo Deitel (2011) “Se não conseguirmos escolher um nome conciso para
um determinado subprograma, é porque este subprograma realiza muitas tarefas
diferentes, e a melhor solução, consiste em fragmenta-lo em subprogramas mais
simples”.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 174


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Fazem parte das boas práticas de programação desenvolver programas como


um conjunto de pequenos subprogramas independentes entre si.

Qualquer sequência de instruções que aparece mais do que uma vez num
programa deve ser implementada como um subprograma.

Como funcionam os subprogramas? Um subprograma só é executado quando


for acionado em alguma parte do programa principal. Nessa altura, o programa
principal é suspenso, e o fluxo de controlo de execução do programa é
transferido para o subprograma. O subprograma começa a ser executado e uma
vez terminado, transfere o fluxo de execução do programa para o local onde foi
suspenso, e continua a sua execução.

Na linguagem C, os subprogramas são chamados de funções, e o subprograma


principal é chamado de função principal, por esse motivo, este tipo de
programação é chamada de programação com funções.

Segundo Deitel (2011), “ A quantidade de linhas de código de qualquer função,


não deve ser maior do que meia página. Essa prática de programação facilita a
reutilização do software”.

6.2 Estrutura de um Programa


Na linguagem C, um programa com funções deve possuir a seguinte estrutura.

Directivas de pré-processamento
Protótipo de funções
Definição de funções
Função principal

que será estudada em detalhe nas próximas secções, com excepção das
directivas de pré-processamento, que já foram vistas num dos capítulos
anteriores.

6.3 Definição de Funções


A Definição de Funções é uma área do programa onde o programador irá
desenvolver as suas funções. Toda a função possui à seguinte sintaxe:

tipo nome (Declaração dos parâmetros)


{
Declaração dos identificadores;
Comandos da função;
Valor de retorno;
}

onde
tipo: representa um tipo elementar de dados;
nome: uma variável que satisfaz as regras de construção de variáveis;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 175


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Declaração dos parâmetros: são os mecanismos de comunicação da


função com o exterior. Cada parâmetro é identificado pelo seu tipo,
seguido do seu nome e de uma vírgula. Em termos formais:

tipo1 parâmetro1 , tipo2 parâmetro2 , … , tipon parâmetron ;

Declaração dos identificadores: são as variáveis e as constantes que


serão utilizadas na função;
Comandos da função: são as instruções que resolvem um problema
específico;
Valor de retorno será objecto de estudo nas próximas linhas.

Por exemplo, a função: importa um determinado valor em graus Celcius, e


exporta o correspondente valor em graus Fahrenheit.

float fahrenheit (int c) /* cabeçalho da função */


{
float f;
f = 9.0/5.0*c + 32;
return f;
}

importa um determinado valor em graus Celcius, e exporta o correspondente


valor em graus Fahrenheit, enquanto que a função:

int soma (int x, int y) /* cabeçalho da função */


{
float res;
res = x + y;
return res;
}

importa dois valores inteiros x e y e exporta a soma desses valores.

Por definição, uma função é um subprograma que importa vários valores através
dos parâmetros e exporta um e apenas um valor através do valor de retorno.

Os parâmetros que aparecem no cabeçalho de uma função são denominados


por parâmetros formais ou simplesmente por parâmetros.

6.4 Protótipo de Funções


O Protótipo de Funções, é uma área do programa onde o programador declara
as funções que irá utilizar. Esta declaração consiste na definição do tipo de
função e nos parâmetros que ela possui. Por exemplo, no comando:

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 176


Fundamentos de Programação em C: Uma Abordagem Algorítmica

float fahrenheit (int c);

informamos ao compilador, que a função de nome fahrenheit é do tipo real e


possui um parâmetro do tipo inteiro.

A declaração de qualquer função deve terminar com um ponto-e-vírgula.

Fazem parte das boas práticas de programação, declarar no protótipo de


funções, todas as funções que serão utilizadas no programa.

Os nomes dos parâmetros que são incluídos no protótipo de funções, servem


para efeito de documentação e legibilidade, mas o compilador os ignora.

Isso quer dizer, que no protótipo da função fahrenheit(), podemos omitir o


parâmetro c, então, este protótipo pode ser declarado como:

float fahrenheit (int );

6.5 Valor de Retorno


O Valor de Retorno é uma das formas de comunicação da função com o mundo
exterior. Essa comunicação é feita através do comando return, que ao ser
acionado, termina a execução da função, e exporta via valor de retorno, um e
apenas um valor. Este comando possui a seguinte sintaxe:

return;
return expressão;
return (expressão);

Se depois da palavra reservada return, tivermos uma expressão, o valor dessa


expressão será exportado. Logo, podemos utilizar essa propriedade, para
optimizar o código da função fahrenheit().

float fahrenheit (int c)


{
return (9.0/5.0*c + 32);
}

e o código da função soma();

int soma (int x, int y)


{
return ( x + y);
}

Para efeito de notação, utilizaremos a palavra retorna para mostrar que a função
exporta um e apenas um valor através do valor de retorno.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 177


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Embora uma função retorna um e apenas um valor, ela pode conter no seu corpo
vários comandos return, mas apenas um desses comandos será executado. Por
exemplo, a função:

int impar (int numero)


{
if ( numero%2 == 0 )
return 1;
else
return 0;
}

importa um número inteiro, e retorna o valor 1 se o número for par, e 0 no caso


contrário. Como essa função termina quando acionarmos um dos comandos
return, então podemos escrever uma função equivalente com o comando
condicional simples.

int impar (int numero)


{
if ( numero%2 == 0 )
return 1;
return 0;
}

Observação: O tipo de dados de uma função deve ser igual ao tipo de dados
que essa função retorna e não o contrário.

Por exemplo, a função impar() que acabamos de estudar, é do tipo inteiro,


porque retorna o valor 0 ou 1, enquanto a função fahrenheit() que também
estudamos nesta secção, é do tipo real, porque retorna o valor da temperatura
em graus Fahrenheit que é uma grandeza real.

6.6 Função Principal


Na linguagem C, o programa principal, é uma função especial denominada por
função principal, que é determinada pela sentença int main(). Quando essa
sentença for accionada o programa entra em funcionamento.

Constitui um padrão de programação na linguagem C, retornar zeros se o


programa funcionou com sucesso e um outro número no caso contrário.

Fazem parte das boas práticas de programação, implementar a função principal


de forma genérica e deixar para os subprogramas a implementação dos detalhes
da solução.

6.7 Chamada de uma Função


Uma função pode ser accionada por uma função principal ou por uma outra
função.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 178


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Tradicionalmente, a chamada de uma função deve ser feita por um comando de


atribuição de valor. Por exemplo:

float grausFahr;
...

grausFahr = fahrenheit (32); /* Chamada da função */


.

ou, por uma acção de impressão, por exemplo:

printf (" \n Valor em graus Fahrenheit = %.2f ", fahrenheit (32));

Para garantir a troca de informações, na chamada de qualquer função, existe um


mecanismo de ligação entre os parâmetros da chamada e os parâmetros da
função. Esse mecanismo verifica se cada parâmetro da chamada está associado
a um e apenas um parâmetro da função. Para além disso, também verifica se
esses parâmetros são do mesmo tipo, e ocupam a mesma posição relativa. Por
exemplo, a função:

int soma (int x , int y)


{
int z;
z = x + y;
return z;
}

pode ser chamada (invocada) pelo segmento de código

int main ()
{
int r, s;
printf (" \n Entre com um numero inteiro r: ");
scanf ( " %d%”,&r );
printf (" \n Entre com um numero real s: ");
scanf ( " %f ",&s );
printf (" \n valor da soma %f ", soma (r, s) ); /* chamada da função */
return 0;
}

O mecanismo de comunicação verifica em primeiro lugar, se o número de


parâmetros da chamada soma(r,s) é igual ao número de parâmetros da função
int soma(int x, float y). Se essa comparação for verdadeira, verifica em seguida,
se esses parâmetros são do mesmo tipo e se estão na mesma posição relativa,
ou seja: se o tipo de r é igual ao tipo de x; se o tipo de s é igual ao tipo de y; se r
e x estão na primeira posição e se s e y estão na segunda posição.

Vamos normalizar a linguagem, para que o texto esteja em conformidade com


os termos técnicos utilizados na área.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 179


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Os parâmetros utilizados na chamada de uma função são chamados de


parâmetros reais, enquanto que os parâmetros que aparecem na declaração
de uma função são chamados de parâmetros formais.

Durante a execução de um programa, os parâmetros formais são substituídos


pelos parâmetros reais. Essa substituição pode ser feita por valor, variável ou
expressão. Para o exemplo anterior, a função soma, pode ser chamada pelas
seguintes instruções:

soma (4, 3.14);


soma (a + 3, (b + 7) / 2);

Na primeira chamada, os valores 4 e 3.14 são transferidos para os parâmetros


formais x e y, enquanto na segunda, as expressões a + 3 e (b + 7) / 2 são
transferidas para os mesmos parâmetros.

6.8 Parâmetros
Os parâmetros são os canais de comunicação entre a função e o exterior. Que
tipo de informações devem circular nesses canais?

Vimos que a entrada de dados da função principal era feita pelo teclado através
da função scanf(), e a saída era feita pelo monitor através da função printf().

As funções que nós iremos desenvolver têm um funcionamento analogo. A


entrada de dados é feita pelos parâmetros formais, enquanto a saída é feita pelo
valor de retorno.

Isso quer dizer, que normalmente, note que está escrito normalmente, não
devemos colocar a função scanf() e a função printf() nessas funções.

Antes de estudarmos três exemplos muito simples para consolidar


conhecimentos, devemos salientar que o desenvolvimento de subprogramas
fáceis de ler e de compreender, só pode ser obtido se utilizarmos uma
metodologia apropriada. A metodologia mais aconselhada é o refinamento
sucessivo.

O primeiro consiste em desenvolver um programa com subprogramas, para ler


dois números reais x e y e dois números inteiros a e b, tais que a > 0 e b > 0.
Calcular e mostrar na tela o valor da expressão xa + yb + (x − y)a+b.

Com base no método de refinamento sucessivo, uma possível solução para este
problema, pode ser descrita pelos seguintes passos:

1- declarar variáveis;
2- ler os expoentes x e y;
3- ler as bases a e b;
4- Calcular potência de x elevado a a;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 180


Fundamentos de Programação em C: Uma Abordagem Algorítmica

5- Calcular potência de y elevado a b;


6- Calcular potência de (x-y) elevado a (a+b);
7- Calcular valor da expressão;
8- Imprimir valor da expressão;

Pelo enunciado, temos como entidade de entrada dois números reais x e y, e


dois números inteiros a e b, tais que a > 0 e b > 0. Como entidade de saída,
temos o valor da expressão, que denotamos por s. Isso permite-nos declarar às
seguintes variáveis:

int a, b;
float x, y, s;

No próximo passo vamos identificar as acções que devem ser escritas como
subprogramas (funções em C) e implementa-las de forma independente.

O subprograma para ler a base, que denominamos por lerBase(), não recebe
nenhum valor via parâmetro, mas retorna um número real. Uma possível solução
para este problema, pode ser descrita pelos seguintes passos:

1- declarar a base;
2- imprimir (“Entre com o valor da base:”);
3- ler (base);
4- retornar base;

O subprograma para ler o expoente, que denominamos por lerExpoente(), não


recebe nenhum valor via parâmetro, mas retorna um número inteiro positivo.
Uma possível solução para este problema, pode ser descrita pelos seguintes
passos:

1- declarar o expoente;
2- repetir infinitamente
3- inicio
4- imprimir (“Entre com o valor do expoente:”);
5- ler (expoente);
6- se expoente > 0 então abandonar;
7- imprimir (“Erro: valor do expoente inválido”);
8- fim
9- retornar expoente;

Para desenvolver um subprograma que calcula o valor da expressão xa + yb + (x


− y)a+b, necessitamos de desenvolver um subprograma para calcular a potência
de um número qualquer com expoente positivo, e reutiliza-lo sempre que for
necessário.

O subprograma para calcular a potência de um número qualquer com expoente


positivo, denominada por potencia(), recebe através dos parâmetros, uma
determinada base e um determinado expoente. Retorna a potência dessa base
elevado ao expoente.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 181


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Mas, pelo capítulo anterior, sabemos que a potência de um número qualquer,


elevado a um expoente não negativo, pode ser determinado pela seguinte
fórmula:

1 se y = 0
xy = {
x (y−1) x se y > 0

Então, uma possível solução para este problema, pode ser descrita pelos
seguintes passos:

1- declarar expoente, base, pot, i;


2- inicializar pot com 1;
3- inicializar i com 0;
4- enquanto i < potencia faça
5- início
6- calcular pot = pot * base;
7- adicionar uma unidade a i;
8- fim
9- retornar pot;

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa na
linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o valor da expressão xa + yb + (x − y)a+b para a > 0 e b > 0
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir a função printf( ) scanf( ) */
#include <stdlib.h> /* incluir a funcao system( ) */

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
int lerExpoente ();
float lerBase ();
float potencia (int base , float expoente);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler o valor da Base
Recebe: Nada
Retorna: Número real
-------------------------------------------------------------------------------------------------------*/
float lerBase ()
{
float valor;
printf (" \n Entre com o valor da base:");
scanf ("%d", &base);
return valor;
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 182


Fundamentos de Programação em C: Uma Abordagem Algorítmica

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler o valor do expoente
Recebe: Nada
Retorna: Número inteiro positivo
-------------------------------------------------------------------------------------------------------*/
int lerExpoente ()
{
int valorExpoente;
while (1)
{
printf (" \n Entre com o valor do expoente:");
scanf ("%d", &valorExpoente);
if (valorExpoente > 0 ) break;
printf (“\n Erro: Valor do expoente invalido”);
}
return valor;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a potencia
Recebe: base e expoente
Retorna: valor da potencia
-------------------------------------------------------------------------------------------------------*/
float potencia (float base, int expoente)
{
float pot = 1.0 ;
int i ;
for (i = 0 ; i < expoente ; i++)
pot *= base ;
return pot;
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int a , b;
float x , y, s;
a = lerBase();
b = lerBase ();
x = lerExponte ();
y = lerExpoente ();
s = potencia(x , a) + potencia( y , b) + potencia ((x-y), (a+b));
printf (" \n Valor da Expressao = %f ", s );
system ("PAUSE");
return 0;
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 183


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Vamos tecer alguns comentários sobre este programa.

A programação com subprogramas tem como princípio fundamental a


reutilização de código. Esse princípio foi amplamente utilizado com as funções
lerBase(), lerExpoente() e potencia(), que foram implementadas uma única vez
e reutilizadas na função principal várias vezes.

Criamos duas funções para ler os dados, uma para ler a base e outra para ler o
expoente. Mas essa forma de implementação de código não viola as boas
prácticas de programação? Se fizermos uma análise profunda, veremos que
essas funções tornam o programa mais fácil de ler e de compreender, e para
além disso, uma dessas funções garante que o expoente para o calculo dessa
expressão é positivo, logo, ela dá uma maior consistência ao código. Isso é uma
prova que não violamos as boas prácticas de programação.

Também verificamos que a função principal é muito genérica. Ela não se


preocupa em resolver questões específicas do problema. Essas questões são
resolvidas por funções criadas para o efeito. Isso mostra que o programa está
em conformidade com as boas prácticas de programação.

O segundo exemplo, consiste em desenvolver um programa com subprogramas,


para ler um conjunto indeterminado dos lados de um retângulo, calcular a sua
área e o seu perímetro.

Com base no método de refinamento sucessivo, uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1- declarar SENTINELA;
2- declarar variáveis;
3- ler lado1;
4- enquanto lado1 ≠ SENTINELA faça
5- início
6- ler lado2;
7- calcular a área;
8- calcular o perímetro;
9- imprimir os resultados;
10- ler lado1;
11- fim

Pelo enunciado, temos como entidade de entrada os lados de um retângulo, e


como entidade de saída, o valor da área e do perímetro. Isso permite-nos
declarar às seguintes variáveis:

int lado1, lado2;


float area, perimetro;

No próximo passo vamos identificar as acções que devem ser escritas como
subprogramas e implementa-las de forma independente.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 184


Fundamentos de Programação em C: Uma Abordagem Algorítmica

O subprograma para ler o primeiro lado do retângulo, que denominamos por


lerLado1(), não recebe nenhum valor através dos parâmetros, e retorna um
número inteiro não negativo, que satisfaz a seguinte propriedade: se esse
número for positivo, faz referência ao comprimento do primeiro lado do retângulo,
no caso contrário, faz referência ao sentinela de fim de leitura. Uma possível
solução para este problema pode ser descrita pelos seguintes passos:

1- declarar lado1;
2- repetir infinitamente
3- início
4- imprimir (“ Entre com primeiro lado do retângulo:”);
5- ler (lado1);
6- se lado1 >= 0 então abandonar;
7- imprimir (“Erro: valor do primeiro lado inválido”);
8- fim
9- retornar lado;

O subprograma para ler o segundo lado do retângulo, que denominamos por


lerLado2(), não recebe nenhum valor através dos parâmetros, e retorna um
número inteiro positivo. Uma possível solução para este problema pode ser
descrita pelos seguintes passos:

1- declarar lado2;
2- repetir infinitamente
3- início
4- imprimir (“Entre com o segundo lado do retângulo:”);
5- ler (lado2);
6- se lado2 > 0 então abandonar;
7- imprimir (“Erro: valor do segundo lado inválido”);
8- fim
9- retornar lado;

O subprograma para calcular área, que denominamos por calcularArea(), recebe


através dos parâmetros, o comprimento dos lados do retângulo, e retorna o valor
da área. Uma possível solução pode ser descrita pelos seguintes passos:

1- declarar area;
2- calcular area = lado1 * lado2;
3- retornar area;

O subprograma para calcular o perímetro, que denominamos por


calcularPerimetro(), recebe através dos parâmetros, o comprimento dos lados
do retângulo, e retorna o valor do perímetro. Uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1- declarar perimetro;
2- calcular perimetro = 2 x (lado1 + lado2);
3- retornar perimetro;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 185


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa na
linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a área e o perímetro de um retângulo.
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir a função printf() e scanf() */
#include <stdlib.h> /* incluir a funcao system() */
#define SENTINELA 0

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
int lerLado1( );
int lerLado2( );
float calcularArea (int lado1, int lado2);
float calcularPerimetro (int lado1, int lados2);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler o primeiro lado do retângulo
Recebe: Nada
Retorna: Número inteiro não negativo
-------------------------------------------------------------------------------------------------------*/
int lerLado1 ( )
{
int lado1;
while (1)
{
printf (" \n Entre com o primeiro lado do retangulo: ");
scanf ("%d", &lado1);
if ( lado1 >= 0 ) break;
printf (“\n Erro: Valor do primeiro lado invalido”);
}
return lado1;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler o segundo lado do retângulo
Recebe: Nada
Retorna: Número inteiro positivo
-------------------------------------------------------------------------------------------------------*/
int lerLado2 ( )
{
int lado2;
while (1)
{
printf (" \n Entre com o segundo lado do retangulo: ");
scanf ("%d", &lado2);

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 186


Fundamentos de Programação em C: Uma Abordagem Algorítmica

if (lado2 > 0 ) break;


printf (“\n Erro: Valor do segundo lado invalido”);
}
return lado2;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a área do retângulo
Recebe: Lados do retângulo
Retorna: Área
-------------------------------------------------------------------------------------------------------*/
float calcularArea (int lado1, int lado2)
{
return (lado1 * lado2);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o perímetro
Recebe: Lados do retângulo
Retorna: Perímetro
-------------------------------------------------------------------------------------------------------*/
float calcularPerimetro (int lado1, int lado2)
{
return 2 * (lado1 + lado2);
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int x , y;
float perimetro , area;
x = lerLado1 ( );
while ( x != SENTINELA )
{
y = lerLado2 ( );
area = calcularArea (x , y);
perimetro = calcularPerimetro (x , y);
printf (" \n Perimetro= %d Area = %d ", perimetro, area);
x = lerLado1 ( );
}
system("PAUSE");
return 0;
}

Podemos optmizar a função principal. Essa optimização consiste em colocar a


chamada das funções calcularArea() e calcularPerimetro() no interior do

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 187


Fundamentos de Programação em C: Uma Abordagem Algorítmica

comando de impressão, e a leitura do comprimento do primeiro lado do


retângulo, no interior da expressão do comando de repetição.

int main ()
{
int x , y;
float perimetro , area;
while (( x = lerLado1( )) != SENTINELA )
{
y = lerLado2 ();
printf (" \n %d %d ", calcularArea (x , y) , calcularPerimetro (x , y));
}
system("PAUSE");
return 0;
{

O terceiro e último exemplo, consiste em desenvolver um programa com


subprogramas, para ler um número inteiro positivo e calcular o valor da série
harmónica.

Por definição, a série harmónica é descrita por:

1 1 1 1
hn = 1 + + + +…+ para n≥ 1
2 3 4 𝑛

Com base no método de refinamento sucessivo, uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1-declarar variáveis;
2-ler número inteiro n;
3-calcular harmónico;
4-imprimir resultados;

Pelo enunciado, temos como entidade de entrada um número inteiro positivo, e


como entidade de saída, o harmónico desse número. Isso permite-nos declarar
às seguintes variáveis:

int n;
float h;

No próximo passo vamos identificar as acções que devem ser escritas como
subprogramas e implementa-las de forma independente.

O subprograma para ler um número inteiro, que denominamos por lerNumero(),


não recebe nenhum valor através dos parâmetros, e retorna um número inteiro
positivo. Deixamos como exercício a implementação desse algoritmo.

O subprograma para calcular harmónico de um número, que denominamos por


harmonico(), recebe através dos parâmetros, um número inteiro positivo, e

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 188


Fundamentos de Programação em C: Uma Abordagem Algorítmica

retorna o harmónico desse número. Uma possível solução para este problema
pode ser descrita pelos seguintes passos:

1- declarar h , i;
2- inicializar h com zeros;
3- para i de 1 até n passo 1 faça
4- adicionar a h o valor 1/i;
2- retornar h;

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa escrito
na linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o valor da Série Harmónica
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir a função printf() e scanf() */
#include <stdlib.h> /* incluir a função system() */

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
int lerNumero ();
float harmonico (int n);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler um número inteiro
Recebe: Nada
Retorna: Número inteiro não negativo digitado pelo utilizador
-------------------------------------------------------------------------------------------------------*/
int lerNumero ()
{
int numero;
while (1)
{
printf (" \n Entre com um numero inteiro positivo: " );
scanf ("%d", &numero );
if ( numero > 0) break;
printf (" \n Erro: numero invalido" );
}
return numero;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o valor da série harmónica
Recebe: Número inteiro positivo
Retorna: Valor da série
-------------------------------------------------------------------------------------------------------*/
float harmonico (int n)

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 189


Fundamentos de Programação em C: Uma Abordagem Algorítmica

{
float h = 0.0 ;
int i ;
for ( i = 1 ; i <= n ; i++)
h += 1.0/i;
return h;
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
float h;
int n;
n = lerNumero ();
h = harmonico(n);
printf (“ \n Valor harmonico de %d igual a %f ”, n , h);
system (“PAUSE”);
return 0;
}

Mais uma vez enfatizamos que a documentação de um programa deve mostrar


de forma sucinta o objectivo de cada função, e a comunicação que este tem com
o exterior. Não se deve descrever como as funções resolvem o problema. Se o
leitor por ventura quiser conhecer esses pormenores, deverá ter a competência
para ler o código (feofiloff 2009).

6.9 Chamada de uma Função por Outra


A maior parte das linguagens de programação, permitem que uma função seja
accionada por uma outra. Mas para que essa comunicação seja possível é
necessário implementar em primeiro lugar a função que será accionada.

Vamos consolidar esse conceito com o desenvolvimento de um programa com


subprogramas para calcular todas as combinações de n p a p, ou seja:

se n = 2 imprimir c(2,0), c(2,1), c(2,2)


se n = 4 imprimir c(4,0), c(4,1), c(4,2) e c(4,4)
onde
C(n, p) = n! / ( p! * (n-p)!)

Com base no método de refinamento sucessivo, uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1- declarar variáveis;
2- ler número inteiro n;
3- para p de 0 até n passo 1 faça

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 190


Fundamentos de Programação em C: Uma Abordagem Algorítmica

4- início
5- calcular combinação de n p a p;
6- imprimir resultado;
7- fim

Pelo enunciado, temos como entidade de entrada dois números inteiros


positivos, e como entidade de saída, os valores das respectivas combinações.
Isso permite-nos declarar às seguintes variáveis:

int n , p , comb;

No próximo passo vamos identificar as acções que devem ser resolvidas como
subprogramas e implementa-las de forma independente.

O subprograma para ler um número inteiro n, que denominamos por lerNumero(),


não recebe nenhum valor através dos parâmetros, e retorna um número inteiro
positivo. Deixamos como exercício a implementação desse algoritmo.

Para calcular a combinação de n p a p, temos de determinar em primeiro lugar,


os valores do factorial de n, factorial de p e factorial de (n-p). Como os
subprogramas que implementam esses factoriais são praticamente iguais, faz
sentido desenvolver em primeiro lugar, um subprograma que calcula o factorial
de um número qualquer, e reutiliza-lo para calcular a combinação de n p a p.

O subprograma para calcular o factorial de um número, que denominamos por


factorial(), recebe através dos parâmetros um número inteiro positivo, e retorna
o factorial desse número. Uma possível solução para este problema pode ser
descrita pelos seguintes passos:

1- declarar fat , i;
2- inicializar fat com 1;
3- para i de 1 até n passo 1 faça
4- início
5- multiplicar fat por i;
6- armazenar o resultado da operação anterior em fat;
7- fim;
8- retornar fat;

Agora, vamos pegar nesse subprograma para desenvolver um subprograma que


calcula a combinação de n p a p.

O subprograma para calcular a combinação de n p a p, que denominamos por


combinacao(), recebe através dos parâmetros um número inteiro positivo n, um
número inteiro positivo p, e retorna o valor da combinação de n p a p. Uma
possível solução para este problema pode ser descrita pelos seguintes passos:

1- declarar comb;
2- calcular comb = factorial(n) / (factorial(p) * factorial (n-p));
3- retornar comb;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 191


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa escrito
na linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular as combinações de n p a p
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir a função printf() e scanf() */
#include <stdlib.h> /* incluir a funcao system() */

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
int lerNumero ();
int factorial (int n);
float combinação (int n , int p);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler um número inteiro
Recebe: Nada
Retorna: Número inteiro não negativo digitado pelo utilizador
-------------------------------------------------------------------------------------------------------*/
int lerNumero ()
{
/* Faça como exercício */;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o factorial de um número inteiro
Recebe: Número inteiro
Retorna: Factorial desse número
-------------------------------------------------------------------------------------------------------*/
int factorial (int n)
{
int i , fat;
for ( fat = 1 , i = 1 ; i <= n ; i++)
fat += i;
return fat;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a combinação de n p a p
Recebe: Valor de n e valor de p
Retorna: Combinação de n p a p
-------------------------------------------------------------------------------------------------------*/
float combinacao (int n, int p)
{
return ( factorial(n)/( factorial(r)*factorial(n-r) ) );
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 192


Fundamentos de Programação em C: Uma Abordagem Algorítmica

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int n , p;
n = lerNumero();
for (p = 0 ; p <= n ; p++)
printf (" \n %d ", combinacao(n , p) );
system ("PAUSE");
return 0;
}

Fazem parte das boas práticas de programação, definir em primeiro lugar as


funções que são chamadas por outras funções.

6.10 Procedimentos
Por definição, um procedimento é um subprograma que não retornam nenhum
valor via valor de retorno.

Na linguagem C os procedimentos são conhecidos como funções do tipo void,


e possuem a seguinte sintaxe:

void nome (Declaração dos parâmetros)


{
Declaração dos identificadores;
Comandos da função;
}

Nas funções do tipo void o comando return não é obrigatório. Uma função sem
o comando return termina quando for encontrado o delimitador de fim de blocos.

Fazem parte das boas práticas de programação, utilizar procedimentos,


sempre que tivermos de implementar subprogramas que não enviam para o
exterior informações.

Para consolidar os conhecimentos, vamos desenvolver um programa com


subprogramas para controlar o número de minutos que um funcionário esteve
numa empresa.

Com base no método de refinamento sucessivo, uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1- declarar SENTINELA;
2- declarar variáveis;
3- ler o passe;
4- enquanto passe ≠ SENTINELA faça

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 193


Fundamentos de Programação em C: Uma Abordagem Algorítmica

5- início
6- ler hora e minuto da entrada;
7- converter essas horas para minutos;
8- ler hora e minuto da saída;
9- converter essas horas para minutos;
10- calcular a diferença de tempo;
11- imprimir resultados;
12- ler passe;
13- fim

Pelo enunciado, temos como entidade de entrada o número do passe do


funcionário, a hora e o minuto de entrada e de saída. Como entidade de saída
temos o número do passe do funcionário e o tempo que este esteve no serviço.
Isso permite-nos declarar às seguintes variáveis:

int passe, minutoEntrada, minutoSaida, tempoNoServico, hora, minutos;

Como não definimos o número de funcionários que iremos processar, vamos


associar um sentinela de fim de leitura ao número do passe do funcionário.

#define SENTINELA 0

No próximo passo vamos implementar como subprogramas as acções que não


foram expandidas na totalidade.

O subprograma para ler o passe, que denominamos por lerPasse(), não recebe
nenhum valor através dos parâmetros, e retorna um número inteiro positivo.
Deixamos como exercício a implementação desse algoritmo.

O subprograma para converter horas para minutos, que denominamos por


converteTempo(), recebe através dos parâmetros, as horas e os minutos, e
retorna o correspondente tempo em minutos. Como o subprograma retorna um
valor deve ser implementado como uma função. Uma possível solução para este
problema pode ser descrita pelos seguintes passos:

1- declarar tempoEmMinutos;
2- calcular tempoEmMinutos = horas* 60 + minutos;
3- retornar tempoEmMinutos;

O subprograma para calcular à diferença de preço, que denominamos por


diferencaTempo(), recebe através dos parâmetros, o tempo de entrada e o
tempo de saída em minutos e retorna a diferença de tempo. Como o
subprograma retorna um valor deve ser implementado como uma função. Uma
possível solução para este problema pode ser descrita pelos seguintes passos:

1- declarar diferencaTempo;
2- calcular diferencaTempo = tempoSaida - tempoEntrada;
3- retornar diferencaTempo;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 194


Fundamentos de Programação em C: Uma Abordagem Algorítmica

O subprograma para imprimir resultados, que denominamos por imprimir(),


recebe através dos parâmetros, o número do passe e a diferença de tempo, mas
não devolve nenhuma informação. Como o subprograma não retorna nenhum
valor deve ser implementado como um procedimento. Uma possível solução
para este problema pode ser descrita pelos seguintes passos:

1- imprimir (passe);
2- imprimir (diferencaTempo);

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa na
linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o número de horas de trabalho por dia de cada empregado.
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir a função printf() e scanf() */
#include <stdlib.h> /* incluir a funcao system() */

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
int lerNumeroPasse ();
int converteTempo (int h , int m);
int diferencaTempo (int entrada , int saida);
void imprimir (int passe , int horasNoServico);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir a assiduidade do empregado
Parâmetros: Passe do trabalhador e horas no serviço
-------------------------------------------------------------------------------------------------------*/
void imprimir (int passe , int horasNoServico)
{
printf (" \n Trabalhador com o passe %d: ", passe);
printf (" \n esteve na Empresa %d: ", horasNoServico);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Converter as horas e os minutos para minutos
Recebe: Horas e minutos
Retorna: Minutos
-------------------------------------------------------------------------------------------------------*/
int converteTempo (int h , int m)
{
return ( h* 60 + m);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler um número do passe do funcionário

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 195


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Recebe: Nada
Retorna: Número do passe
-------------------------------------------------------------------------------------------------------*/
int lerNumeroPasse ()
{
int passe;
while (1)
{
printf (" \n Entre com um numero do passe do trabalhador: " );
scanf ("%d", &passe );
if ( passe > 0) break;
printf (" \n Erro: numero do passe invalido" );
}
return passe;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular os minutos de trabalho
Parâmetros: Minutos de entrada e minutos e saída
Valor de retorno: Tempo em minutos
-------------------------------------------------------------------------------------------------------*/
int diferencaTempo (int entrada , int saida)
{
return saida - entrada;
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int passe , minutoEntrada , minutoSaida , tempoNoServico , hora , minutos;
while ((passe = lerNumeroPasse ( )) != SENTINELA )
{
printf (" \n Digite hora de entrada (hora:minutos) : " );
scanf (" %d : %d ",&hora , &minutos);
minutoEntrada = converteTempo (hora , minutos);
printf ("\n Digite hora de saida (hora:minutos) : " );
scanf (" %d : %d ",&hora , &minutos);
minutoSaida = converteTempo (hora , minutos);
tempoNoServico = diferencaTempo (minutoEntrada , minutoSaida);
imprimir (passe , tempoNoServico);
}
system("PAUSE");
return 0;
}

Podemos optimizar a função principal, com a chamada da função


diferencaTempo() no parâmetro tempoNoServico do procedimento imprimir().

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 196


Fundamentos de Programação em C: Uma Abordagem Algorítmica

int main ()
{
int passe , minutoEntrada , minutoSaida , hora , minutos;
while (passe = lerNumeroPasse() != SENTINELA )
{
printf (" \n Digite hora de entrada (hora:minutos) : " );
scanf (" %d : %d ",&hora , &minutos);
minutoEntrada = converteTempo(hora ,minutos);
printf (" \n Digite hora de saida (hora:minutos) : " );
scanf (" %d : %d ",&hora , &minutos);
minutoSaida = converteTempo (hora , minutos);
imprimir (passe , diferencaTempo(minutoEntrada , minutoSaida));
}
system("PAUSE");
return 0;
}

6.11 Passagem de Parâmetros


Vimos que a comunicação entre as funções e o mundo exterior deve ser feita
pelos parâmetros para entrada de dados, e pelo comando return para saída de
uma e apenas uma informação.

Este tipo de comunicação, entrada de dados via parâmetros e saída via comando
valor de retorno, é a mais comum nas linguagens de programação modernas, e
denomina-se por passagem por valor.

Na passagem por valor, uma copia dos parâmetros reais (parâmetros da


chamada) é enviada para os parâmetros formais (parâmetros da função). Isso
quer dizer que os parâmetros formais e os parâmetros reais estão armazenados
em posições de memória diferentes. Logo, qualquer alteração feita aos
parâmetros formais não afectam os valores dos parâmetros reais.

Mas em programação é muito comum que um subprograma envie para o exterior


mais do que um valor. Um exemplo clássico consiste em trocar o conteúdo de
duas variáveis. O procedimento (função do tipo void em C) que realiza essa
tarefa é descrito por:

void troca (int a, int b)


{
int tmp;
tmp = a;
a = b;
b = tmp;
}

e uma possível função principal que acciona este procedimento pode ser descrita
por:

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 197


Fundamentos de Programação em C: Uma Abordagem Algorítmica

int main ()
{
int x , y;
printf (" \n Entre com dois numeros inteiros: ");
scanf (" %d %d ", &x , &y);
prinf (" \n Antes da troca x = %d e y= %d ", x , y);
troca (x , y); /* Chamada da função */
printf (" \n Depois da troca x= %d e y= %d ", x , y);
return 0;
}

Suponhamos sem perda da generalidade, que x = 5 e y = 9. Se executarmos


esse programa, teremos os seguintes resultados:

Antes da troca x = 5 e y = 9
Depois da troca x = 5 e y= 9

O que está errado? O erro não está no código do procedimento, mas na forma
de passagem de parâmetros. O procedimento deve receber através dos
parâmetros formais dois valores, e devolver através dos mesmos parâmetros os
seus conteúdos trocados.

Para que um subprograma possa alterar no seu interior os valores dos


parâmetros formais, é necessário que estes sejam passados por referência.

Na passagem por referência, a comunicação entre os parâmetros formais


(parâmetros da função) e os parâmetros reais (parâmetros da chamada) são
feitas por endereços. Isso quer dizer que esses parâmetros compartilham as
mesmas posições de memória, e como consequência, qualquer alteração feita
ao conteúdo dos parâmetros formais, afectam os valores dos parâmetros reais.

Mas, para efectuar essa passagem, os parâmetros formais e os parâmetros reais


devem ser declarados como variáveis do tipo ponteiro.

Um ponteiro, é tipo especial de dados, que permite manipular endereços, e


possui a seguinte sintaxe:

tipo (oper) nome;


onde
tipo representa o tipo de dados, int, float, double ou char;
oper representa o operador do tipo ponteiro que pode ser * ou &;
nome denota uma variável.

O operador unário & denominado por operador endereço é um ponteiro que


devolve o endereço de memória do seu operando. Por exemplo:

m = &cont;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 198


Fundamentos de Programação em C: Uma Abordagem Algorítmica

armazena no ponteiro m o endereço da variável cont. Esse endereço é uma


posição interna de memória do computador.

Vamos clarificar esse conceito com um exemplo. Suponhamos sem perda da


generalidade que a variável cont está armazenada no endereço de memória 250
e possui o valor 150. Com essa operação o ponteiro m contêm o valor 250.

O operador unário * denominado por operador indirecto é um ponteiro que


devolve o conteúdo do endereço de memória do seu operando. Por exemplo, se
m contêm o endereço da variável cont, a atribuição

q = *m;

armazena o conteúdo de cont na variável q. Logo q terá o valor 150, porque 150
é o valor de está armazenado nessa posição de memória.

Então, a resolução do nosso problema passa pela declaração do conteúdo das


localizações de memória nos parâmetros formais. Esse conteúdo é declarado
pelo operador indirecto, ou seja:

void troca ( int *a, int *b)


{
int tmp;
tmp = *a;
*a = *b;
*b = temp;
}

e, na chamada do procedimento, devemos passar os endereços dos parâmetros


reais. Esses endereços são declarados pelo operador de endereço, ou seja:

int main ()
{
int x, y;
printf (" \n Entre com dois numeros inteiros: ");
scanf (" %d %d ", &x , &y);
printf (" \n Antes da troca x = %d e y= %d ", x , y);
troca(&x , &y); /* chamada da Função */
printf (" \n Depois da troca x= %d e y= %d ", x , y);
return 0;
}

Na passagem por referencia, os parâmetros reais devem possuir como prefixo o


operador de endereço (&), enquanto que os parâmetros formais devem possuir
como prefixo o operador de acesso indirecto (*)

Para terminar está secção, veremos mais um exemplo clássico. Desenvolva um


subprograma para calcular as raízes reais de uma equação do segundo grau
ax2+bx+c = 0.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 199


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Este subprograma recebe através dos parâmetros, os coeficientes da equação


de segundo grau, e devolve através dos parâmetros as raízes dessa equação.
Mas, como existem vários casos particulares, este subprograma também retorna
através valor de retorno, uma informação a notificar o tipo de raiz encontrada,
que pode ser:

1 = quando temos duas raízes diferentes;


0 = quando temos duas raízes iguais;
-1 = quando não temos raízes reais;
-2 = quando temos uma equação do primeiro grau;
-3 = quando não temos uma equação.

Como acreditamos que o leitor não deverá ter qualquer dificuldade em


desenvolver um algoritmo para resolver o problema, mostraremos a seguir, a
correspondente função na linguagem C.

int equac2Grau (double a , double b , double c , double *x1 , double *x2)


{
double delta;
if (a == 0.0 && b == 0.0) /* não é uma equação*/
return -3;
if (a == 0.0) /*equação do 1. Grau */
{
*x1 = -c / b;
return -2;
}
delta = b*b - 4*a*c;
if (delta < 0) /* se delta < 0, raízes não são reais */
return -1;
if (delta == 0) /* se delta = 0, raízes reias iguais */
{
*x1 = *x2 = -b / (2*a);
return 0;
}
*x1 = (-b + sqrt(delta))/(2*a); /* se delta > 0, raízes reais diferentes */
*x2 = (-b - sqrt(delta))/(2*a);
return 1;
}

Observe que nesta função, os parâmetros a, b e c foram passados por valor,


enquanto os parâmetros x1 e x2 foram passados por referência.

Agora, estamos em condições de escrever uma notação que utilizaremos neste


livro, para descrever as várias formas de comunicação entre o subprograma e o
mundo exterior.

Recebe: O subprograma importa através dos parâmetros informações.


Devolve: O subprograma exporta através dos parâmetros informações.
Retorna: O subprograma devolve através do valor de retorno um e apenas um
valor.

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 200


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Fazem parte das boas práticas de programação, passar por valor, todos os
parâmetros que não vão ser modificados durante a execução de um
subprograma.

6.12 Identificadores Locais e Globais


As linguagens de programação modernas, permitem que se faça declarações de
variáveis e de funções em qualquer parte do programa. Essas declarações
definem as suas áreas de visibilidade, ou seja, as áreas que essas variáveis ou
essas constantes podem ser utilizadas, que na ciência de computação dá-se o
nome de Escopo.

Todas as variáveis ou constantes declaradas no interior de um subprograma,


são chamadas por identificadores locais, e só são visíveis no subprograma
onde foram declaradas. As áreas de memória relacionadas com esses
identificadores, só serão alocadas no momento que o subprograma é accionado
e libertadas quando este termina.

Vamos clarificar este conceito com um exemplo, na função:

void troca ( int *a, int *b)


{
int aux; /* variável local */
aux = *a;
*a = *b;
*b = aux;
}

Os parâmetros formais a e b servem para a entrada e a saída de dados do


subprograma. Mas para fazer a troca do conteúdo de duas variáveis
necessitamos uma variável auxiliar, que será declarada no interior do
subprograma. Esta variável só existe quando esta função for accionada.

Em contrapartida, as variáveis e as constantes declaradas antes do protótipo das


funções, são chamadas de Identificadores globais, e são visíveis em todo o
programa. As áreas de memória relacionadas com esses identificadores são
alocadas quando o programa começa a ser executado e libertadas quando o
programa termina.

Não fazem parte das boas práticas de programação utilizar variáveis globais no
interior de um subprograma.

As linguagens de programação modernas também permitem que se declare


identificadores locais com o mesmo nome de identificadores já utilizadas no
programa.

Por exemplo, suponhamos sem perda da generalidade que declaramos uma


variável global com o nome media e que declaramos na função calcularMedia()

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 201


Fundamentos de Programação em C: Uma Abordagem Algorítmica

uma variável local com o mesmo nome. Quando a função calcularMedia() for
accionada, qualquer referência a variável media está associada a variável local.
No interior dessa função essa variável global torna-se inacessível.

Toda a comunicação entre um subprograma e o programa que o accionou, deve


ser feita pelos parâmetros. Os restantes elementos necessários para o seu
funcionamento devem ser declarados como identificadores locais.

6.13 Exercícios Resolvidos


Problema 6.14.1: Uma Universidade pretende informatizar o lançamento de
notas. Durante o semestre, os estudantes são submetidos a três projectos de
laboratório, e a média para aprovação é determinada pela fórmula:

20 projecto1 + 30 projecto2 + 50 projecto3


100

Com base nessas médias, o estudante tem a seguinte classificação:

Superior a 15 valores Dispensado ao exame


Entre 8 a 15 valores Vai a Exame final
Inferior a 8 valores Reprovado

O programa deve ler o número do estudante, as notas dos três projectos e


imprimir uma pauta com as seguintes informações: número, média final e
classificação.

Resolução: uma versão já refinada para este problema pode ser descrita pelos
seguintes passos:

1- declarar SENTINELA;
2- declarar variáveis;
3- ler número do aluno;
4- enquanto (número do aluno ≠ SENTINELA) faça
5- início
6- ler nota do projecto1;
7- ler nota do projecto2;
8- ler nota do projecto3;
9- calcular média dos projectos;
10- classificar nota do aluno;
11- imprimir uma linha da pauta;
12- ler número do aluno;
13- fim

Pelo enunciado, temos como entidade de entrada o número do aluno e as notas


dos três projectos. Como entidade de saída temos uma pauta com a respectiva
classificação. Isso permite-nos declarar às seguintes variáveis:

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 202


Fundamentos de Programação em C: Uma Abordagem Algorítmica

int numero , projecto1 , projecto2 , projecto3;


char classificacao;

Como não conhecemos o número de alunos vamos processar, utilizaremos um


sentinela de fim de leitura associado ao número do estudante.

#define SENTINELA 0

No próximo passo vamos identificar as acções que devem ser resolvidas como
subprogramas e implementa-las de forma independente.

O subprograma, ler o número do aluno, que denominamos por


lerNumeroAluno(), não recebe nenhum valor e retorna o número do passe do
aluno. Faça como exercício.

O subprograma, ler a nota de um projecto, que denominamos por


lerNotaProjecto(), recebe o número de um projecto e retorna o valor da nota
desse projecto. Conceitualmente, estamos em presença de uma função, cuja
solução pode ser descrita pelos seguintes passos:

1- enquanto (verdadeiro) faça


2- início
3- imprimir (" Entre com a nota do projecto "); ler (projecto);
4- se projecto ≥ 0 e projecto ≤ 20 então abandonar;
5- imprimir (" Erro: Nota Invalida ");
6- fim
7- retornar projecto

O subprograma, calcular a média dos projectos, que denominamos por


calcularMedia(), recebe o valor dos três projectos e retorna a sua média
aritmética. Conceitualmente, estamos em presença de uma função, cuja solução
pode ser descrita pelos seguintes passos:

1- declarar media;
2- media = 0.2 * projecto1 + 0.3 * projecto2 + 0.5 * projecto3;
3- retornar media;

O subprograma, classificar a nota do aluno, que denominamos por


classificarEstudante(), recebe a média do estudante e retorna a sua classificação
escolar. Conceitualmente estamos em presença de uma função, cuja solução
pode ser descrita pelos seguintes passos:

1- se media > 15 então retornar 'D';


2- se media > 8 então retornar 'E';
3- retornar 'R';

O subprograma, imprimir uma linha na pauta, que denominamos por


imprimirLinha() recebe o número do passe, a média do estudante e a sua
classificação escolar. Não devolve nenhuma informação. Conceitualmente

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 203


Fundamentos de Programação em C: Uma Abordagem Algorítmica

estamos em presença de um procedimento cuja solução pode ser descrita pelos


seguintes passos:

1- imprimir (passe, media, classificacao);

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa em C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir uma pauta com as notas dos estudantes de uma turma.
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir as funções scanf( ) e printf( ) */
#include <stdlib.h> /* incluir a função system( ) */
#define SENTINELA 0

/*-------------------------------------------------------------------------------------------------------
Protótipo de funções
-------------------------------------------------------------------------------------------------------*/
float calcularMedia (int projecto1 , int projecto2 , int projecto3);
int lerNumeroEstudante ( );
int lerNotaProjecto (int numProjecto);
char classificarEstudante (float mediaprojectos);
void imprimirLinha (int passe , float media , char classe);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a média
Recebe: Notas dos três projectos
Retorna: Média
-------------------------------------------------------------------------------------------------------*/
float calcularMedia (int projecto1 , int projecto2 , int projecto3)
{
return ( 0.2 * projecto1 + 0.3 * projecto2 + 0.5 * projecto3 );
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler o número do estudante
Recebe: Nada
Retorna: Número do passe do estudante
-------------------------------------------------------------------------------------------------------*/
int lerNumeroEstudante ()
{
int passe;
while (1)
{
printf (" \n Entre com o numero do estudante:");
scanf (" %d", &passe);
if (passe >= 0) break;
printf ("\n Numero do passe invalido");
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 204


Fundamentos de Programação em C: Uma Abordagem Algorítmica

return passe;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler a nota de um projecto
Recebe: Número do Projecto
Retorna: A nota desse projecto
-------------------------------------------------------------------------------------------------------*/
int lerNotaProjecto (int numProjecto)
{
float nota;
while (1)
{
printf ("\Entre com a nota do nº /d projecto:", numProjecto));
scanf ("%d", &nota));
if (nota >= 0 && nota <= 20) break;
printf ("\n Erro: Nota invalida");
}
return nota;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Selecionar a Classificação do estudante
Recebe: Média dos projectos
Retorna: Classificação do aluno
-------------------------------------------------------------------------------------------------------*/
char classificarEstudante (float media)
{
if (media > 15 ) return 'D';
if (media > 8 ) return 'E';
return 'R';
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir uma linha da pauta
Recebe: Passe, media, classificacao
Devolve: Nada
-------------------------------------------------------------------------------------------------------*/
void imprimirLinha (int passe , float media , char classificacao)
{
printf ("\n Estudante com o passe %d :", passe);
printf (" \n Media dos projectos %.2f ", media);
printf (" \n Classicacao de %c ", classificacao);
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 205


Fundamentos de Programação em C: Uma Abordagem Algorítmica

int main ()
{
int numero , projecto1 , projecto2 , projecto3;
float mediaprojecto;
char classificacao;
while ( numero = lerNumeroEstudante ( ) != SENTINELA )
{
projecto1 = lerNotaProjecto(1);
projecto2 = lerNotaProjecto(2);
projecto3 = lerNotaProjecto(3);
mediaprojecto = calcularMedia (projecto1, projecto2, projecto3);
classificacao = classificarEstudante (mediaprojecto);
imprimirLinha (numero , mediaprojecto , classificacao);
}
system("PAUSE");
return 0;
}

Problema 6.14.2: A companhia de pulverização Avion Ltda, utiliza aeronaves


para pulverizar fazendas. Os custos do serviço de pulverização dependem do
tipo de praga e da área a pulverizar:

Tipo1: pulverização contra ervas daninhas, Kz 8.000,00 por km quadrado


Tipo2: Pulverização contra gafanhotos, KZ 10.000,00 por km quadrado
Tipo3: Pulverização contra broca , KZ 15.000,00 por km quadrado
Tipo4: Pulverização contra tudo, Kz 18.000,00 por km quadrado.

Se a área pulverizada for maior do que 10 km2, o fazendeiro recebe um desconto


de 5% sobre o custo do serviço. Em contrapartida, qualquer fazendeiro cujo do
serviço do serviço ultrapasse os 100.000,00 Kz, recebe um desconto de 10%
sobre o valor que ultrapassar esse limite. Desenvolver um programa para ler um
conjunto de dados com os seguintes campos: código do fazendeiro, tipo de
pulverização, área pulverizada. Imprimir o código do fazendeiro seguido do valor
a pagar pelo serviço.

Resolução: Como o leitor já está familiarizado com a metodologia de


refinamento sucessivo, apresentamos uma versão já refinada:

1- declarar variáveis;
2- ler identificação do fazendeiro;
3- enquanto identificação ≠ SENTINELA faça
4- inicio
5- ler tipo pulverização;
6- ler área pulverizada;
7- calcular custo do serviço;
8- calcular desconto sobre a área;
9- calcular desconto sobre o preço;
10- atualizar custo do serviço;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 206


Fundamentos de Programação em C: Uma Abordagem Algorítmica

11- imprimir factura;


12- ler identificação do fazendeiro;
13- fim

Pelo enunciado, temos como entidade de entrada, o número de fazendeiro, o


tipo de praga e a área pulverizada. Como entidade de saída temos uma factura
de cobrança do serviço com o custo do serviço. Isso permite-nos declarar às
seguintes variáveis:

int identificação;
float areaPulverizada , custoServico;
int tipoPulverizacao;

Como não conhecemos o número dos fazendeiros que iremos processar,


utilizaremos um sentinela de fim de leitura associado a identificação do
fazendeiro.

#define SENTINELA 0

Também vamos declarar as seguintes constantes que fazem referencia ao tipo


de praga:

#define ERVADANINHA 1
#define GAFANHOTOS 2
#define BROCAS 3
#define TUDO 4

No próximo passo, vamos descrever as acções que devem ser desenvolvidas


como subprogramas de forma independente.

Deixamos como exercício o desenvolvimento dos subprogramas: ler


identificação do fazendeiro, ler o tipo de pulverização, e ler a área pulverizada.
Para ler o tipo de pulverização, o leitor deve utilizar um menu com a seguinte
informação:

1- Erva Daninha
2- Gafanhotos
3- Broca
4- Tudo

O subprograma para calcular desconto sobre o custo, que denominamos por


CalcDescPreco() recebe o custo do serviço, e retorna o valor do desconto sobre
o custo que exceder os 100.000,00 Kz. Conceitualmente, estamos em presença
de uma função, cuja solução pode ser descrita pelos seguintes passos:

1- declarar excedente , desconto;


2- se custoServico > 100000.00 então
3- calcular excedente = custoServico - 100000.00;
4- senão
5- Atribuir zeros a excedente;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 207


Fundamentos de Programação em C: Uma Abordagem Algorítmica

4- calcular desconto = excedente * 10 %;


5- retornar desconto;

O subprograma para calcular o desconto sobre a área, que denominamos por


calcDescArea() recebe o custo do serviço e a área pulverizada. Retorna o valor
do desconto de 5% se a área pulverizada for maior do 10 Km2. Conceitualmente,
estamos em presença de uma função cuja solução pode ser descrita pelos
seguintes passos:

1- declarar desconto;
2- se areaPulverizada > 10.00 então
3- calcular desconto = custoServico * 5 %;
4- senão
5- atribuir zeros a desconto;
6- retornar desconto;

O subprograma, actualizar o custo, que denominamos por actualizarCusto(),


recebe o custo do serviço, o valor do desconto, e retorna o custo do serviço
actualizado. O custo do serviço é importado e exportado pelo subprograma, logo
podemos implementa-lo como um procedimento, utilizando para o efeito à
passagem por referência. Como o subprograma envia para o exterior um e
apenas um valor, este deve declarado como uma função. Uma possível solução
pode ser descrita pelos seguintes passos:

1- calcular custoDoServico = custoDoServico - desconto;


2- retornar custoDoServico;

O subprograma, calcular o custo do serviço, que denominamos por


calcCustServico() recebe o tipo de pulverização e a área pulverizada. Retorna o
valor do custo do serviço. Conceitualmente, estamos em presença de uma
função cuja solução pode ser descrita pelos seguintes passos:

1- declarar custo;
2- se tipoPulverizacao = ERVADANINHA então
3- custo = 8000 x areaPulverizada;
4- senão se tipoPulverizacao = GAFANHOTOS então
5- custo = 10000 x areaPulverizada;
6- senão se tipoPulverizacao = BROCAS então
7- custo = 150000 x areaPulverizada;
8- senão
9- custo = 180000 x areaPulverizada;
10- retornar o custo;

O subprograma, imprimir a factura, que denominamos por imprimirFatura()


recebe a identificação do fazendeiro e o custo do serviço. Não devolve nenhuma
informação. Conceitualmente, estamos em presença de um procedimento cuja
solução pode ser descrita pelos seguintes passos:

1- imprimir (identificacao , custoServico);

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 208


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa em C.

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir uma factura com os custos de serviço de pulverização
-------------------------------------------------------------------------------------------------------*/
#include <stdio.h> /* incluir as funções scanf( ) e printf( ) */
#include <stdlib.h> /* incluir a função system( ) */
#define SENTINELA 0
#define ERVADANINHA 1
#define GAFANHOTOS 2
#define BROCAS 3
#define TUDO 4

/*-------------------------------------------------------------------------------------------------------
Protótipos de funções
-------------------------------------------------------------------------------------------------------*/
int lerDadosFazendeiro ();
int lerTipoPulverizacao ();
float lerAreaPulverizada ();
void imprimirFatura (float custo , int identificacao);
float calcCustServico (int tipoPulverizacao , float areaPulverizada);
float calcDescArea (float custoServico, float areaPulverizada);
float calcDescPreco (float custoServico);
float actualizarCusto (float custoServico, float desconto);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler dados do Fazendeiro
Recebe: Nada
Retorna: Número da identificação do fazendeiro;
-------------------------------------------------------------------------------------------------------*/
int lerDadosFazendeiro ()
{
/* Fica como exercício */
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: através de um menu, selecionar o tipo de pulverização
Recebe: Nada
Retorna:Tipo de Pulverização
-------------------------------------------------------------------------------------------------------*/
int lerTipoPulverizacao ()
{
/* Fica como exercício */
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler a área pulverizada
Recebe: Nada

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 209


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Retorna: Área pulverizada


-------------------------------------------------------------------------------------------------------*/
int lerAreaPulverizada ()
{
/* Fica como exercício */
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o desconto com base na área pulverizada
Recebe: Custo do serviço e a área pulverizada
Retorna: Valor do desconto
-------------------------------------------------------------------------------------------------------*/
float calcDescArea (float custoServico, float areaPulverizada)
{
float desconto;
if (areaPulverizada > 10.00 )
desconto = custoServico * 0.05;
else
desconto = 0.0;
return desconto;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o desconto com base no custo do serviço (preço)
Recebe: Custo do serviço
Retorna: Valor do desconto
-------------------------------------------------------------------------------------------------------*/
float calcDescPreco (float custoServico)
{
float excedente, desconto;
if (custoServico > 100000.00 )
excedente = custoServico – 1000000.00
else
excedente = 0.0;
desconto = excedente * 0.10;
return desconto;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir fatura
Recebe: Custo do serviço, identificação
Devolve: Nada
-------------------------------------------------------------------------------------------------------*/
void imprimirFatura (float custoServico , int identificacao)
{
printf (" \n Codigo do fazendeiro %d ", identificacao);
printf (" Valor a pagar %.2f ", custoServico);
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 210


Fundamentos de Programação em C: Uma Abordagem Algorítmica

/*-------------------------------------------------------------------------------------------------------
Objectivo: Actualizar o Custo
Recebe: Custo do serviço e o valor do desconto
Retorna: Custo do serviço actualizado
-------------------------------------------------------------------------------------------------------*/
float actualizarCusto (float custoServico , float desconto)
{
return (custoServico – desconto);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o custo do serviço
Recebe: Tipo de pulverizaçao, área Infectada
Retorna: Valor do custo do serviço
-------------------------------------------------------------------------------------------------------*/
float calCustServico (int tipopulverizacao , float areainfectada)
{
float custo;
if (tipopulverizacao == ERVADANINHA)
custo = 8000 * areaInfectada;
else if (tipopulverizacao == GAFANHOTOS)
custo = 10000 * areaInfectada;
else if (tipopulverizacao == BROCAS)
custo = 15000* areaInfectada;
else
custo = 18000 x areaInfectada;
return custo;
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int tipo , identificacao;
float area , custo, descontoArea, descontoPreco;
while ((identificacao = lerDadosFazendeiro () ) != SENTINELA)
{
tipo = lerTipoPulverizacao ();
area = lerAreaPulverizada ();
custo = calcCustServico (tipo , area);
descontoArea = calcDescArea (custo, area);
descontoPreco = calcDescPreco(custo);
custo = actualizaCusto (custo, descontoPreco + descontoArea);
imprimirFatura (custo, identificacao);
}
system("PAUSE");
return 0;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 211


Fundamentos de Programação em C: Uma Abordagem Algorítmica

Problema 6.14.3: Desenvolver um programa para ler um conjunto indefinido de


dados que contêm a seguinte informação: carta de condução, velocidade limite
e velocidade do carro. Imprimir um relatório com o valor arrecada pelas multas.

Velocidade em excesso Multa


Até 10% da velocidade limite 0
Entre 10% e 20 % da velocidade limite 15.000,00
Acima de 20 % da velocidade limite 30.000,00

Para além disso, o programa deverá imprimir o valor total de multas aplicadas.

Resolução: Como o leitor já está familiarizado com a metodologia de


refinamento sucessivo, apresentamos uma versão já refinada:

1- declarar variáveis;
2- inicializar total arrecadado;
3- ler número da carta de condução;
4- enquanto número da carta de condução ≠ SENTINELA faça
5- inicio
6- ler velocidade do carro;
7- ler velocidade limite;
8- calcular velocidade em excesso;
9- se é infractor então
10- inicio
11- calcular percentagem da velocidade em excesso;
12- calcular valor da multa;
13- calcular valor arrecadado;
14- imprimir multa na tela;
15- fim
16- ler número da carta de condução;
17- fim
18- imprimir total do valor arrecadado;

Pelo enunciado, temos como dados de entrada, o número da carta de condução,


a velocidade limite e a velocidade do carro. Vamos associar esses dados as
respectivas variáveis a associa-las aos seus tipos de dados:

int carta , velLimite, velCarro;

Como dados de saída temos dois mapas. O primeiro é uma listagem com o
número da carta de condução e o valor da multa. Essa informação está
associada a variável:

float valMulta;

O segundo é uma listagem com o valor arrecadado com as multas. Essa


informação está associada a variável:

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 212


Fundamentos de Programação em C: Uma Abordagem Algorítmica

float TotValArrecadado;

Como não conhecemos o número de multas que iremos processar, utilizaremos


um sentinela de fim de leitura associada à carta de condução.

#define SENTINELA 0

No próximo passo, vamos descrever as acções que devem ser implementadas


como subprogramas.

De forma análogo ao exercício anterior, deixamos como exercício o


desenvolvimento dos algoritmos: lerCartaConducao(), lerVelCarro() e
lerVelLimite().

O subprograma para calcular a velocidade em excesso, que denominamos por


velocidadeExcesso(), recebe a velocidade do carro e a velocidade limite.
Retorna a velocidade em excesso. Conceitualmente, estamos em presença de
uma função cuja solução pode ser descrita pelos seguintes passos:

1- calcular velExcesso = velCarro - velLimite;


2- retornar velExcesso;

O subprograma para verificar se é infractor, que denominamos por isinfractor(),


recebe a velocidade do carro e a velocidade limite. Retorna verdadeiro se a
velocidade do carro for maior do que a velocidade limite e falso no caso contrário.
Faça como exercício.

O subprograma para calcular a percentagem da velocidade em excesso, que


denominamos por percVelocidade(), recebe a velocidade em excesso, e retorna
o valor da percentagem que essa velocidade representa relação a velocidade
limite. Conceitualmente, estamos em presença de uma função cuja solução pode
ser descrita pelos seguintes passos:

1- calcular percent = (velExecesso * 100) / velLimite;


2- retornar percent;

O subprograma para calcular o valor da multa, que denominamos por


valorDaMulta(), recebe a percentagem da velocidade em relação a velocidade
limite e retorna o valor da multa. Conceitualmente, estamos em presença de uma
função cuja solução pode ser descrita pelos seguintes passos:

1- se percent <= 10.00 então


2- armazenar 0.0 no valor da multa;
3- senão se percent <= 20.00 então
4- armazenar 15000.00 no valMulta;
5- senão
6- armazenar 30000.00 no valMulta;
7- retornar valMulta

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 213


Fundamentos de Programação em C: Uma Abordagem Algorítmica

O subprograma para calcular o total arrecadado, que denominamos por


valTotArrecadado(), recebe o valor da multa e o valor arrecadado. Retorna o
valor arrecadado até momento. O valor arrecadado é importado e exportado pelo
subprograma, e pelo exemplo anterior, vimos que devemos implementa-lo como
uma função. Uma possível solução para este problema pode ser descrita pelo
seguinte passo:

1- calcular valArrecadado = valArrecadado + valMulta;


2- retornar valArrecadado;

O subprograma para imprimir multa na tela, que denominamos por


imprimirMulta(), recebe a carta de condução e o valor da multa. Não devolve
nenhuma informação. Conceitualmente, estamos em presença de um
procedimento, cuja solução pode ser descrita pelo seguinte passo:

1- imprimir (cartaConducao , valorMulta);

O subprograma imprimir valor total arrecadado, que denominamos por


totalArrecadado(), recebe o valor total das multas arrecadadas. Não devolve
nenhuma informação. Conceitualmente, estamos em presença de um
procedimento, cuja solução pode ser descrita pelo seguinte passo:

1- imprimir (valArrecadado);

Como todas as linhas dos algoritmos estão claras e não possuem qualquer
ambiguidade, estamos em condições de converte-los para um programa na
linguagem C.

/*-------------------------------------------------------------------------------------------------------
Objectivos: imprimir um relatório com o valor das multas e os pontos perdidos na
carteira de motoristas dos infractores. No fim do relatório adicionar uma linha com
as estatísticas
-------------------------------------------------------------------------------------------------------*/
##include <stdio.h> /* incluir as funções scanf() e printf() */
#include <stdlib.h> /* incluir a função system() */
#define SENTINELA 0
#define TRUE 1
#define FALSE 0

/*-------------------------------------------------------------------------------------------------------
Protótipos de funções
-------------------------------------------------------------------------------------------------------*/
int lerCartaConducao ();
int lerVelCarro ();
int lerVelLimite ();
int isInfractor(int velCarro , int velLimite);
int velExcesso (int velCarro , int velLimite);
float percentVelocidade (int velExcesso , int velLimite);
float valDaMulta (float percent);
float valArrecadado (float valMulta , float valTotMultas);

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 214


Fundamentos de Programação em C: Uma Abordagem Algorítmica

void imprimirMulta (float valMulta);


void totArrecadado (float valTotMultas);

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler número da carta de condução
Recebe: Nada
Retorna: Número da carta de condução
-------------------------------------------------------------------------------------------------------*/
int lerCartaConducao ()
{
/* faca como exercício */
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Verificar se é infrator
Recebe: velocidade do carro e velocidade limite
Retorna: verdadeiro ou falso
-------------------------------------------------------------------------------------------------------*/
int isInfrator (int velCarro , int velLimite)
{
if (velCarro <= velLimite)
return FALSE;
else
return TRUE;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler velocidade do carro
Recebe: Nada
Retorna: Velocidade do carro
-------------------------------------------------------------------------------------------------------*/
int lerVelCarro ()
{
int velocidade;
while (1)
{
printf (" \n Entre com a velocidade do carro: ");
scanf ("%d", &velocidade);
if (velocidade > 0) break;
printf ( “\n Erro: Velocidade não permitida “);
}
return velocidade;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Ler velocidade limite
Recebe: Nada
Retorna: Velocidade limite
-------------------------------------------------------------------------------------------------------*/

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 215


Fundamentos de Programação em C: Uma Abordagem Algorítmica

int lerVelLimite ()
{
int velocidade;
while (1)
{
printf (" \n Entre com a velocidade limite : ");
scanf ("%d",&velocidade);
if (velocidade > 0 ) break;
printf ( “\n Erro: Velocidade limite não permitida “);
}
return velocidade;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a velocidade em excesso
Recebe: velocidade do carro e a velocidade limite
Retorna : Velocidade em excesso
-------------------------------------------------------------------------------------------------------*/
int velExcesso (int velCarro , int velLimite)
{
return velCarro - velLimite;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular a percentagem da velocidade em excesso
Recebe: Velocidade em excesso e a velocidade limite
Retorna: Percentagem dessa velocidade
-------------------------------------------------------------------------------------------------------*/
float percentVelocidade (int velExcesso , int velLimite)
{
return (velExcesso * 100.00) / velLimite;
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Calcular o valor da multa
Recebe: Percentagem
Retorna: Valor da multa
-------------------------------------------------------------------------------------------------------*/
float valorDaMulta (float percent)
{
float multa;
if (percent <= 10.0)
multa = 0.0;
else if (percent <= 20.0)
multa = 15000.0;
else
multa = 30000.0;
return multa;

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 216


Fundamentos de Programação em C: Uma Abordagem Algorítmica

/*-------------------------------------------------------------------------------------------------------
Objectivo: Actualizar o total de multas arrecadadas
Recebe: valor da Multa e o valor total de multas arrecadas
Retorna : total de multas actualizado
-------------------------------------------------------------------------------------------------------*/
float valArrecadado ( float valMulta , float valTotMultas);
{
return (valTotMultas + valMulta);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir uma linha com os dados de uma multa
Recebe: Carta condução e o valor da multa
Retorna: Nada
-------------------------------------------------------------------------------------------------------*/
void imprimirMulta (int carta , float valMulta)
{
printf (" \n Numero carta Conducao %d ", carta);
printf (" \n Valor da multa %12.2f ", valMulta);
}

/*-------------------------------------------------------------------------------------------------------
Objectivo: Imprimir uma linha com o valor arrecadado
Recebe: Valor total de multas
Retorna: Nada
-------------------------------------------------------------------------------------------------------*/
void totArrecadado ( float valTotMultas)
{
printf (" \n Valor total das multas %.2f ", valTotMultas);
}

/*-------------------------------------------------------------------------------------------------------
Função principal
-------------------------------------------------------------------------------------------------------*/
int main ()
{
int carta , velCarro , velLimite , velExcesso , percent;
float valMulta , valTotMultas = 0.0;
while ((carta = LerCartaConducao()) != SENTINELA )
{
velCarro = lerVelCarro();
velLimite = lerVelLimite()
if (isinfrator (velCarro , velLimite) == TRUE)
{
velExcesso = velExcesso(velCarro ,velLimite );
percent = percentVelocidade (velExcesso , velLimite);

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 217


Fundamentos de Programação em C: Uma Abordagem Algorítmica

valMulta = valorDaMulta (percent);


valTotMultas = valArrecadado (valMulta , valTotMultas);
imprimirMulta(carta , valMulta);
}
else
printf ("\Erro: não infractor");
}
totArrecadado (valTotMultas);
system("PAUSE");
return 0;
}

Manuel Menezes- Faculdade de Engenharia da Universidade Católica de Angola 218

Você também pode gostar