Um algoritmo pode ser definido como uma sequência lógica de operações que levam a um determinado resultado. Portanto em teoria podemos escrever uma quantidade absurdamente grande de instruções desde que ao final nosso problema chegue em uma solução.

O problema deste pensamento está no fato de que tanto o nosso tempo quanto as capacidades computacionais são grandezas finitas e portanto precisamos pensar em formas de reduzir o nosso algoritmo.

Intuitivamente a primeira estrategia que pode ser adotada é eliminar todo código que de alguma forma tenha que ser executado repetidamente. Dessa forma com o passar do tempo foram surgindo soluções capazes de lidar com esse tipo de problema as quais são chamadas de estruturas de repetição.

1. Repetindo Execuções

Suponha que precisamos criar um programa que deva imprimir uma sequencia de números inteiros consecutivos de 0 até 4. Em pseudo-linguagem uma possível solução para o problema seria:

programa 
{ 
	funcao inicio () 
	{
	    escreva(0);
		escreva(1);
		escreva(2);
		escreva(3);
		escreva(4);
	} 
}

Agora suponha que desejamos resolver o mesmo problema mas ao invés de imprimir 5 inteiros precisamos imprimir um total de 1000 valores, ou pior, simplesmente não sabemos o total de valores que devem ser impressos pois será definido pelo usuário em tempo de execução.

Escrever todas as instruções necessárias para esse problema seria uma tarefa inviável, entretanto perceba como o que realmente estamos fazendo é repetir consecutivamente a instrução “escreva()” por N vezes.

Para resolver esse problema fazemos uso das estruturas de repetição na qual podemos dizer quantas vezes queremos que uma determinada instrução seja repetida. Logo para resolvermos o problema anterior, ao invés de escrevermos 1000 linhas de código podemos simplesmente fazer uso das estruturas de repetição e escrever o seguinte algoritmo:

programa 
{
	funcao inicio() 
	{
		inteiro N = 0;
		
		enquanto (N < 1000)
		{
			escreva (N);
		  	
		  	N = N+1;
		}
	}
}

Perceba como foi possível reduzir consideravelmente o código. Agora lembre-se que isso foi apenas um exemplo, esteja ciente de que em algoritmos com propósitos reais é muito comum existirem diversas instruções que devem ser executadas repetidamente e dessa forma as estruturas de repetição são consideradas de uso obrigatório.

2. Variáveis de Controle e Condições de Parada

Antes de começarmos a codar, precisamos entender o que são variáveis de controle e condições de parada, pois essas são as responsáveis por determinar o número de repetições de um determinado bloco de código.

Imagine que queremos repetir uma determinada instrução por 10 vezes seguidas. Para isso podemos usar uma variável de controle N de tal forma a controlar o estado do processo.

Inciaremos então a variável de controle N com o valor 0 e para cara repetição somaremos 1 a este valor. Portanto para cada iteração o valor da variável será igual à 0,1,2,3,…,N.

Precisamos também de uma condição de parada a qual é definida através de uma expressão lógica. Enquanto esta expressão lógica for satisfeita a execução do bloco de instruções irá se repetir, entretanto no momento em que está expressão não for mais valida a repetição será imediatamente parada.

Vamos definir então a seguinte condição a ser satisfeita:

Enquanto N for menor que 10 some 1 ao conteúdo da variável N, caso contrario pare a repetição, em outras palavras, enquanto N for menor que 10 a execução do bloco de instruções deverá se repetir.

A cada iteração a variável N será incrementada em uma unidade e assim que o laço identificar que chegou ao final, as repetições irão parar de ocorrer.

Atente-se ao fato de que tanto a variável de controle N quanto as expressões lógicas podem assumir diferentes tipos de valores, por exemplo, ao invés de valores numéricos podemos utilizar caracteres, strings ou até mesmo objetos.

Nas próximas sessões esta ideia irá ficar mais clara, entretanto lembre-se do fato de que sempre teremos uma variável de controle e uma condição que deve ser satisfeita.

3. While

