Comentários

0%

NÃO PODE FALTAR

Estruturas de repetição condicional

Marcio Aparecido Artero

Otimização das soluções de problemas

As estruturas de repetição são utilizadas para realização de tarefas repetitivas vinculadas a uma condição, envolvendo variáveis de controle, contadores e acumuladores.

Fonte: Shutterstock.

Deseja ouvir este material?

Áudio disponível no material digital.

Praticar para Aprender

Caro aluno, chegamos a mais um desafio do nosso curso, no qual você terá a oportunidade de estudar as estruturas de repetição condicionais while e do/while, seus comparativos e aplicações.

Assim como as estruturas de decisão, as estruturas de repetição têm a função de otimizar as soluções de problemas. Considere que você decidiu distribuir cinco livros de computação ao final de um evento; a estrutura de repetição, por exemplo, ficaria assim: enquanto o número de pessoas for menor que cinco, você entregará um livro; depois, a distribuição será encerrada. Veja que a expressão “enquanto” foi utilizada no início da frase.

Pois bem, para colocarmos os conhecimentos a serem aprendidos em prática, vamos analisar a seguinte situação: você deverá criar um programa em linguagem C para ajudar a instituição de ensino na qual você se graduou. Foi solicitada a elaboração de um programa que receberá as notas finais dos alunos de determinada disciplina. O professor poderá entrar com quantas notas ele desejar e, por fim, o programa deverá apresentar a média final dessa disciplina.

Pense nas soluções e execute o código em um compilador de linguagem C. Apresente o código livre de erros em um documento de texto. Boa aula!

Roteiro para o professor

Para auxiliar no desenvolvimento da competência e no entendimento do problema abordado na situação-problema, é possível apresentar um exemplo que envolve as variáveis contadores e acumuladores. O exemplo pode evitar um erro muito comum dos alunos, que é o esquecimento de inicializar variáveis contadores e acumuladores. Isso pode gerar erros de execução que são difíceis de identificar e corrigir. Portanto, chame a atenção dos alunos para esse fato. Antes de implementar a solução da situação-problema, peça aos alunos que implementem e executem o código a seguir no software Paiza.io (PAIZA.IO, 2020).

#include 
int main(void){
  int soma;
  int i = 0; 
  while(i < 5) {
    soma += i;
    i++;
  }  
  printf("%d", soma);  
}

Por fim, peça que eles registrem qual foi a saída do programa, isto é, qual foi o valor impresso na tela. Faça um debate com os alunos a respeito da saída apresentada pelo programa, levando em consideração as seguintes questões:

  • Qual era o resultado esperado e qual foi a saída do programa? Eles são compatíveis?
  • Qual problema do código apresentado que levou ao resultado inesperado?
  • O que acontece com a saída do programa se ele for executado mais de uma vez? Por que isso aconteceu?

conceito-chave

Você já observou a quantidade de tarefas repetitivas que realizamos no dia a dia? Indo ao trabalho todos os dias, por exemplo, podemos nos deparar com situações rotineiras no caminho: paramos em semáforos, viramos à esquerda, à direita e seguimos em frente algumas vezes para chegar ao nosso destino. Nesse caso, vivemos circunstâncias que se repetem um determinado número de vezes. Podemos associar esse tipo de ação também ao contexto computacional, por exemplo, ao desenvolver um programa para contar o número de caixas de produtos em uma esteira de produção ou o número de clientes que realizou a compra de um produto específico, também para contar quantos produtos ainda há no estoque de uma loja. Essas situações correspondem à ideia de contagem, repetindo até que o último produto seja vendido e até que o último cliente realize a compra do último produto – são tarefas repetitivas. A Figura 2.8 ilustra um exemplo de aplicação de repetição: a simples contagem de caixas em uma esteira. Nessa situação, seriam necessários outros aparatos, como sensores, mas é possível realizar a contagem a partir de uma estrutura de repetição.

