• Nenhum resultado encontrado

O comando while

No documento Programando com Pascal (páginas 55-58)

CAPÍTULO 4 ESTRUTURAS DE REPETIÇÃO

4.3 O comando while

Para introduzir uma nova estrutura de repetição e cotejá-la com o comando for, considere um programa para encontrar um divisor próprio de um inteiro dado (um divisor próprio de um inteiro n é um divisor de n menor que n e diferente de 1. Esta questão é importante na verificação da primalidade de um inteiro: um número que não tem divisores próprios é primo, conforme [Evaristo, J. 2002]). Com a utilização do comando for, teríamos a seguinte solução para esta questão.

{Programa que determina um divisor próprio de um inteiro}

program DivisorProprio;

var Num, i, Divisor : integer;

begin

write('Digite um numero: ');

readln(Num);

Divisor := 0;

for i := 2 to Num - 1 do if Num mod = 0

then

Divisor := i;

if Divisor <> 0 then

writeln(Divisor, ' eh divisor proprio de ', Num);

else

writeln(Num, ' eh primo');

end.

Um problema com este programa é que ele retorna sempre, se existir, o maior divisor próprio. Isto significa que, se a entrada for um número par, a estrutura de repetição não é interrompida quando o divisor 2 é encontrado, o que, evidentemente, vai prejudicar a performance do programa. Este problema pode ser resolvido em alguns compiladores Pascal que permitem que uma variável de controle de um comando for tenha o seu conteúdo alterado dentro do próprio comando. Com isto, o programa acima ficaria da seguinte forma.

{Programa que determina um divisor próprio de um inteiro}

program DivisorProprio;

var Num, i, Divisor : integer;

begin

write('Digite um numero: ');

readln(Num);

Divisor := 0;

for i := 2 to Num - 1 do if Num mod = 0

then begin

Divisor := i;

i := Num – 1;

end;

if Divisor <> 0 then

writeln(Divisor, ' eh divisor proprio de ', Num);

else

writeln(Num, ' eh primo');

end.

Nesta versão, quando o primeiro divisor próprio é encontrado, o comando i := Num – 1 e o seguinte incremento da variável i faz com que a execução do comando for seja interrompida. A prática de alterar o conteúdo da variável de controle não será aqui incentivada pelo fato de que outras linguagens não a permitem. Na verdade, a questão central é que o comando for deve ser utilizado quando o número de repetições de execução de uma seqüência de comandos é conhecido a priori. Quando isto não acontece (que é o caso do exemplo anterior: não se sabe a priori se e quando um divisor próprio vai ser encontrado), deve-se usar o comando while, que possui a seguinte sintaxe:

while Expressão lógica do seqüência de comandos

Quando da sua execução, a Expressão lógica é avaliada. Se for verdadeira, a seqüência de comandos é executada e o processamento retorna ao próprio comando while. Se for falsa, a seqüência não é executada e o processamento se transfere para o comando seguinte.

Naturalmente, pode ocorrer que a seqüência não seja executada nenhuma vez, isto acontecendo se a Expressão lógica for falsa quando da “primeira” execução do comando. Por outro lado, se a tal expressão lógica permanecer verdadeira, a seqüência de comandos terá sua execução infinitamente repetida o que implicará a não-execução da tarefa. Se isto acontece, dizemos que o programa está em looping e é necessária a digitação da combinação das teclas <Ctrl> + <Break> para interromper a sua execução.

Com o comando while as questões levantadas acima sobre o programa para determinar um divisor próprio de um inteiro dado são resolvidas e temos o seguinte programa:

{Programa que determina o menor divisor próprio de um inteiro}

program DivisorProprio;

var Num, Divisor : integer;

begin

write('Digite um numero: ');

readln(Num);

Divisor := 2;

while Num mod Divisor <> 0 do Divisor := Divisor + 1;

if Divisor < Num then

writeln(Divisor, ' eh divisor proprio de ', Num);

else

writeln(Num, ' e primo');

end.

Como todo inteiro é divisor de si mesmo, a estrutura while sempre será interrompida. Se foi interrompida com Divisor < Num, é porque um divisor próprio foi encontrado; se foi interrompida com Divisor = Num, então Num é primo.

Evidentemente esta versão é bem mais eficiente do que aquela que utilizava o comando for e o interessante é que ela ainda pode ser melhorada, pois a matemática prova que, se um inteiro não possui um divisor próprio menor do que sua raiz quadrada, então ele é primo (ver [Evaristo, J 2002]). Levando em conta este fato, teríamos o seguinte programa:

{Programa que determina o menor divisor próprio de um inteiro}

program DivisorProprio;

var Num, Divisor : integer;

begin

write('Digite um numero: ');

readln(Num);

Divisor := 2;

while (Num mod Divisor <> 0) and (Divisor <= SqrT(Num)) do Divisor := Divisor + 1;

if Divisor <= SqrT(Num) then

writeln(Divisor, ' e divisor proprio de ', Num);

else

writeln(Num, ' e primo');

end.

Na procura de se aprender a escrever programas mais eficientes, observe que a função SqrT foi executada duas vezes para o mesmo valor. Num caso como este, é mais interessante considerar uma variável para armazenar o valor da função e utilizar o conteúdo da variável nos outros comandos. Desta forma o programa anterior poderia ser assim escrito:

{Programa que determina o menor divisor próprio de um inteiro}

program DivisorProprio;

var Num, Divisor : integer;

Raiz : real;

begin

write('Digite um numero: ');

readln(Num);

Raiz := SqrT(Num);

Divisor := 2;

while (Num mod Divisor <> 0) and (Divisor <= Raiz) do Divisor := Divisor + 1;

if Divisor <= Raiz then

writeln(Divisor, ' e divisor proprio de ', Num);

else

writeln(Num, ' e primo');

end.

Aproveitando o ensejo, vale observar que o comando Divisor := 2; dos programas acima atribuiu um valor inicial à variável Divisor. Este valor era modificado quando não era um divisor de Num. Um comando de atribuição de um valor inicial a uma variável é chamado inicialização da variável.

Uma outra aplicação importante do comando while diz respeito a execuções sucessivas de um programa.

O leitor deve ter observado que os programas anteriores são executados apenas para uma entrada. Se quisermos a sua execução para outra entrada, precisamos executar o programa de novo.

Pode-se repetir a execução de um programa quantas vezes se queira, colocando-o numa estrutura definida por um comando while, controlada pelo valor de algum dado de entrada. Neste caso, o valor que encerra a execução pode ser informado dentro da mensagem que indica a necessidade da digitação da entrada. O programa anterior poderia ser então escrito da seguinte forma.

{Programa que determina o menor divisor próprio de vários inteiros}

program DivisorProprio;

var Num, Divisor : integer;

Raiz : real;

begin

Num := 1;

while Num <> 0 do begin

write('Digite um numero (0 para encerrar): ');

readln(Num);

Raiz := SqrT(Num);

Divisor := 2;

while (Num mod Divisor <> 0) and (Divisor <= Raiz) do Divisor := Divisor + 1;

if Divisor <= Raiz then

writeln(Divisor, ' eh divisor proprio de ', Num);

else

writeln(Num, ' eh primo');

end;

end.

No documento Programando com Pascal (páginas 55-58)