A estrutura de repetição mais simples é o while, onde inicialmente temos uma condição a ser satisfeita através de uma expressão lógica. Enquanto está condição for satisfeita, a execução do bloco de instruções será repetida.

Preste atenção ao fato de que antes mesmo de executar algo a condição é verificada. Isto quer dizer que se de imediato passarmos uma variável de controle que na primeira iteração não satisfaz a expressão lógica a estrutura while nunca será executada.

Por exemplo, suponha como expressão lógica que o bloco de instrução deverá ser executado enquanto a variável N for maior que 0, isto é, no momento em que for identificado um valor negativo a repetição deve parar de ocorrer. Entretanto logo de inicio atribuímos o valor -1 a variável de controle e dessa forma a instrução while irá terminar a sua execução antes mesmo de executar qualquer coisa.

int N = -1;

while(N>0){

    /*O bloco de instruções abaixo nunca
    * será executado pois N desde o inicio
    * não satisfaz a condição N>0.
    */

    "Bloco de Instruções"

}

3.1. Estrutura do While

3.2. Código Fonte

Iremos utilizar como exemplo o problema da impressão de 1000 números inteiros apresentado anteriormente.

Java

Exemplo 1

/**

  3.2
  Exemplo 1 - Imprindo os númerais de 0 à 1000
  com while.

**/
/***************************************************/

class Main {
  public static void main(String[] args) {

    int N = 0;

    while(N<1000){
    
      System.out.printf("%d\n", N);
    
      N++;
    }
    
  }
}

C

Exemplo 1

/**

  3.2
  Exemplo 1 - Imprindo os númerais de 0 à 1000
  com while.

**/
/***************************************************/

#include <stdio.h>

int main(void) {

  int N = 0;

  while(N<1000){
    
    printf("%d\n",N);
    
    N++;
  }

  return 0;
}

C++

Exemplo 1

/**

  3.2
  Exemplo 1 - Imprindo os númerais de 0 à 1000
  com while.

**/
/***************************************************/

#include <iostream>

using namespace std;

int main() {
  
  int N = 0;

  while(N<1000){
    
    cout << N << "\n";
    
    N++;
  }

}

Python

Exemplo 1

'''

  3.2
  Exemplo 1 - Imprindo os númerais de 0 à 1000
  com while.

'''
'''*******************************************'''

N = 0

while N<1000:
    
    print("%d" % (N))
    
    N = N+1

Arduino

Exemplo 1

/**

  3.2
  Exemplo 1 - Imprindo os númerais de 0 à 1000
  com while.

**/
/***************************************************/

void setup() {

  Serial.begin(9600);
  
  int N = 0;

  while(N<1000){

    Serial.print(N+"\n");

    N++;

  }

}

void loop() {

}

4. Do While

O do while difere da estrutura de repetição while pelo simples fato de que executa ao menos uma única vez o bloco de instruções antes de verificar a expressão lógica.

Como exemplo vamos novamente utilizar como condição que o bloco de instruções deverá permanecer sendo executado enquanto o valor da variável N for maior que 0, entretanto como valor inicial atribuídos -1 a mesma.

Dessa vez como estamos utilizando a instrução do while o bloco de instruções será de imediato executado, logo em seguida quando a variável for comparada será identificado que atribuímos um valor negativo e a repetição será interrompida.

Está é a única diferença em relação a instrução while e por esta razão costuma gerar uma certa confusão quanto a sua utilização.

4.1. Estrutura do Do While

4.2. Código Fonte

Como exemplo vamos imprimir a mensagem “Hello World” a qual deveria se repetir enquanto N fosse um valor entre 0 e 9 (N >= 0 && N < 10), mas como logo de inicio estamos passando um valor de variável de controle que não satisfaz a expressão (N = -1) o texto será impresso apenas uma única vez.

Java

Exemplo 1

/**

  4.2
  Exemplo 1 - Imprimindo a mensagem "Hello World" 
  uma única vez ao passar uma condição falsa
  propositalmente para a estrutura Do While.

**/
/***********************************************/

class Main {
  public static void main(String[] args) {

    int N = -1;

    do{

      System.out.printf("Hello World\n");

    }while(N >= 0 && N < 10);

  }
}