Figura 2.8 | Caixas em uma esteira de produção
Fonte: Shutterstock.

ESTRUTURA DE REPETIÇÃO COM TESTE NO INÍCIO - WHILE

Assim, chegou o momento de encarar o desafio de estudar as estruturas de repetição. Segundo Manzano (2013), para a solução de um problema, é possível utilizar a instrução if para tomada de decisão e para criar desvios dentro de um programa para uma condição verdadeira ou falsa. Seguindo essa premissa, vamos iniciar nossos estudos com as repetições com teste no início – while. É preciso estar ciente de que algo será repetidamente executado enquanto uma condição verdadeira for verificada e de que somente após a sua negativa essa condição será interrompida.

Segundo Soffner (2013, p. 64), o programa “não executará qualquer repetição (e as ações que ali dentro estiverem programadas) sem antes testar uma condição”. Na realização dessa condição, vamos fazer uso do comando iterativo while, que significa “enquanto” em português. Veja na Figura 2.9 a forma simplificada do fluxograma do comando while direcionado para o teste no início.

Figura 2.9 | Fluxograma do comando while
A imagem mostra o símbolo condicional, dele saem dois fluxos, o que segue o fluxo normal com a letra F e o outro à direito com a letra V que segue para o símbolo de processo com o texto: comandos a serem repetidos, seu fluxo volta para o símbolo condicional.
Fonte: elaborada pelo autor.

Como o programa será elaborado em linguagem C, veja a sintaxe com a repetição com teste no início:

while (<condição>) {
  Comando 1;
  Comando 2;
  Comando n;
}

Em alguns casos, quando utilizamos um teste no início, pode ocorrer o famoso loop (laço) infinito (quando um processo é executado repetidamente). Para que isso não aconteça, você poderá utilizar os seguintes recursos:

Reflita

Perceba que quando aplicamos um laço várias instruções podem ser aplicadas, até mesmo a existência de um laço dentro de outro laço. Que nome damos a esse laço?

Observe o exemplo a seguir, uma aplicação do comando while em um teste no início, que deverá mostrar a palavra “PROGRAMA” dez vezes:

Código 2.11 | Comando while – teste no início
#include <stdio.h>
 int main() {
     int cont = 0; 
     
     // Será executado enquanto cont for menor que 10
     while (cont < 10) {
           printf("\n PROGRAMA");
           
           // incrementa cont, para que não entre em loop infinito
           cont++; 
      } 
      return 0;
 }
Fonte: elaborado pelo autor.

Teste o Código 2.11 utilizando a ferramenta Paiza.io.

No exemplo do código, podemos observar alguns dos recursos comentados, tais como contador, incremento e condição de parada. Na linha 3, uma variável denominada cont é inicializada com o valor 0. Essa variável servirá como contador do programa, isto é, ela vai indicar quantas repetições do laço já foram executadas. Na linha 6 nós temos o que chamamos de condição de parada, ou seja, uma condição lógica que, ao se tornar falsa, determinará a parada do laço de repetição. Nesse caso, estamos utilizando o contador que foi criado na condição de parada. Quando ele chegar ao valor 10 (ou maior), a condição de parada se tornará falsa e o laço será encerrado. Por fim, na linha 10 nós temos o incremento do contador. Sem isso, o programa entraria em loop infinito, uma vez que o valor da variável cont não seria atualizado, portanto, a condição de parada nunca se tornaria falsa. Duas outras formas de se representar o incremento do contador são: cont = cont + 1 ou cont += 1. Esse tipo de instrução é conhecido como atribuição composta.

Roteiro para o professor

Uma das principais dificuldades dos alunos durante o aprendizado das estruturas de repetição consiste em acompanhar o fluxo de execução do programa. Uma ferramenta útil, nesse sentido, é a C tutor.

O código foi criado com a intenção de somar todos os números pares de 0 a N. Contudo, ele está apresentando resultados incorretos.

