5 - ESTRUTURAS DE CONTROLE
5.1.
LAÇOS
Os
laços são estruturas de programação em forma fechada, cuja execução geralmente
é feita de modo repetitivo. A execução destes trechos de programa pode ser
controlada de forma automática com comandos tais como FOR, WHILE e REPEAT (estes laços serão tratados
neste texto), ou então com auxílio de instruções de desvio (não serão tratados
neste texto).
Os
laços formados com estrutura de repetição automática são os mais usados e
pertencem a uma de duas categorias:
1
- Laços com número prefixado de iterações - escritos em PASCAL com auxílio do
comando FOR e
2
- Laços com número não fixado de iterações - escritos em PASCAL com auxílio dos
comandos WHILE ... DO e REPEAT ... UNTIL.
Em
ambos os casos, os laços podem depender apenas de valores internos ao programa
ou então ser mais abrangentes e depender de valores externos (quando utilizam
variáveis cujo valor é obtido do meio exterior com auxílio de um comando de
leitura).
5.1.1. LAÇOS COM NUMERO PREFIXADO DE
ITERAÇÕES
Os
laços com número prefixado de iterações são utilizados quando já se conhece com
exatidão, pela natureza do problema a ser resolvido, o número de vezes que um
determinado comando (ou grupo de comandos) deve ser executado.
Na
linguagem PASCAL estes laços são escritos com a utilização do comando FOR.
Suponhamos,
a título de ilustração, que devemos encontrar uma solução para o seguinte
problema:
Escrever
um programa PASCAL que leia quatro (04) valores inteiros e, para cada um dos
valores imprima:
- o valor lido;
- o quadrado do valor;
- o cubo
do valor.
Uma possível solução seria:
PROGRAM GRANDE;
VAR
V1,
V2, V3, V4, Q1, Q2, Q3, Q4, CB1, CB2, CB3, CB4: INTEGER;
/*
Cada Vi representa um valor lido */
/*
Cada Qi representa o quadrado do valor Vi */
/*
Cada Cbi representa o cubo do valor Vi */
BEGIN
/* PARA O PRIMEIRO VALOR... */
WRITELN('INFORME
UM VALOR INTEIRO');
READLN(V1);
Q1
:= SQR(V1);
CB1 := V1 * Q1;
WRITELN('VALOR 1=', 'QUADRADO=', Q1,
'CUBO=', CB1);
/* PARA O SEGUNDO VALOR... */
WRITELN('INFORME
UM VALOR INTEIRO');
READLN(V2);
Q2
:= SQR(V2);
CB2 := V2 * Q2;
WRITELN('VALOR
2=', V2, 'QUADRADO=', Q2, 'CUBO=', CB2);
/* PARA O TERCEIRO VALOR ... */
WRITELN('INFORME
UM VALOR INTEIRO');
READLN(V3);
Q3
:= SQR(V3);
CB3 := V3 * Q3;
WRITELN('VALOR3=', V3, 'QUADRADO=', Q3,
'CUBO=', CB3);
/* FINALMENTE, PARA O QUARTO VALOR... */
WRITELN('INFORME
UM VALOR INTEIRO');
READLN(V4);
Q4
:= SQR(V4);
CB4 := V4 * Q4;
WRITELN('VALOR 4=', V4, 'QUADRADO=', Q4,
'CUBO=', CB4)
END.
A solução
anterior pode e deve ser melhorada de várias maneiras. Primeiro, a leitura dos
quatros valores poderia ser feita de uma só vez. Segundo, como após a impressão
dos valores referentes a cada número lido, os valores não mais são utilizados,
não haveria necessidade de várias variáveis para armazenamento dos quadrados e
dos cubos - isto poderia ser feito com apenas duas variáveis (Q e CB,
respectivamente). Desta forma, o programa melhorado seria:
PROGRAM MELHORADO;
VAR
V1,
V2, V3, V4, Q, CB: INTEGER;
/*
Cada Vi representa um valor lido */
/* Q
representa um quadrado, em cada instante */
/*
CB representa um cubo, em cada instante */
BEGIN
/* PARA O PRIMEIRO VALOR... */
WRITELN('INFORME
QUATRO VALORES INTEIROS');
READLN(V1,
V2, V3, V4);
Q :=
SQR(V1);
CB := V1 * Q;
WRITELN('VALOR
1=', V1, 'QUADRADO=', Q, 'CUBO=',CB);
/* PARA O SEGUNDO VALOR... */
Q :=
SQR(V2);
CB := V2 * Q;
WRITELN('VALOR
2=',V2,'QUADRADO='Q,'CUBO=',CB);
/* PARA O TERCEIRO VALOR ... */
Q :=
SQR(V3);
CB := V3 * Q;
WRITELN('VALOR3=', V3, 'QUADRADO=', Q,
'CUBO=', CB);
/* FINALMENTE, PARA O QUARTO VALOR ... */
Q :=
SQR(V4);
CB := V4 * Q;
WRITELN('VALOR 4=', V4, 'QUADRADO=', Q,
'CUBO=', CB);
END.
Por
outro lado, como os valores dos quadrados (Q) e dos cubos (CB) estão sendo utilizados
apenas temporariamente até a hora da impressão e, neste caso, não têm nenhuma
outra finalidade, estes cálculos podem ser efetuados diretamente nos comandos
de impressão, mesmo perdendo um pouco da legibilidade do programa que passa a
ser:
PROGRAM DIRETO;
VAR
V1,
V2, V3, V4: INTEGER;
/*
CADA Vi REPRESENTA UM VALOR LIDO */
BEGIN
WRITELN('INFORME
QUATRO VALORES INTEIROS');
READLN(V1,
V2, V3, V4);
/* PARA O PRIMEIRO VALOR... */
WRITELN('VALOR
1=', V1, 'QUADRADO=', SQR(V1), 'CUBO=', V1 * SQR(V1));
/* PARA O SEGUNDO VALOR... */
WRITELN('VALOR=', V2, 'QUADRADO=', SQR(V2),
'CUBO=', V2 * SQR(V2));
/* PARA O TERCEIRO VALOR... */
WRITELN('VALOR3=', 'QUADRADO=', SQR(V3),
'CUBO=',V3 * SQR(V3));
/* PARA O QUARTO VALOR... */
WRITELN('VALOR4=', V4, 'QUADRADO=', SQR(V4),
'CUBO=', V4 * SQR(V4));
END.
Nenhuma
das soluções anteriores, entretanto, é adequada ao problema caso queiramos
modificar o programa anterior de maneira que ele passe a funcionar para
cinqüenta valores.
Neste
caso, a melhor opção passa a ser a utilização do comando FOR. Com este comando, o programa DIRETO, que funciona para quatro valores, poderia ser reescrito da
seguinte maneira, lendo um valor de cada vez:
PROGRAM PEQUENO;
VAR
V, Q, CB, K: INTEGER;
/* V representa um valor lido, em cada
instante */
/* Q representa um quadrado, em cada
instante */
/* CB representa um cubo, em cada instante
*/
BEGIN
/*
PARA O K-ésimo valor ... */
FOR K := 1 TO 4 DO
BEGIN
WRITELN('INFORME UM VALOR
INTEIRO');
READLN(V);
WRITELN('VALOR=',
V, 'QUADRADO=', SQR(V),'CUBO=', V * SQR((V))
END
END.
Para
modificar o programa PEQUENO de modo
que funcione para cinqüenta valores inteiros, e atenda ao solicitado, a única
mudança necessária é substituir o número 4 pelo número 50 no comando FOR.
COMO UTILIZAR O COMANDO FOR.
Como já
afirmamos anteriormente, o comando FOR
destina-se à repetição automática de um (01) comando PASCAL, enquanto que uma
série de valores é atribuída à variável de controle, e aplica-se ao comando que
o segue. O comando a ser executado pelo comando FOR pode ser qualquer comando simples ou composto. Um comando
composto é formado por qualquer grupo de comandos delimitado por um par BEGIN ... END, podendo ser
utilizado em qualquer ponto do programa onde possa vir um comando PASCAL.
A forma geral do comando FOR é:
FOR id := VrInic {TO } VrFin DO
{DOWNTO}
Comando;
Onde:
FOR - é uma palavra reservada em
PASCAL - identifica o comando FOR;
id - é um identificador (nome de
variável);
VrInic - é o valor inicial que será
atribuído à variável de controle (não necessariamente será 1), podendo ser de
qualquer tipo escalar simples, exceto REAL;
TO - é uma palavra reservada, parte
integrante do comando FOR;
DOWNTO - é uma palavra reservada, parte
integrante do comando FOR;
VrFin - é o valor final a ser atribuído
à variável de controle;
Comando - é o comando a ser repetido.
A
variável de controle (id) deve ser
do mesmo tipo (qualquer tipo simples, exceto REAL) que o valor inicial e que o
valor final.
A opção
TO indica que os valores serão
atribuídos em ordem crescente à variável de controle: caso VrFin seja menor que VrInic,
o comando FOR não terá nenhum efeito
- o comando que o segue não será executado.
A opção
DOWNTO indica que os valores serão
atribuídos em ordem decrescente à variável de controle: caso VrInic seja menor que VrFin, o comando que segue o FOR não será executado.
É
importante lembrar que a variável de controle não pode ter seu valor alterado
dentro do domínio do comando FOR
pois isso traria resultados imprevisíveis. Por outro lado, o valor da variável
de controle não deve ser utilizado após a execução completa do comando FOR pois
este valor dependerá do compilador que estiver sendo utilizado e pode ser
indefinido em alguns casos.
Em
algumas situações será interessante utilizar o valor da variável de controle
para indicar o número da iteração que está sendo executada em um dado instante.
Por exemplo, o segundo comando de impressão do programa PEQUENO poderia ser reescrito
como:
WRITELN('VALOR',
K, '=', V, 'QUADRADO=', QR(V), 'CUBO=', V * SQR(V));
Esta modificação faria com que a
cada nova execução do comando acima, fosse impresso um novo valor da variável K - este valor corresponde em cada
instante ao número da atual iteração visto que a variável de controle teve
valor inicial igual a um (01).
OUTRO EXEMPLO
Anteriormente
apresentamos um programa para cálculo da média parcial de um aluno da
disciplina Introdução à Ciência da Computação. O que seria necessário fazer com
o programa de modo que ele calculasse a média parcial para cinqüenta (50)
alunos? A solução seria introduzir um comando FOR para repetir cinqüenta vezes o trecho de programa que calcula a
média para um só aluno. Assim o novo programa seria:
PROGRAM MEDIAS;
VAR
P1,
P2, E1, E2, E3, E4, M_PARCIAL: REAL;
/* P1 e P2 São as provas parciais */
/* Cada Ei representa a nota da i-ésima lista
de exercícios */
K:
INTEGER;
M_PROVAS,
M_EXERC: REAL;
BEGIN
FOR K := 1 TO 50 DO
BEGIN
WRITELN('INFORME
AS NOTAS DAS DUAS PROVAS');
READLN(P1,
P2);
WRITELN('INFORME AS NOTAS DOS QUATRO EXERCICIOS');
READLN(E1,
E2, E3, E4);
M_PROVAS
:= (P1 + P2) / 2.0;
M_EXERC
:= (E1 + E2 + E3 + E4) / 4.0;
M_PARCIAL
:= M_PROVAS * 0.8 + M_EXERC * 0.2;
WRITELN('PROVA1=',
P1: 5: 1, 'PROVA2=', P2: 5: 1);
WRITELN('EXERCICIO1=', E1: 5: 1, 'EXERCICIO2=',
E2: 5: 1,
'EXERCICIO3=', E3: 5: 1, 'EXERCICIO4=',
E4: 5: 1);
WRITELN('MEDIA
PARCIAL=', M_PARCIAL: 6: 2)
END
END.
5.1.2.
LAÇOS COM NUMERO NÃO FIXADO DE ITERAÇÕES
Os
laços com número não fixado de iterações são utilizados quando não se conhece
com exatidão o número de vezes que um determinado comando (simples ou composto)
deve ser executado. Nestas situações, em função do tipo de problema a ser
resolvido, o número de iterações é dependente de computações internas ao
programa. Em PASCAL estes laços são escritos utilizando os comandos WHILE ... DO e REPEAT ... UNTIL.
WHILE
... DO
Como
exemplo inicial, consideremos o seguinte problema:
Escrever
um programa PASCAL que leia valores inteiros seguidamente, até encontrar um
valor nulo. Para cada valor lido, exceto o último, o programa deve imprimir: o
valor lido, o quadrado do valor e o seu cubo.
Utilizando
o comando WHILE na solução, obtemos:
PROGRAM REPETITIVO;
VAR VALOR: INTEGER;
BEGIN
/* PARA O PRIMEIRO VALOR ... */
WRITELN('INFORME
UM VALOR INTEIRO');
READLN
(VALOR);
/* PARA TODOS OS VALORES, EXCETO O
ULTIMO...*/
WHILE
VALOR <> 0 DO
BEGIN
WRITELN('VALOR
LIDO=', VALOR, 'QUADRADO=',
SQR(VALOR), 'CUBO=', VALOR * SQR(VALOR));
READLN(VALOR)
END
END.
Ao
analisar a solução apresentada, você constatará que o último valor lido
atenderá ao solicitado na condição do comando WHILE e não mais será repetida a execução do trecho de programa
dependente do comando WHILE. Observe
que o trecho de programa será repetido enquanto não for lido um valor nulo. A
forma geral do comando WHILE é:
WHILE condição DO
comando;
Onde:
WHILE - é uma palavra reservada em
PASCAL - identifica o comando WHILE;
Condição - é uma condição lógica que
deverá possuir no mínimo uma variável que obrigatoriamente já terá sido
definida e cujo valor deverá mudar dentro do comando a ser repetido - do contrário
poderá ser obtido um laço infinito;
DO - é uma palavra reservada da
linguagem PASCAL - seu uso é obrigatório como parte integrante do comando WHILE;
Comando - é o comando a ser repetido,
podendo ser um comando simples ou composto.
O
comando que segue o WHILE será
repetido enquanto a condição for verdadeira - se o valor da condição for falso
no início da execução, o comando não será executado. Considerando-se o fato de
o comando que segue o WHILE não ser
executado quando a condição for falsa, recomendamos a utilização do comando WHILE apenas para os laços onde não se
deseja levar em consideração nos cálculos o último de uma seqüência de valores.
Ao
utilizar o comando WHILE o
programador não pode esquecer que a variável que aparece na condição deve ter
sido declarada e definida antes de ser utilizada na condição.
REPEAT
... UNTIL
A
exemplo do que ocorre com o comando WHILE
, o comando REPEAT ... UNTIL é utilizado quando não se conhece com exatidão o número de
vezes que um determinado comando (simples ou composto) deve ser repetido.
As
diferenças básicas no processamento são devidas ao fato de no comando WHILE o teste de parada ser efetuado no
início do laço enquanto que no REPEAT
o teste é efetuado no final do laço e, portanto, após a execução do comando
(simples ou composto). Como conseqüências do teste no final do comando REPEAT temos:
1)
O comando (simples ou composto) será executado no mínimo uma
vez; e
2)
a facilidade de inclusão do último de uma seqüência de
valores no processamento. As variáveis da condição do comando REPEAT não necessitam ser definidas
antes do início do REPEAT e, deste
modo, sua definição ocorrerá exatamente no início do REPEAT.
A forma geral do comando REPEAT é
REPEAT
comando
UNTIL condição;
Onde:
REPEAT - é uma palavra reservada -
identifica o comando REPEAT;
comando -
é o comando (ou grupo de comandos - os delimitadores BEGIN ... END são opcionais, neste caso) a ser
executado;
UNTIL - é uma palavra reservada de uso
obrigatório;
condição - é uma condição lógica que
deverá possuir no mínimo uma variável e cujo valor deverá mudar dentro do
comando a ser repetido - do contrário, poderá ser obtido um laço infinito.
Considere
o problema:
Determinar
a temperatura média de João Pessoa em um certo período, sabendo-se que a última
temperatura a ser informada é de 40 graus.
Como
não sabemos com exatidão quantas temperaturas serão informadas, não podemos
utilizar o comando FOR. Da mesma
forma, como o último dos valores deve ser considerado nos cálculos então o comando
WHILE não é uma boa escolha: a opção
mais recomendável é utilizar o comando REPEAT.
O nosso programa será:
PROGRAM TEMPERATURA;
VAR
TEMP:
REAL; /* CADA TEMPERATURA SENDO
PROCESSADA */
SOMA:
REAL; /* A SOMA DE TODAS AS TEMPERATURAS
*/
TEMP_MED:
REAL; /* A TEMPERATURA MÉDIA */
N_TEMP: INTEGER; /* O NUMERO DE TEMPERATURAS INFORMADAS */
BEGIN
N_TEMP
:= 0; /* AINDA NÃO FOI INFORMADA NENHUMA TEMPERATURA*/
SOMA
:= 0; /* A SOMA INICIAL DAS TEMPERATURAS
*/
REPEAT
WRITELN('INFORME
UMA TEMPERATURA');
READLN(TEMP);
N_TEMP
:= N_TEMP + 1; /*FOI LIDA UMA NOVA TEMPERATURA
*/
SOMA
:= SOMA + TEMP; /* ACUMULA A TEMPERATURA LIDA */
WRITELN('TEMPERATURA
LIDA=',TEMP: 5: 1);
UNTIL
TEMP = 40.0;
/*A TEMPERATURA MÉDIA SERÁ DETERMINADA UMA
ÚNICA VEZ */
TEMP_MED := SOMA / N_TEMP;
WRITELN('TEMPERATURA MEDIA', TEMP_MED: 6: 2)
END.
Sugerimos
implementar e testar o programa TEMPERATURA
no computador. Que modificações seriam recomendáveis caso não se desejasse
incluir a última temperatura no cálculo da temperatura média?
5.2.
DESVIOS
A
implementação de decisões sobre que caminho deve ser seguido em um dado ponto
de um programa PASCAL é feita com a utilização de comandos condicionais. Os
comandos condicionais permitem escolher entre rotas alternativas de um trecho
de programa ou então desviar um comando ou bloco de comandos, em função de
alguma condição lógica cujo valor é determinado na hora da execução do
programa.
5.2.1.
DESVIOS CONDICIONAIS
Os
desvios condicionais são os mais utilizados em programação. Os desvios
condicionais são representados em PASCAL pelo comando IF e pelo comando CASE.
O COMANDO IF
O comando IF pode ser do tipo simples, quando tem
a forma geral:
IF condição THEN
comando;
Onde:
IF - é uma palavra reservada que
identifica o comando IF;
condição - é uma condição lógica qualquer
válida em PASCAL;
THEN - é uma palavra reservada em
PASCAL - é parte integrante do comando IF;
Comando - é um comando (simples ou composto)
que deverá ser executado apenas se a condição for verdadeira;
O comando IF pode
ser também do tipo composto, quando tem a forma geral:
IF condição
THEN
comando1
ELSE
comando2;
Onde:
IF - é uma palavra reservada da
linguagem PASCAL - identifica o comando
IF;
condição - é uma condição lógica qualquer
válida em PASCAL;
THEN - é uma palavra reservada da
linguagem PASCAL - é parte integrante do comando IF composto;
comando1 - é o comando a ser executado
caso o valor resultante da avaliação da condição seja TRUE. Pode ser
um comando simples ou composto;
ELSE - é uma palavra reservada de uso
obrigatório - é parte integrante do comando IF composto;
comando2 - é o comando, simples ou
composto, a ser executado caso o valor resultante da avaliação da condição seja
FALSE.
O programa apresentado a
seguir exemplifica a utilização do comando IF:
PROGRAM SIMPLES;
/*
DETERMINAR O MAIOR ENTRE DOIS INTEIROS */
VAR
A,
B: INTEGER; /* OS INTEIROS QUE SERÃO
LIDOS E COMPARADOS */
BEGIN
WRITELN('INFORME
DOIS VALORES INTEIROS');
READLN(A,
B);
WRITELN('OS VALORES LIDOS FORAM:', A: 5, 'E ', B: 5);
WRITE('O
MAIOR DOS DOIS VALORES');
IF
A > B
THEN WRITE ('EH:', A: 5)
ELSE BEGIN
IF B > A THEN WRITE('EH:', B: 5)
ELSE WRITE('NÃO PODE SER DETERMINADO: SÃO
IGUAIS')
END
END.
Mas, se
o problema fosse encontrar o maior de um grupo de 20 valores distintos, qual
seria a solução? Vamos considerar os valores: 16, 3, 110, 7, 109, 151, 18, 100,
0 , -5, 3, 40, 19, 101, 25, 29, 103, 107, 210 e 190.
Inicialmente,
afirmamos que 16 é o maior até agora e determinamos o maior entre 16 e 3
através de uma comparação simples. A seguir, determinamos o maior entre 16
(maior até agora) e 110. Continuamos fazendo isto até chegar ao último dos
valores. Como as ações serão sempre as mesmas para cada número do grupo, a
partir do segundo, podemos utilizar um comando de repetição automática. Por
outro lado, a quantidade de repetições é previamente conhecida e a opção passa
a ser o comando FOR. O programa
teria possivelmente a forma:
PROGRAM
MAIOR;
/* DETERMINA O MAIOR DE 20 INTEIROS
DISTINTOS */
VAR
VALOR_ATUAL: INTEGER; /* O VALOR QUE ESTÁ SENDO PROCESSADO */
MAIOR_ATE_AGORA: INTEGER; /* O MAIOR VALOR
DENTRE OS PROCESSADOS */
K:INTEGER; /*
UMA VARIÁVEL AUXILIAR PARA O FOR */ BEGIN
WRITELN('INFORME UM VALOR INTEIRO');
READLN(VALOR_ATUAL); /* O PRIMEIRO DOS VALORES */
MAIOR_ATE_AGORA := VALOR_ATUAL; /*SO FOI LIDO UM VALOR ...*/
FOR K := 1 TO 19 DO /* PARA OS OUTROS 19 VALORES ...*/
BEGIN
WRITELN('INFORME UM VALOR INTEIRO');
READLN(VALOR_ATUAL);
IF VALOR_ATUAL > MAIOR_ATE_AGORA
THEN
MAIOR_ATE_AGORA := VALOR_ATUAL;
WRITELN('VALOR LIDO=', VALOR_ATUAL: 6)
END;
WRITELN('O MAIOR DOS VALORES LIDOS EH:', MAIOR_ATE_AGORA')
END.
Sugerimos
implementar e testar o programa MAIOR
no computador. Modifique o programa MAIOR
de forma que ele determine o maior dos 2 primeiros, o maior dos 3 primeiros,
... o maior dos 19 primeiros e o maior dos 20 valores. Implemente e teste no
computador a solução obtida.
O COMANDO CASE
O
comando CASE é uma estrutura de
controle que permite a seleção de um entre vários caminhos alternativos para execução
em um programa PASCAL - tem, portanto, o mesmo efeito que uma série de comandos
IF aninhados.
A
seleção do comando a ser executado é feita comparando-se o valor da
expressão_seletora com os vários rótulos do CASE.
A forma
geral do comando CASE é:
CASE expressão_seletora OF
lista_de_rótulos_1: comando_1;
lista_de_rótulos_2: comando_2;
.
.
.
lista_de_rótulos_n: comando_n
END;
Onde:
CASE -- é uma palavra reservada em
PASCAL - identifica o comando CASE; expressão_seletora
- é uma expressão ou variável de qualquer tipo escalar
simples exceto REAL;
OF - é uma palavra reservada em
PASCAL - é parte integrante do comando CASE;
lista_de_rótulos_i - é uma lista contendo uma
ou mais constantes de tipo compatível com o tipo da expressão_seletora, separadas por vírgula;
comando_i - é um comando PASCAL qualquer
(simples ou composto) que será
executado caso o valor calculado para expressão_seletora
seja igual a uma das constantes da lista_de_rótulos_i,
podendo inclusive ser um comando vazio.
Cada
rótulo que aparece em uma lista_de_rótulos
deve ser de tipo compatível com o tipo da expressão_seletora
e só pode aparecer em uma única lista_de_rótulos
para cada comando CASE.
Só será
executado algum comando das várias opções especificadas no comando CASE se o valor computado para a expressão_seletora for igual a um dos
rótulos especificados. A ação a ser desenvolvida quando o valor da expressão_seletora divergir de todos os
rótulos especificados nas listas_de_rótulos
do comando CASE dependerá do
compilador que estiver sendo utilizado: alguns compiladores dispõem da opção OTHERWISE (ou a forma equivalente ELSE) para especificar o comando que
deve ser executado quando o valor da expressão_seletora
for diferente de todos os rótulos especificados nas várias listas_de_rótulos.
O
programa apresentado a seguir foi escrito para uma Pousada que desejava
conceder descontos progressivos aos seus clientes. Os descontos são de 10, 20,
30 e 35 por cento para os clientes que se hospedarem por 1, 2, 3 e por 4 ou
mais dias, respectivamente. A entrada para o programa de computador é formada
pelo valor da diária e pelo número de diárias.
Utilizando
um ninho de comandos IF poderíamos
ter:
PROGRAM
POUSO_VELHO;
CONST
TFAIXA1 = 1;
FAIXA2 = 2;
FAIXA3 = 3;
FAIXA4 = 4..30;
VAR
VALOR_DA_DIARIA, SUB_TOTAL, SERVIÇOS: REAL;
VALOR_DA_NOTA, DESCONTO, VALOR_A_PAGAR: REAL;
QUANT_DIARIAS: INTEGER;
BEGIN
WRITELN('INFORME O VALOR DA DIARIA E A
QUANTIDADE DE DIARIAS');
READLN(VALOR_DA_DIARIA, QUANT_DIARIAS);
SUB_TOTAL := QUANT_DIARIAS *
VALOR_DA_DIARIA;
SERVIÇOS := SUB_TOTAL * 0.1; /* DEZ POR
CENTO */
VALOR_DA_NOTA := SUB_TOTAL + SERVIÇOS; /* CALCULO DO DESCONTO */
IF QUANT_DIARIAS = FAIXA1
THEN DESCONTO := 0.1 * VALOR_DA_NOTA
ELSE IF QUANT_DIARIAS = FAIXA2
THEN DESCONTO := 0.2 *
VALOR_DA_NOTA
ELSE IF QUANT_DIARIAS = FAIXA3
THEN DESCONTO := 0.3 *
VALOR_DA_NOTA
ELSE DESCONTO := 0.35 *
VALOR_DA_NOTA;
/* CALCULO DO VALOR A PAGAR E SAIDA DOS RESULTADOS
*/
VALOR_A_PAGAR := VALOR_DA_NOTA - DESCONTO;
WRITELN('NUMERO DE DIAS: ', QUANT_DIARIAS:
3, 'VALOR DA DIARIA:',
VALOR_DA_DIARIA:
8: 2, 'SUB_TOTAL: ', SUB_TOTAL: 9: 2);
WRITELN('SERVIÇOS: ', SERVIÇOS: 7: 2, 'VALOR
DA NOTA: ',
VALOR_DA_NOTA: 9: 2, 'DESCONTO: ', DESCONTO: 9:
2,
'VALOR A PAGAR: ', VALOR_A_PAGAR: 9: 2)
END.
Substituindo o ninho de IFs por um comando CASE, obtemos:
PROGRAM
POUSO_NOVO;
CONST
TFAIXA1 = 1;
FAIXA2 = 2;
FAIXA3 = 3;
FAIXA4 = 4 .. 30;
VAR
VALOR_DA_DIARIA, SUB_TOTAL, SERVIÇOS: REAL;
VALOR_DA_NOTA, DESCONTO, VALOR_A_PAGAR: REAL;
QUANT_DIARIAS: INTEGER;
BEGIN
WRITELN('INFORME O VALOR DA DIARIA E A
QUANTIDADE DE DIARIAS');
READLN(VALOR_DA_DIARIA, QUANT_DIARIAS);
SUB_TOTAL := QUANT_DIARIAS *
VALOR_DA_DIARIA;
SERVIÇOS := SUB_TOTAL * 0.1; /* DEZ POR
CENTO */
VALOR_DA_NOTA := SUB_TOTAL + SERVIÇOS; /* CALCULO DO DESCONTO */
CASE QUANT_DIARIAS OF
FAIXA1: DESCONTO := VALOR_DA_NOTA *
0.1;
FAIXA2: DESCONTO := VALOR_DA_NOTA *
0.2;
FAIXA3: DESCONTO := VALOR_DA_NOTA *
0.3;
FAIXA4: DESCONTO := VALOR_DA_NOTA *
0.35
END;
/* CALCULO DO VALOR A PAGAR E SAIDA DOS
RESULTADOS */
VALOR_A_PAGAR := VALOR_DA_NOTA - DESCONTO;
WRITELN('NUMERO DE DIAS: ', QUANT_DIARIAS:
3, 'VALOR DA DIARIA: ',
VALOR_DA_DIARIA: 8: 2, 'SUB_TOTAL: ',
SUB_TOTAL: 9: 2);
WRITELN('SERVIÇOS: ', SERVIÇOS: 7: 2, 'VALOR
DA NOTA: ',
VALOR_DA_NOTA: 9: 2, 'DESCONTO: ', DESCONTO:
9: 2,
'VALOR A PAGAR: ', VALOR_A_PAGAR: 9: 2)
END.
Comparando
as duas soluções você comprovará que a versão utilizando o comando CASE é mais legível que aquela
utilizando o comando IF.
5.2.2.
DESVIOS INCONDICIONAIS
Os
desvios incondicionais são implementados em PASCAL com a utilização do comando GOTO. O comando GOTO, quando é executado, desvia incondicionalmente a execução do
programa para algum ponto especificado no comando. Tendo em vista que os
desvios incondicionais tendem a obscurecer a lógica dos programas, a sua
utilização não é recomendada e por essa razão o comando GOTO não será aqui apresentado - o nosso objetivo será sempre
construir bons programas e isso só será conseguido quando nossos programas,
antes de tudo, forem programas fáceis de ler e de entender por pessoas e não
somente por máquinas.
Um bom
programa além de ser claro e fácil de ler, deve ser o mais genérico possível
(não ser aplicável apenas a situações específicas) e sempre fornecer resultados
corretos e confiáveis.
5.3.
EXERCICIOS PROPOSTOS
1. Escreva um programa em PASCAL que
a cada execução imprima dez vezes as informações do seu cartão pessoal.
2. Escreva um programa em PASCAL
que leia um número inteiro N e imprima N vezes as informações do seu cartão
pessoal.
3. Escreva um programa em PASCAL
para gerar os cinqüenta primeiros termos da série: 1, 1, 2, 4, 3, 9, 4, 16, 5,
25, 6, 36, ...
4. Escreva um programa em PASCAL
para gerar os cinqüenta primeiros termos da série: 2, 4, 4, 16, 6, 36, 8, 64,
..., e determinar a sua soma.
5. Escreva um programa em PASCAL
para gerar os cinqüenta primeiros termos da série: 1, 2, 4, 7, 11, 16, 22, ...
6. Escreva um programa em PASCAL
para gerar os cinqüenta primeiros termos da série: 1 + N, 2 * N, 3 + N, 4 * N,
..., onde N é um valor lido da unidade padrão de entrada.
7. Escreva um programa em PASCAL
para gerar os quinze primeiros termos da série de FIBONACCI: 1, 1, 2, 3, 5, 8,
13, ...
8. Escreva um programa em PASCAL
para imprimir os termos da série de FIBONACCI menores que 10000.
9. Escreva um programa em PASCAL
para ler um número inteiro N e, a seguir, gerar os N primeiros termos da série
de FIBONACCI com auxílio da fórmula:
fi = round(ci / Ö5), onde c = (1 + Ö 5) / 2.
10. Escreva um programa em PASCAL
que leia um número inteiro qualquer e determine se o número que foi lido é par
ou ímpar.
11. Escreva um programa em PASCAL
para ler vinte números inteiros e determinar se cada um desses números é par ou
ímpar.
12. Escreva um programa em PASCAL
para ler um número inteiro N e imprimir o valor lido e os N primeiros números
ímpares positivos.
13. Escreva um programa em PASCAL
para ler um número inteiro N e imprimir os N primeiros números pares positivos.
14. Escreva um programa em PASCAL
para ler um número inteiro K e imprimir os K primeiros números ímpares
positivos e sua soma.
15. Escreva um programa em PASCAL
para ler dois números inteiros M e N e, a seguir, imprimir os números pares
existentes no intervalo [M, N]. Lembre-se que nem sempre M é um número par.
16. Escreva um programa em PASCAL
para ler um número inteiro qualquer e determinar seu fatorial.
17. Escreva um programa em PASCAL
para determinar o fatorial de dez números inteiros quaisquer.
18. Escreva um programa em PASCAL
para ler seguidamente valores inteiros até que seja lido um valor nulo. Para
cada valor lido, o programa deve determinar seu fatorial.
19. Escreva um programa em PASCAL
para ler seguidamente valores inteiros até que seja lido um valor negativo.
Para cada valor lido, exceto o último, o programa deve determinar seu fatorial.
20. Escreva um programa em PASCAL
para determinar o número de combinações de n objetos tomados p a p, a partir de
valores de n e p lidos da unidade padrão de entrada.
Fórmula:
n n!
=
----------
p
p!(n - p)!
21. Escreva um programa em PASCAL
para calcular uma aproximação para Pi. A aproximação pode ser obtida de Pi = 4
- 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ... O programa deve encerrar o processamento
quando a variação no valor calculado for inferior a 0.0001.
22. Escreva programas em PASCAL para
cálculo da soma 1 - 1/2 + 1/3 - 1/4 + ... + 1/9999 - 1/10000 por adição dos
termos: - da esquerda para a direita; - da direita para a esquerda; - positivos
e dos termos negativos, separadamente, da esquerda para a direita; - positivos
e dos termos negativos, separadamente, da direita para a esquerda. O resultado
com dez casas decimais é 0.6930971830.
23. Escreva um programa para
calcular uma aproximação para cosseno(X), onde X é um valor inteiro lido da
unidade padrão de entrada. A aproximação pode ser obtida de cos(x) = 1 - X/2! +
X/4! - X/6! ... O programa deve encerrar o processamento quando a variação no
valor calculado for inferior a 0.001.
24. Escreva um programa em PASCAL
para calcular uma aproximação para seno(X), onde X é um valor inteiro lido da
unidade padrão de entrada. A aproximação pode ser obtida de: sen(X) = X - X/3!
+ X/5! - X/7! + ... O programa deve encerrar o processamento quando a variação
no valor calculado for inferior a 0.001.
25. Escreva um programa em PASCAL
para calcular uma aproximação para exp(X), onde X é um número qualquer lido da
unidade padrão de entrada. A aproximação pode ser obtida de: exp(X) = 1 + X +
X/2! + X/i!. O programa deve encerrar o processamento quando a variação no
valor calculado for inferior a 0.0001.
26. Escreva um programa em PASCAL
que imprima a tabela abaixo:
NUMERO
QUADRADO CUBO RAIZ QUADRADA RAIZ CUBICA
1.5
2.25 3.375 1.2247 1.1447
2.5
6.25 15.625 1.5811 1.3572
.
. . . .
.
. . . .
99.5
9900.25 985074.875 9.9749 4.6338
27. Escreva um programa em PASCAL
para imprimir uma tabela de temperaturas em graus Célsius e equivalentes em
Fahrenheit, de 0 C a 100 C.
28. Escreva um programa em PASCAL
para ler dez grupos de valores para A, B e C (variáveis do tipo REAL). Para
cada grupo de valores o programa deve imprimir os valores lidos e as raízes da
equação Ax2 + Bx + C = 0.
29. Escreva um programa em PASCAL
para ler quatro valores reais, imprimir o maior dos quatro valores e os valores
lidos, nesta seqüência.
30. Escreva um programa em PASCAL
para ler 50 valores inteiros aleatórios, imprimir os valores lidos e determinar
o maior dos valores lidos.
31. Escreva um programa em PASCAL
para ler cinqüenta valores inteiros aleatórios, imprimir os valores lidos e
determinar o menor dos valores lidos e sua posição no conjunto.
32. Escreva um programa em PASCAL
para ler N e a seguir ler N valores inteiros, imprimir os valores lidos e
determinar o maior e o menor dos N valores.
33. Escreva um programa em PASCAL
para ler N números inteiros, imprimir os números lidos e determinar a diferença
entre os dois maiores números lidos.
34. Escreva um programa em PASCAL
para ler e imprimir a idade de um grupo de 20 pessoas. Ao final, o programa
deve determinar a pessoa mais idosa, a mais jovem, e a média das idades do
grupo de pessoas.
35. Escreva um programa em PASCAL
que leia cinqüenta valores reais quaisquer, imprima os valores lidos e
determine qual o segundo menor dentre os valores, sem efetuar ordenação.
36. Escreva um programa em PASCAL
que leia cinqüenta valores reais quaisquer, imprima os valores lidos e
determine qual o segundo maior dentre os valores e sua posição no conjunto, sem
efetuar ordenação.
37. Escreva um programa em PASCAL
para ler três números reais quaisquer e imprimir estes números em ordem
numérica crescente.
38. Escreva um programa em PASCAL
para ler três valores inteiros, imprimir os valores lidos e determinar o valor
que não é o maior e que não é o menor dos três valores lidos.
39. Escreva um programa em PASCAL
para ler dez grupos de três valores inteiros cada, imprimir os valores lidos
identificado o valor que não é o maior e que não é o menor para cada um dos
grupos de três valores.
40. Escreva um programa em PASCAL
para ler vários grupos de três valores inteiros e determinar o valor que não é
o maior e que não é o menor para cada um dos grupos. O processamento deve ser
encerrado quando um dos três valores for negativo.
41. Escreva um programa em PASCAL
para ler oito valores reais, imprimir os valores lidos e determinar: - a média
dos números positivos; - a média dos números negativos; e - a soma de todos os
valores lidos.
42. Escreva um programa em PASCAL
para ler um valor inteiro K e calcular a média aritmética de K valores reais
lidos da unidade padrão de entrada. O programa deve imprimir os valores lidos e
a sua média aritmética.
43. Escreva um programa em PASCAL
para ler um número inteiro K, e a seguir ler K números inteiros, imprimir os
valores lidos e determinar a média aritmética dos valores ímpares e a média
aritmética dos valores pares existentes entre os valores lidos.
44. Escreva um programa em PASCAL
para ler um número desconhecido de valores reais e imprimir todos os valores
lidos, a soma dos valores lidos e a média aritmética dos valores. O
processamento encerra quando um mesmo valor for lido duas vezes consecutivas,
sem considerar uma destas leituras no processamento.
45. Escreva um programa em PASCAL
para ler vários grupos de 5 valores reais cada e calcular a média ponderada destes
valores, sabendo-se que o primeiro valor tem peso 4, o segundo e o terceiro têm
peso 2 e os dois últimos têm peso 1. O processamento encerra quando for lido um
grupo com todos os valores negativos, sem considerar este grupo de valores nos
cálculos. Para cada grupo de valores, o programa imprime os valores lidos e a
média ponderada.
46. Escreva um programa em PASCAL
que leia dois valores inteiros A e B (A sempre par e menor que B), calcule o
produtório dos números pares compreendidos entre A e B, inclusive. O programa
deve imprimir o produtório e a quantidade de elementos que compõem o
produtório.
47. Escreva um programa em PASCAL
para ler três números inteiros e imprimir todos os múltiplos do primeiro que
estejam compreendidos entre o segundo e o terceiro, inclusive. Assuma que
primeiro <= segundo <= terceiro.
48. Escreva um programa em PASCAL
para ler um número inteiro qualquer e determinar todos os seus divisores
exatos.
49. Escreva um programa em PASCAL
para ler vinte valores inteiros e imprimir cada um dos valores acompanhado de
todos os seus divisores exatos.
50. Escreva um programa em PASCAL
para ler quinze pares de valores inteiros e determinar o Máximo Divisor Comum
para cada um dos quinze pares de valores.
51. Escreva um programa em PASCAL
para cálculo do Mínimo Múltiplo Comum entre dois números inteiros lidos da
unidade padrão de entrada.
52. Escreva um programa em PASCAL
para ler um número inteiro N e a seguir ler N pares de valores inteiros. Para
cada um dos N pares de valores o programa deve determinar seu Mínimo Múltiplo
Comum.
53. Escreva um programa em PASCAL
para ler vários grupos de dois valores inteiros até encontrar dois valores
iguais. O programa deve imprimir cada par de valores acompanhado de seu Mínimo
Múltiplo Comum.
54. Escreva um programa em PASCAL
que leia um número inteiro qualquer e determine se o número lido é primo ou
não.
55. Escreva um programa em PASCAL
para ler um número inteiro N e imprimir os N primeiros números primos.
56. Escreva um programa em PASCAL
para determinar os números primos do intervalo [501, 1500].
57. Escreva um programa em PASCAL
para determinar os números primos do intervalo [M, N], onde M e N são valores
lidos da unidade padrão de entrada.
58. Escreva um programa em PASCAL
para ler um número inteiro qualquer e verificar se o número lido é primo. Em
caso afirmativo, o programa deve imprimir o fatorial do número. Caso o número
não seja primo, imprimir todos os seus divisores.
59. Escreva um programa em PASCAL
para ler seguidamente vários valores inteiros até encontrar um valor negativo
ou nulo. Para cada um dos valores lidos, exceto o último, o programa deve
informar se o valor é primo ou não.
60. Escreva um programa em PASCAL
para identificar os pares de números menores que 500 tais que o segundo seja
igual a 1 mais duas vezes o primeiro. Exemplo: 3 e 7.
61. Escreva um programa em PASCAL
para determinar um número inteiro N tal que N + 3N + 5 seja divisível por 121.
62. Escreva um programa em PASCAL
para ler dois números inteiros e determinar se eles são primos gêmeos. Dois
números são primos gêmeos se eles são primos e existe uma diferença de dois (2)
entre eles (11 e 13 são primos gêmeos).
63. Escreva um programa em PASCAL
que imprima os seis primeiros pares de primos gêmeos.
64. Escreva um programa em PASCAL
para determinar todos os pares de primos gêmeos menores que N, sendo N um valor
lido.
65. Escreva um programa em PASCAL
que leia um número inteiro qualquer e determine se esse número é perfeito ou
não. Um número é perfeito quando a soma de seus divisores, excetuando- se o
próprio número, for igual ao número.
66. Escreva um programa em PASCAL
para determinar todos os números perfeitos existentes entre 2 e 1000.
67. Escreva um programa em PASCAL
para ler dois números inteiros e determinar se eles são primos relativos. Dois
números são primos relativos (ou primos entre si) quando eles não têm nenhum
divisor comum (excetuando-se a unidade).
68. Escreva um programa em PASCAL
para determinar se um número inteiro de quatro dígitos é palíndromo perfeito.
Um número é palíndromo perfeito quando pode ser lido da direita para a esquerda
sem alterar seu valor, tal como 1661.
69. Escreva um programa em PASCAL
para determinar todos os números palíndromos perfeitos do intervalo [1000,
9999].
70. Escreva um programa em PASCAL
para identificar os números amigáveis menores que 2000. Dois números são
amigáveis quando cada um é igual à soma dos divisores do outro número
(excluindo apenas o próprio número). Exemplo: 220 e 284 são números amigáveis
pois a soma dos divisores de 220 (1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110) é
igual a 284 e a soma dos divisores de 284 (1, 2, 4, 71, 142) é igual a 220.
71. Escreva um programa em PASCAL
para determinar todos os números de 3 algarismos, cujas somas dos cubos dos
algarismos sejam iguais ao próprio número. Exemplo: 153 = 1 + 5 + 3 .
72. Escreva um programa em PASCAL
para determinar todos os números de 4 algarismos que possam ser separados em
dois números de dois algarismos que somados e elevando-se a soma ao quadrado
obtenha-se o próprio número. Exemplo: 3025 = (30 + 25) = 55 .
73. Escreva um programa em PASCAL
para ler os coeficientes de várias equações do segundo grau e determinar, para
cada uma das equações, suas raízes reais, caso existam. Quando a equação não
possuir raízes reais, o programa deve informar esta ocorrência. O processamento
deve ser encerrado quando o primeiro valor lido for nulo, sem considerar este
grupo de valores nos cálculos.
74. Um método para verificar se uma
multiplicação está correta é a soma dos nove fora dos multiplicadores e
produto. Elabore um programa em PASCAL para determinar a soma dos nove fora de
um número decimal inteiro positivo com no máximo 8 algarismos.
75. Escreva um programa em PASCAL
para ler e imprimir 3 valores reais. O programa deve verificar se esses valores
formam um triângulo e o tipo de triângulo. O triângulo poderá ser:
-
equilátero - quando os três lados forem iguais;
-
isósceles - quando dois dos lados forem iguais e
-
escaleno - quando os três lados forem distintos.
76. Escreva um programa em PASCAL
que leia as coordenadas (X1, Y1), (X2, Y2), e (X3, Y3) representando os
vértices de um triângulo em um sistema de coordenadas cartesianas, leia as
coordenadas (X4, Y4) de um ponto qualquer e determine se o ponto localiza-se
dentro do triângulo. O programa deve escrever todas as coordenadas.
77. Escreva um programa em PASCAL
para ler um número inteiro qualquer e determinar sua raiz quadrada pelo método
de Newton com aproximação de 0.0001. A aproximação deve ser obtida de:
X
= a/2
X
= 1/2 (X + a/X) para i = 1, 2, 3, ...
78. Modifique o programa de
cálculo da raiz quadrada pelo método de Newton, de modo a informar quantas
iterações foram necessárias para atingir uma aproximação desejada (lida da
unidade padrão de entrada).
79. Escreva um programa em PASCAL
para ler um número inteiro qualquer e determinar sua raiz cúbica por
aproximações sucessivas pelo método de Newton. A raiz com aproximação de 0.0001
deve ser obtida de:
X
= a/3
X
= 1/3 (2X + a/X ) para i = 0, 1, 2, 3, ...
80. Escreva um programa em PASCAL
para determinar o dia da semana referente a uma data qualquer do Calendário
Gregoriano. A data deve ser lida no formato dia-mês-ano. O Reverendo Zeller
desenvolveu o seguinte algoritmo com esse objetivo:
-
considerar M como sendo o mês do ano, iniciando com março com M = 1 e janeiro e fevereiro sendo os meses 11 e 12 do ano anterior;
-
considerar D como sendo o dia do mês;
-
considerar A como sendo o ano do século;
-
considerar S como sendo o século anterior. O índice do dia
(Domingo = 0, Segunda = 1, ..., Sábado = 6) é dado pelo resto da divisão de
(13M - 1)/5 + A/4 + S/4 por 7, considerando apenas a parte inteira de cada uma
das divisões.
Avançar para o Capítulo Anterior Voltar para o Índice Avançar para o
Próximo Capítulo