C

Exemplo 1

/**

  4.2
  Exemplo 1 - Imprimindo a mensagem "Hello World" 
  uma única vez ao passar uma condição falsa
  propositalmente para a estrutura Do While.

**/
/***********************************************/

#include <stdio.h>

int main(void) {

    int N = -1;

    do{

      printf("Hello World\n");

    }while(N >= 0 && N < 10);

  return 0;
}

C++

Exemplo 1

/**

  4.2
  Exemplo 1 - Imprimindo a mensagem "Hello World" 
  uma única vez ao passar uma condição falsa
  propositalmente para a estrutura Do While.

**/
/***********************************************/

#include <iostream>

using namespace std;

int main() {

  int N = -1;

  do{

    cout << "Hello World \n";
    
  }while(N >= 0 && N <10);

}

Python

Exemplo 1

'''

  4.2
  Exemplo 1 - Imprimindo a mensagem "Hello World" 
  uma única vez ao passar uma condição falsa
  propositalmente para a estrutura Do While.

'''
'''********************************************'''

N = -1

while True:

  print("Hello World")

  if not (N >=0 and N < 10):
    break

Arduino

Exemplo 1

/**

  4.2
  Exemplo 1 - Imprimindo a mensagem "Hello World" 
  uma única vez ao passar uma condição falsa
  propositalmente para a estrutura Do While.

**/
/***********************************************/

void setup() {
  
  Serial.begin(9600);
  
  int N = -1;
  
  do{

    Serial.print("Hello World");
    
  }while(N>=0 && N<10);

}

void loop() {

}

5. For

Nas sessões anteriores você deve ter percebido que ao utilizar o while é muito comum criarmos uma variável de controle a fim de guardar o número de repetições.

A instrução for faz uso desse princípio e implementa esta variável em sua própria estrutura a qual irá funcionar como um contador. Dessa forma, a atualização deste contador ficará a cargo da própria estrutura de repetição for.

Inicialmente, atribuímos um valor ao contador que será de imediato comparado pela expressão lógica. Se o valor satisfazer a expressão, o bloco de instruções será executado e logo em seguida o contador terá seu valor incrementado ou decrementado passando novamente por uma comparação. No momento em que o contador não satisfazer mais a expressão lógica, a repetição será parada.

5.1. Estrutura do For

5.2. Código Fonte

Os códigos fontes abaixo realizam a impressão de 1000 números inteiros mas agora utilizando a estrutura de repetição for.

Java

Exemplo 1

/**

  5.2
  Exemplo 1 - Imprimindo os númerais de 0 à 1000
  com a estrutura de repetição FOR.

**/
/*************************************************/

class Main {
  public static void main(String[] args) {

    for(int N=0; N<1000; N++){
      System.out.println(N);
    }

  }
}

C

Exemplo 1

/**

  5.2
  Exemplo 1 - Imprimindo os númerais de 0 à 1000
  com a estrutura de repetição FOR.

**/
/*************************************************/

#include <stdio.h>

int main(void) {

  for(int N = 0; N < 1000; N++){
    printf("%d\n", N);
  }

  return 0;
}

C++

Exemplo 1

/**

  5.2
  Exemplo 1 - Imprimindo os númerais de 0 à 1000
  com a estrutura de repetição FOR.

**/
/*************************************************/

#include <iostream>

using namespace std;

int main() {

  for(int N=0; N<1000; N++){
    cout << N << "\n";
  }

}

Python

Exemplo 1

'''

  5.2
  Exemplo 1 - Imprimindo os númerais de 0 à 1000
  com a estrutura de repetição FOR.

'''
'''**********************************************'''

for N in range(0, 1000):
    print(N)

Arduino

Exemplo 1

/**

  5.2
  Exemplo 1 - Imprimindo os númerais de 0 à 1000
  com a estrutura de repetição FOR.

**/
/*************************************************/

void setup() {
  
  Serial.begin(9600);
  
  for(int N=0; N<1000; N++){
      Serial.print(N+"\n");
  }

}

void loop() {

}

6. Equivalência entre While, Do While e For