Peça aos alunos que utilizem a ferramenta C Tutor disponível em: http://pythontutor.com/c.html para executarem o programa e então descobrirem e apontarem os erros contidos nele.

int main() {
 int n = 6, i = 1, soma = 0;
 while(i <= n) {
  soma += soma + i;
  i = i + 2;
 }
 printf("Soma = %d", soma);

 return 0;
}

Após os alunos terem identificado os erros, algumas questões podem ser feitas para fixar o conteúdo aprendido até o momento, tais como:

  • Os erros estavam em quais recursos do laço (contador, incremento, acumulador ou condição de parada)?
  • Qual o erro contido no contador?
  • Qual o erro contido no acumulador?

O próximo exemplo é para checar se a nota final de um aluno está entre 0 e 10.

Código 2.12 | Comando while – validação de entrada de dados
 #include <stdio.h>
 int main(void) {
     char parar;
     float nota; 
     printf("\nDigite a nota final do aluno: "); 
     scanf("%f", ¬a); 
     while (nota < 0 || nota > 10) {
         printf("\nNota inválida! Digite a nota final do aluno: "); 
         scanf("%f", ¬a); 
     }
	return 0;
 }
Fonte: elaborado pelo autor.

Teste o Código 2.12 utilizando a ferramenta Paiza.io.

Lembre-se de que você deve inserir a nota na aba input na ferramenta; após executar, vá até a aba input, entre com os dados, execute novamente e observe a saída.

Esse é um bom exemplo de validação de entrada de dados, um recurso muito utilizado em diversos softwares atuais. A validação consiste em garantir que os dados de entrada informados pelo usuário do sistema estejam dentro do esperado para o bom funcionamento do software. No caso do código apresentado, é um software educacional, e não queremos que uma nota negativa ou maior do que o limite máximo (10) seja inserida no software. Por isso, na linha 6, a nota do aluno é lida uma primeira vez. Logo após (linha 7), temos um laço while, cuja condição de parada é quando a nota do aluno estiver entre 0 e 10. Isto é, o laço só será encerrado quando a nota do aluno for válida. Lendo de outra forma, enquanto a nota do aluno for menor do que 0 ou maior do que 10, o programa exibirá uma mensagem informando ao usuário que a nota é inválida e solicitando a entrada de uma nova nota (linha 8). Após a mensagem, a nova nota é lida na linha 9.

Estrutura de repetição com teste no fim – do-while

Agora, vamos aplicar as repetições com testes no final (do-while). Segundo Schildt (1997), o laço do-while analisa a condição ao final do laço, ou seja, os comandos são executados antes do teste de condição. Nesse caso específico, ao contrário do while, os comandos são executados pelos menos uma vez.

A Figura 2.10 ilustra o fluxograma utilizando o teste de repetição no final:

Figura 2.10 | Fluxograma com teste de repetição no final
A imagem inicia com o símbolo de terminal com o texto: início da repetição, que segue o fluxo para o símbolo conector, que segue o fluxo para o símbolo de processo com o texto: comandos a serem repetidos, que segue o fluxo para o símbolo condicional com o texto: condição, na saída para direita com a letra F, segue o fluxo para o símbolo de terminal com o texto fim da repetição, e na saída para esquerda com a letra V, o fluxo volta para o símbolo conector.
Fonte: elaborada pelo autor.

Observe a sintaxe para realização da repetição com teste no final:

do {
  comandos; 
} while (condição);

Observe como ficaria o exemplo anterior, com a utilização do comando do-while:

Código 2.13 | Comando do-while – teste no final
#include <stdio.h>
 int main(void) {
     char parar;
     float nota; 
     do {
         printf("\nDigite a nota final do aluno (min: 0, max: 10): "); 
         scanf("%f", ¬a); 
     } while (nota < 0 || nota > 10);
	return 0;
 }
Fonte: elaborado pelo autor.

Agora é a sua vez de testar o código utilizando a ferramenta Paiza.io.

