DENTRO DE REPETIC¸O˜ES 59 positivos, ignorando os negativos ou nulos. Se o enunciado fosse simplesmente para ler e imprimir 30 nu´meros, como far´ıamos? Provavelmente como ilustrado na figura 6.6. Observamos que este problema e´ muito similar a outros ja´ estudados no cap´ıtulo anterior. Trata-se de um lac¸o que precisa de um contador para se determinar a sa´ıda. program lereimprimir ; var i , a : integer ; (∗ i serve para contar quantos numeros foram lidos ∗) begin i := 1; while i <= 30 do begin read (a) ; writeln (a) ; i := i + 1; end; end. Figura 6.6: Lendo e imprimindo 30 nu´meros. O problema e´ que na˜o queremos imprimir todos os nu´meros lidos, mas apenas aqueles que sa˜o positivos: se o nu´mero lido for positivo, enta˜o queremos imprimir, sena˜o na˜o. Conforme ja´ visto, o comando if faz exatamente isto, testa uma expressa˜o booleana que, caso satisfeita, executa o comando subsequente, sena˜o o pula, passando diretamente para o seguinte, tal como ilustrado na figura 6.7. program lereimprimir ; var i , a : integer ; begin i := 1; while i <= 30 do begin read (a) ; i f a > 0 then writeln (a) ; (∗ so eh executado quando a eh positivo ∗) i := i + 1; end; end. Figura 6.7: Lendo e imprimindo os positivos apenas. Relembrando, o comando de desvio condicional tambe´m permite executar exclu- sivamente uma ac¸a˜o alternativa, caso o teste da expressa˜o booleana resulte em falso. Por exemplo, se o enunciado fosse “ler 30 nu´meros e imprimir os que sa˜o pares mas imprimir o quadrado dos que na˜o sa˜o, incluindo o zero”. 60 CAPI´TULO 6. TE´CNICAS ELEMENTARES Do ponto de vista lo´gico, seria o mesmo que dizer o seguinte: “se o nu´mero lido for positivo, imprimı´-lo, caso contra´rio ele e´ zero ou negativo, enta˜o imprimir o quadrado dele”. Isto pode ser visto na figura 6.8. Destacamos mais uma vez que a estrutura de controle do lac¸o na˜o mudou, apenas os comandos que sa˜o executados no lac¸o mudaram, caracterizando-se dois subproblemas: um para controlar o lac¸o, outro para se decidir se o nu´mero e´ positivo ou na˜o e o que fazer com ele. program lereimprimir ; var i , a : integer ; begin i := 1; while i <= 30 do begin read (a) ; i f a > 0 then writeln (a) (∗ so eh executado quando a for positivo ∗) else writeln (a∗a) ; (∗ so eh executado quando a <= 0 ∗) i := i + 1; end; end. Figura 6.8: Lendo e imprimindo os positivos e os quadrados dos ı´mpares. Agora, o comando que imprime a so´ e´ executado quando a > 0. Se isto na˜o for verdade, o que e´ impresso e´ o quadrado de a. Em ambos os casos o valor de i e´ incrementado. Este u´ltimo programa pode facilmente ser modificado para se resolver o problema de se contar quantos nu´meros lidos sa˜o positivos e quantos na˜o sa˜o. Basta, ao inve´s de imprimir, contar, ou em outras palavras, acumular. Para isto sa˜o necessa´rias duas varia´veis adicionais, que iniciam em zero e que sa˜o incrementadas a cada vez que um nu´mero e´ identificado como positivo ou na˜o. Esta ideia pode ser vista na figura 6.9. Importante notar a similaridade das duas soluc¸o˜es. Os problemas sa˜o ligeiramente diferentes, eles diferem em um dos subproblemas ape- nas: um deve imprimir, o outro deve acumular. Os outros problemas tais como o controle do lac¸o e a leitura dos dados sa˜o exatamente os mesmos problemas. Podemos usar o mesmo racioc´ınio para resolver toda uma classe de problemas similares, isto e´, imprimir a soma de nu´meros que satisfazem alguma propriedade. No caso do problema anterior, a propriedade era “ser negativo” ou “ser positivo”. Mas poderia ser qualquer outra coisa, como por exemplo “ser diferente de zero”, “ser primo”, “ser mu´ltiplo de 50” ou algo mais complexo como “ter saldo positivo nos u´ltimos 12 meses e na˜o estar devendo para o imposto de renda”. Vejamos um problema similar para uma propriedade simples, cuja soluc¸a˜o pode ser facilmente adaptada do algoritmo anterior. 6.3. DESVIOS CONDICIONAIS DENTRO DE REPETIC¸O˜ES 61 program contar ; var i , (∗ serve para contar ate 30 ∗) conta positivos , (∗ serve para contar os positivos ∗) conta outros , (∗ serve para contar os nao positivos ∗) a: integer ; (∗ numeros lidos na entrada ∗) begin conta positivos:= 0; (∗ eh preciso inicializar a variavel ∗) conta outros:= 0; i := 1; while i <= 30 do begin read (a) ; i f a > 0 then conta positivos:= conta positivos + 1 else conta outros:= conta outros + 1; i:= i + 1; end; writeln (’A quantidade de positivos lidos eh ’ , conta positivos) ; writeln (’A quantidade de nao positivos lidos eh ’ , conta outros) ; end. Figura 6.9: Contando os positivos e os negativos e nulos. 6.3.2 Somando pares e ı´mpares Problema: Ler uma sequeˆncia de nu´meros e imprimir separadamente a soma dos que sa˜o pares e a soma dos que sa˜o ı´mpares. O programa deve terminar quando o nu´mero lido for o zero. Este u´ltimo nu´mero tambe´m deve ser ignorado. No programa ilustrado na figura 6.10, basicamente foi colocado no lugar do if x > 0 then a traduc¸a˜o da expressa˜o if “x e´ par” then, traduc¸a˜o esta que envolve o uso da operac¸a˜o de resto de divisa˜o inteira. Todo nu´mero que, dividido por 2, resulta em resto 0 so´ pode ser par. Caso contra´rio e´ ı´mpar. Tambe´m foi feita uma mudanc¸a no nome das varia´veis para facilitar a compreensa˜o do co´digo. A propriedade pode ser ta˜o complexa quanto se queira, mas e´ importante observar que o co´digo de base na˜o muda muito. Observe que ha´ uma leitura, o teste, algum processamento e, por u´ltimo, a leitura do pro´ximo valor, repetindo-se o co´digo. Problema: Ler nu´meros do teclado, ate´ ler um zero, e imprimir apenas os que sa˜o ao mesmo tempo mu´ltiplos de 7 mas na˜o sa˜o mu´ltiplos de 2. Soluc¸a˜o similar (apresentada na figura 6.11). Um lac¸o controla o te´rmino da repetic¸a˜o, e um desvio condicional verifica a propriedade e algum co´digo e´ executado em seguida (no caso uma simples impressa˜o na tela). 62 CAPI´TULO 6. TE´CNICAS ELEMENTARES program somapareseimpares ; var x, somapares , somaimpares: integer ; begin somapares:= 0; somaimpares:= 0; read (x) ; while x <> 0 do begin if x mod 2 = 0 then (∗ verdadeiro quando x eh par ∗) somapares:= somapares + x else somaimpares:= somaimpares + x; read (x) ; end; writeln (somapares , somaimpares) ; end. Figura 6.10: Soma pares e ı´mpares. program somaquadradosperfeitos ; var a: integer ; begin read (a) ; while a <> 0 do begin if (a mod 7 = 0) AND (a mod 2 <> 0) then writeln (a) ; read (a) ; end; end. Figura 6.11: Imprime os mu´ltiplos de 7 que na˜o sa˜o mu´ltiplos de 2. Um terceiro problema similar e´ apresentado a seguir. Problema: Ler nu´meros do teclado, ate´ ler um zero, e imprimir apenas os que forem mu´ltiplos de 3 maiores do que 50 e menores ou iguais a 201. Novamente, mesmo racioc´ınio (soluc¸a˜o na figura 6.12). Apenas a propriedade a ser satisfeita e´ mais complexa, envolve uma expressa˜o booleana contendo conectivos de conjunc¸a˜o. E´ importante para o estudante comparar os treˆs u´ltimos co´digos e perceber a enorme similaridade entre eles. 6.3.3 Convertendo para bina´rio Este problema e´ um desafio que pode ser resolvido com a mesma ideia de se aninhar um desvio condicional sob o escopo de uma repetic¸a˜o, combinada com o uso dos 6.3. DESVIOS CONDICIONAIS DENTRO DE REPETIC¸O˜ES 63 program somaquadradosperfeitos ; var a: integer ; begin read (a) ; while a <> 0 do begin if (a mod 3 = 0) AND (a > 50) AND (a <= 201) then writeln (a) ; read (a) ; end; end. Figura 6.12: Imprime os mu´ltiplos de 3 lidos entre 51 e 201. acumuladores. Problema: Dado um nu´mero inteiro entre 0 e 255 imprimir este nu´mero em seu formato bina´rio. Este e´ um exemplo cla´ssico em que o estudante esquece da teoria. Tradicional- mente, o professor apresenta a definic¸a˜o de nu´meros bina´rios,