Você deve ter notado que até agora todas as estruturas de repetição contém uma variável de controle e uma expressão lógica que deve ser respeitada. A explicação para isto é que todas realizam exatamente a mesma coisa, mais que isso, na prática tais instruções são exatamente iguais.

A diferença está somente nos locais onde estão declarados as variáveis e expressões, observe a imagem abaixo para entender melhor:

Portanto perceba como existe a possibilidade de converter uma instrução em outra.

Mas agora você deve estar se perguntando, se tais instruções representam a mesma coisa por que a notação é diferente?

Dependendo da situação, a utilização de uma ou de outra instrução torna o código mais simples de se entender, principalmente quando estamos trabalhando com algumas estruturas de dados. Explicarei melhor isso na última seção.

7. Criando Loops Infinitos

Se usado corretamente as estruturas de repetição podem ser utilizadas para a criação de loops infinitos. Existem aplicações praticas para isso como por exemplo gastar tempo propositalmente, travar um programa em determinado ponto, aguardar por um recurso de forma síncrona, manter ativo a execução de um microcontrolador, etc.

Para isso basta não definirmos uma expressão lógica ou criar uma situação onde a expressão sempre será valida fazendo com que o laço nunca possa chegar a um ponto de interrupção.

Veja um exemplo utilizando o while:

while (true) {

	"bloco de instruções"

}

Agora um exemplo utilizando o for:

for (;;) {

	"bloco de instruções"

}

Existe uma forma de se sair de um loop infinito através da instrução break entretanto vou dedicar um artigo apenas sobre o assunto.

8. For Each

O for each é uma estrutura de repetição que acaba surgindo quando estamos trabalhando com coleções de objetos.

Note que até o momento foi necessário definirmos explicitamente uma variável de controle e uma expressão lógica, entretanto existem problemas que são extremamente comuns em programação como por exemplo percorrer todos os elementos de um vetor ou de uma coleção de objetos.

Nesta situação temos uma enumeração na qual sempre começaremos no primeiro elemento e iremos buscando os elementos posteriores um a um até chegarmos na ultima posição.

Esse tipo de situação é tão comum que foi criado uma estrutura de repetição especifica para ela, o for each.

Por termos uma enumeração não precisamos definir a variável de controle e nem uma condição de parada, o único parâmetro necessário é o próprio vetor ou objeto com o qual estamos trabalhando. O for each entenderá que se trata de uma enumeração e o bloco de instruções irá se repetir pela quantidade de elementos que existir ou até pararmos a execução de forma explicita.

Para termos acesso aos valores de cada elemento, o for each também fornece uma variável a qual tem seu valor atualizado a cada iteração com cada valor do vetor ou objeto.

Logo supondo que temos um vetor com os respectivos valores {1 ,2, 3, 4, 5}, na primeira iteração será atribuído o valor 1 a variável, na segunda iteração o valor 2 e assim por diante até que todos os elementos tenham sido iterados.

8.1. Estrutura do For Each

8.2. Código Fonte

Por se tratar de um recurso avançado nem todas as linguagens de programação implementam em sua especificação.

Java

Exemplo 1

/**

  8.2
  Exemplo 1 - Iterando sobre uma lista usando a 
  estrutura de repetição FOR EACH.

**/
/******************************************************/

import java.util.Arrays;
import java.util.List;

public class Sample {

    public static void main(String[] args) {

        List<Integer> lista = Arrays.asList( 1, 2, 3, 4, 5 );

        for(Integer numero : lista){
            System.out.print(numero);
        }
    }
}

C++

Exemplo 1

/**

  8.2
  Exemplo 1 - Iterando sobre uma lista usando a 
  estrutura de repetição FOR EACH.

**/
/******************************************************/

#include <iostream>

using namespace std; 

int main()
{
    int lista[] = { 1, 2, 3, 4, 5 };

    for (int numero : lista) 
       cout << numero << "\n"; 
 
    return 0;
}

Python

Exemplo 1

'''

  8.2
  Exemplo 1 - Iterando sobre uma lista usando a 
  estrutura de repetição FOR EACH.

'''
'''****************************************************'''