A validação de dados de entrada do usuário, como explicamos anteriormente, é um ótimo exemplo para utilização do laço do-while. Isso porque a entrada precisa ser lida pelo menos uma vez para (linha 7), para então decidirmos se podemos encerrar o laço ou se devemos solicitar a entrada novamente (condição de parada – linha 8). Uma diferença do exemplo apresentado para o anterior, que usava o laço while, é que nesse caso não é exibida uma mensagem ao usuário informando-o que a nota é inválida. Isso poderia ser facilmente resolvido, incluindo uma estrutura condicional if após a leitura da nota do aluno (linha 7), como:

if (nota < 0 || nota > 10) {
  printf(“\nNota inválida! ”);
}

Outro potencial uso do laço do-while é na implementação de menus de opções, conforme apresentado no exemplo a seguir. Você verá um programa que calcula a metragem quadrada de um terreno, usando o teste no final para criar a opção de digitar novos valores sem sair do programa:

Código 2.14 | Laço do-while – metragem terreno
#include <stdio.h>
int main() {
    float metragem1, metragem2, resultado;
    int resp;
    metragem1 = 0;
    metragem2 = 0;
    resultado = 0;
    printf("\nC Á L C U L O    D E   M E T R O S    Q U A D R A D O S");
    do {
        printf("\n\nDigite a primeira metragem do terreno: ");
        scanf("%f", &metragem1);
        printf("\nDigite a segunda metragem do terreno: ");
        scanf("%f", &metragem2);
        resultado = metragem1 * metragem2;
        printf("\n\nO Terreno tem = %.2f m2", resultado);
        printf("\n\nDigite 1 para continuar ou 2 para sair: ");
        scanf("%d", &resp);
    } while (resp == 1);
    return 0;
}
Fonte: elaborado pelo autor.

Teste o Código 2.14 utilizando a ferramenta Paiza.io.

Na sequência dos nossos estudos, vamos trabalhar com outra aplicação das estruturas de repetição condicionais. Nesse caso, realizando um programa que simula uma conta bancária (tela de opções das transações), adaptado do livro do Soffner (2013).

Código 2.15 | Comando do-while – conta bancária
#include <stdio.h>
 int main() {
     float soma=0; 
     float valor; 
     int opcao; 
     do {
         printf("\n M E N U   D E  O P Ç Õ E S");
         printf("\n 1. Depósito"); 
         printf("\n 2. Saque"); 
         printf("\n 3. Saldo"); 
         printf("\n 4. Sair"); 
         printf("\n Informe uma opção: "); 
         scanf("%d", &opcao);
         switch(opcao) {
             case 1: 
                 printf("\n Informe o valor: "); 
                 scanf("%f", &valor); 
                 soma += valor; 
                 break;
             case 2: 
                 printf("\n Informe o valor: "); 
                 scanf("%f", &valor); 
                 soma -= valor; 
                 break;
             case 3: 
                 printf("\n Saldo atual = R$ %.2f", soma); 
                 break; 
             case 4: 
                 printf("\n Saindo..."); 
                 break; 
             default: 
                 printf("\n Opção inválida!"); 
         }   
     } while (opcao != 4); 
     printf("\n\n Fim das operações!");
	  return 0;
 }
Fonte: elaborado pelo autor.

Teste o Código 2.15 utilizando a ferramenta Paiza.io.

Nas linhas 3 a 5, temos a declaração das variáveis iniciais do programa. Na linha 6, temos o início do bloco do comando do-while. Isso significa que tudo o que está inserido entre as linhas 6 e 34 pode executar uma ou mais vezes. Nas linhas 7 a 12 temos a impressão do menu de opções do programa na tela do usuário. Já na linha 13, há a leitura da opção desejada do usuário. Com base nessa opção, o comando switch-case (linha 14) redirecionará o fluxo de execução do programa para o bloco mais adequado. Caso nenhum caso (case) seja encontrado, então o bloco de instruções do caso padrão (default), que está linha 32 será executado. Ao final do comando switch-case, temos a condição de parada do bloco do-while (linha 34). Nessa condição, é verificado se a opção selecionada pelo usuário é diferente de 4, que corresponde à opção “Sair”. Caso isso seja verdadeiro, o fluxo do programa volta para o início do bloco do-while, e todo processo comentado anteriormente se repete. Caso contrário, o programa é encerrado. Quanto às operações de saque e depósito, trata-se de instruções simples, já estudadas neste livro. A única diferença está na utilização do comando de atribuição composta duas vezes, uma para a operação de depósito e outra para a de saque.

Assimile

Algumas variáveis podem sofrer alterações baseadas nos seus valores anteriores. Para facilitar, você pode utilizar o que chamamos de atribuição composta, que indica qual operação será realizada. Nesse caso, coloca-se o operador à esquerda do sinal de atribuição. Por exemplo: y += 1, que tem o mesmo efeito que y = y + 1, nesse caso, evitando colocar a variável à direita da atribuição. O mesmo pode ser feito com as operações de subtração, multiplicação e de divisão.

Roteiro para o professor 

Caro professor, é possível apresentar uma brincadeira clássica da adivinhação de números, implementada em C, com auxílio das estruturas de repetição. Peça aos alunos que acessem o website http://guida.querido.net/jogos/portug/adivinum.htm, o qual apresenta uma versão web do jogo “Advinha o número”.

Após isso, discuta uma possível solução de implementação para esse jogo, na linguagem C. Eis algumas perguntas para direcionar a discussão:

  • Como selecionar um número aleatoriamente? Para gerar números aleatórios, podemos utilizar as biblioteca time.h e stdlib.h, com suas funções srand , rand e time.
  • Temos que estabelecer um limite máximo para que o jogo não se torne muito difícil. Esse limite será fixo ou deixaremos que o usuário escolha?
  • Temos, também, que estabelecer um limite máximo de tentativas, para que o jogo não se torne muito fácil. É melhor que esse número seja fixado no código do programa, certo?
  • Qual estrutura de repetição seria mais adequada: while ou do-while, for? Por quê?

Por fim, peça aos alunos que se reúnam em grupos e implementem o jogo “Advinha o número” na linguagem C. Logo após, peça que troquem os programas dos grupos entre si para que eles se divirtam com os programas feitos pelos colegas.

Chegamos ao final de mais uma seção e agora é o momento de aplicar o conhecimento adquirido. Bons estudos!

Faça valer a pena

Questão 1

Sobre o comando while, podemos afirmar que:

  1. O programa não executará nenhuma repetição (as ações que ali dentro estiverem programadas) sem antes testar uma condição.
  2. Pode ocorrer o famoso loop infinito.
  3. Geralmente usamos o comando while quando não sabemos quantas vezes o laço da condição deve ser repetido.

É correto o que se afirma em:

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Correto!

Podemos afirmar que I, II e III estão corretas.

  1. O programa não executará nenhuma repetição (as ações que ali dentro estiverem programadas) sem antes testar uma condição.
  2. Pode ocorrer o famoso loop infinito.
  3. Geralmente usamos o comando while quando não sabemos quantas vezes o laço da condição deve ser repetido.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Questão 2

Levando em consideração que precisamos estar atentos para que não ocorra um loop infinito, analise as afirmações a seguir:

  1. Contador – é utilizado para controlar as repetições, quando são determinadas.
  2. Incremento e decremento – trabalham o número do contador, seja aumentando, seja diminuindo.
  3. Acumulador – segundo Soffner (2013), somará as entradas de dados de cada iteração da repetição, gerando um somatório a ser utilizado quando da saída da repetição.
  4. Condição de parada – utilizada para determinar o momento de parar quando não se tem um valor exato dessa repetição.

É correto o que se afirma em:

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Correto!