lista = (1, 2, 3, 4, 5)

for numero in lista:
    print(numero)

9. Escolhendo entre While ou For

Agora que sabemos como utilizar cada estrutura de repetição iremos realizar uma breve discussão a respeito de como saber quando devemos utilizar uma ou outra estrutura.

A dificuldade para quem está começando a aprender surge pelo fato de que este é um tema que apenas se pode dominar tendo experiência em programação, logo para quem realmente quer seguir na carreira a melhor dica é programar o máximo possível.

Tenha em mente que existe uma infinidade de aplicações para todas essas estruturas de repetição, logo a fim de auxiliar quem está começando vou apresentar exemplos tendo como base os exercícios que geralmente são cobrados em sala de aula e que percebo que geram uma certa confusão.

9.1. Utilizando o While

O while é muito utilizado quando queremos realizar a leitura de valores (inteiros, caracteres, texto, etc) que foram passados pelos usuários.

Em muitos exercícios é comum não se determinar o número de valores que deverá ser analisado, isto é, o programa deve parar de ler os valores inseridos no momento em que o usuário deixar de digitar algo.

Como exemplo, abaixo temos um trecho de código no qual irá imprimir uma mensagem até que o usuário deixe de enviar qualquer carácter.

Java

Exemplo 1

/**

  9.1
  Exemplo 1 - Lendo valores indefinidamente com o auxilio
  da estrutura de repetição WHILE.

**/
/********************************************************/

import java.util.Scanner;

class Main {
  public static void main(String[] args) {

    int numero;

    Scanner input = new Scanner(System.in);

    while (input.hasNextInt()) {
        numero = input.nextInt();
        System.out.println(numero);
    }

  }
}

C

Exemplo 1

/**

  9.1
  Exemplo 1 - Lendo valores indefinidamente com o auxilio
  da estrutura de repetição WHILE.

**/
/********************************************************/

#include <stdio.h>

int main(void) {
  
  int N;

  while(scanf("%d", &N) != EOF){

    printf("%d\n", N);

  }
  
  return 0;
}

C++

Exemplo 1

/**

  9.1
  Exemplo 1 - Lendo valores indefinidamente com o auxilio
  da estrutura de repetição WHILE.

**/
/********************************************************/

#include <iostream>

using namespace std;

int main(){

    int N;

    while (cin >> N) {
      cout << N << "\n";
    }

  return 0;
}

Python

Exemplo 1

'''

  9.1
  Exemplo 1 - Lendo valores indefinidamente com o auxilio
  da estrutura de repetição WHILE.

'''
'''*****************************************************'''

import sys

while True:
   line = sys.stdin.readline()
   if line == '': 
     break
   print (line)

Arduino

Exemplo 1

/**

  9.1
  Exemplo 1 - Lendo valores indefinidamente com o auxilio
  da estrutura de repetição WHILE.

**/
/********************************************************/

int input = 0;

void setup() {
  Serial.begin(9600);

  while(true){
    
    input = Serial.read();
    if(input == EOF) break;
    Serial.println(input);
    
  }
  
}

void loop() {
                   
}

Quando for executar esse algoritmo, não basta apenas pressionar a tecla “enter” sem inserir nenhum caractere esperando que nada será lido pois em si o próprio “enter” é um caractere. Ao invés disso pressione a combinação de teclas Ctrl+D.

Existe outra situação que é muto comum, onde se pede que os dados de entrada devem ser lidos até que o usuário insira um caractere específico, como por exemplo o “-1”. Este tipo de situação é mais comum e pode ser facilmente resolvida da seguinte forma:

Java

Exemplo 2

/**

  9.1
  Exemplo 2 - Usando a instrução BREAK para sair
  de um laço infinito.

**/
/**********************************************/

import java.util.Scanner;

class Main {
  public static void main(String[] args) {

    int numero;

    Scanner input = new Scanner(System.in);

    while (true) {
        numero = input.nextInt();
        if(numero == -1) break;
        System.out.println(numero);
    }

  }
}

C

Exemplo 2