Quando trabalhamos com teste no início, precisamos estar atentos para que não ocorra um loop infinito. Por esse motivo, você poderá fazer uso de alguns casos específicos, como:

  1. Contador – é utilizado para controlar as repetições, quando são determinadas.
  2. Incremento e decremento – trabalham o número do contador, seja aumentando, seja diminuindo.
  3. Acumulador – segundo Soffner (2013), somará as entradas de dados de cada iteração da repetição, gerando um somatório a ser utilizado quando da saída da repetição.
  4. Condição de parada – utilizada para determinar o momento de parar quando não se tem um valor exato dessa repetição.
Questão 3

Segundo Soffner (2013), quando aplicado o comando do/while, as ações são executadas pelo menos uma vez antes do teste condicional. Analise o programa a seguir, que realiza a soma dos números positivos usando repetição com teste no final, e complete as partes que estão faltando.

#include<stdio.h>
int main() {
  int n;
  int soma = 0;
  _____ {
    printf("Digite um número positivo para ser somado ou negativo 
        para sair: ");
    scanf("%d", &n);
    ___ (n >= 0) {
      soma = soma + n;
    }
  } while( _____ );
  printf("A soma é %d\n", soma);
  return 0;
}

Assinale a alternativa que completa as lacunas no programa.

Correto!

#include<stdio.h>
int main() {
  int n;
  int soma = 0;
  do {
    printf("Digite um número positivo para ser somado ou negativo 
        para sair: ");
    scanf("%d", &n);
    if ( n >= 0 ) {
      soma = soma + n;
    }
  } while( n >= 0 );
  printf("A soma é %d\n", soma);
  return 0;
}

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Tente novamente...

Esta alternativa está incorreta, leia novamente a questão e reflita sobre o conteúdo para tentar novamente.

Referências

02 - EXERCÍCIO - Estruturas de repetição em C. 10 mar. 2017. 1 vídeo (10 min 38s). Publicado pelo canal Hélio Esperidião. Disponível em: https://cutt.ly/rjW4fQp. Acesso em: 20 nov. 2020.

13 - PROGRAMAÇÃO em Linguagem C - Desvio Condicional Aninhado - if / else if. 27 fev. 2015. 1 vídeo (11 min 12s). Publicado pelo canal Bóson Treinamentos. Disponível em: https://cutt.ly/bjW4g9G. Acesso em: 20 nov. 2020.

DAMAS, L. Linguagem C. 10. ed. Rio de Janeiro: LTC, 2016.

EDELWEISS, N. Algoritmos e programação com exemplos em Pascal e C. Porto Alegre: Bookman, 2014.

MANZANO, J. A. N. G. Estudo Dirigido de Linguagem C. 17. ed. rev. São Paulo: Érica, 2013.

MANZANO, J. A. N. G. Linguagem C: acompanhada de uma xícara de café. São Paulo: Érica, 2015.

MIZRAHI, V. V. Treinamento em linguagem C. 2. ed. São Paulo: Pearson Prentice Hall, 2008.

PAIZA.IO. Página inicial. Paiza Inc., Tóquio, 2020. Disponível em: https://paiza.io/en. Acesso em: 29 out. 2020.

PROGRAMAÇÃO C - Aula 07 - while, do-while, for – Estruturas de repetição. 10 abr. 2012. 1 vídeo (15 min 56s). Publicado pelo canal Peterson Lobato. Disponível em: https://cutt.ly/jjW4kik. Acesso em: 20 nov. 2020.

PROGRAMAR EM C - Como Utilizar "do while" - Aula 13. 24 out. 2012. 1 vídeo (7 min 3s). Publicado no canal De aluno para aluno. Disponível em: https://cutt.ly/9jW4lDN. Acesso em: 20 nov. 2020.

SCHILDT, H. C Completo e total. 3. ed. São Paulo: Pearson Prentice Hall, 2005.

SOFFNER, R. Algoritmos e Programação em Linguagem C. São Paulo: Saraiva, 2013.

Bons estudos!

AVALIE ESTE MATERIAL

OBRIGADO PELO SEU FEEDBACK!