/**

  9.1
  Exemplo 2 - Usando a instrução BREAK para sair
  de um laço infinito.

**/
/**********************************************/

#include <stdio.h>

int main(void) {
  
  int N;

  while(scanf("%d", &N)){

    if(N == -1) break;

    printf("%d\n", N);

  }
  
  return 0;
}

C++

Exemplo 2

/**

  9.1
  Exemplo 2 - Usando a instrução BREAK para sair
  de um laço infinito.

**/
/**********************************************/

#include <iostream>

using namespace std;

int main(){

    int N;

    while (true) {
      cin >> N;

      if(N == -1) break;

      cout << N << "\n";
    }

  return 0;
}

Python

Exemplo 2

'''

  9.1
  Exemplo 2 - Usando a instrução BREAK para sair
  de um laço infinito.

'''
'''*********************************************'''

while 1:
  N = int(input())
  if N == -1:
    break
  else:
    print(N)

Arduino

Exemplo 2

/**

  9.1
  Exemplo 2 - Usando a instrução BREAK para sair
  de um laço infinito.

**/
/**********************************************/

void setup() {
  
  Serial.begin(9600);
  
  int N;

  while (true) {
      N = Serial.read();
      if(N == -1) break;
      Serial.print(N+"\n");
  }
}

void loop() {

}

9.2. Utilizando o For

O for é muito utilizado quando precisamos iterar por algum vetor. Vamos pegar como exemplo um vetor de 10 posições, no qual queremos imprimir apenas alguns de seus valores, mais especificamente os índices de 2 à 5. A estrutura do for permite acessar facilmente esses índices pois basta iniciarmos a variável de controle N com o valor inicial 2 e, na expressão lógica a ser satisfeita, definirmos que o bloco de instrução deverá se repetir enquanto a variável N for menor que 6.

Veja o exemplo abaixo onde iteramos por cada índice do vetor e imprimimos os respectivos valores.

Java

Exemplo 1

/**

  9.2
  Exemplo 1 - Imprimindo os elementos de um 
  vetor com a estrutura de repetição FOR.

**/
/**************************************************/

class Main {
  public static void main(String[] args) {

    int vetor[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    for(int N=2; N<6; N++){
      System.out.println(vetor[N]);
    }

  }
}

C

Exemplo 1

/**

  9.2
  Exemplo 1 - Imprimindo os elementos de um 
  vetor com a estrutura de repetição FOR.

**/
/**************************************************/

#include <stdio.h>

int main(void) {
  
  int vetor[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  for(int N=2; N<6; N++){
    printf("%d\n", vetor[N]);
  }
  
  return 0;
}

C++

Exemplo 1

/**

  9.2
  Exemplo 1 - Imprimindo os elementos de um 
  vetor com a estrutura de repetição FOR.

**/
/**************************************************/

#include <iostream>

using namespace std;
 
int main()
{

  int vetor[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  for(int N=2; N<6; N++){
    cout << vetor[N] << "\n";
  }
 
    return 0;
}

Python

Exemplo 1

'''

  9.2
  Exemplo 1 - Imprimindo os elementos de um 
  vetor com a estrutura de repetição FOR.

'''
'''**************************************************'''

vetor = (0, 1, 2, 3, 4 , 5, 6, 7, 8, 9)

for numero in range(2 , 6):
    print(numero)

Arduino

Exemplo 1

/**

  9.2
  Exemplo 1 - Imprimindo os elementos de um 
  vetor com a estrutura de repetição FOR.

**/
/**************************************************/

void setup() {
  
  Serial.begin(9600);
  
  int vetor[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  int tamanhoVetor = 10;

  for(int N=2; N<6; N++){
    Serial.print(vetor[N]+"\n");
  }

}

void loop() {

}

Esses são os exemplos mais comuns que costumam surgir para quem está começando a aprender programação, mas como dito antes existem uma infinidade de utilizações possíveis para tais estruturas de repetição. Esses são conhecimentos que apenas se adquire programando muito.

Qualquer dúvida deixem nos comentários abaixo ou se preferir faça parte do nosso canal no Discord.

Até o Próximo Artigo!


25 Posts