Aula 08 - Estruturas de Controle de Repetição Quantificadas

Introdução

Para ilustrar a utilidade das estruturas de controle de repetição quantificadas, também conhecidas como laços, iremos usar o exercício proposto na Atividade 8.1. Tente resolver esse exercício com os conhecimentos que você já possui.

Atividade 8.1

Crie um script em Ruby que lê um número inteiro e mostra a tabuada de multiplicação desse número de 1 a 10.

Para resolver o problema proposto na Atividade 8.1, provavelmente você produziu um script parecido com o ilustrado no Exemplo de código 1.
  
    puts "Digite um número: "
    numero = gets.chomp.to_i

    puts "#{numero} x 1 = #{numero * 1}"
    puts "#{numero} x 2 = #{numero * 2}"
    puts "#{numero} x 3 = #{numero * 3}"
    puts "#{numero} x 4 = #{numero * 4}"
    puts "#{numero} x 5 = #{numero * 5}"
    puts "#{numero} x 6 = #{numero * 6}"
    puts "#{numero} x 7 = #{numero * 7}"
    puts "#{numero} x 8 = #{numero * 8}"
    puts "#{numero} x 9 = #{numero * 9}"
    puts "#{numero} x 10 = #{numero * 10}"
  

Exemplo de código 1 - Solução da Atividade 8.1 sem usar laços

Observe que, para resolver esse problema usando apenas os conhecimentos que temos atualmente, precisamos escrever repetidas vezes uma ação específica: multiplicar o número informado pelo usuário por um outro número (linhas 4 a 13). Para esse problema específico, precisamos realizar essa ação apenas 10 vezes, mas e se o problema exigisse que executássemos a ação 100 vezes? Ou 1000 vezes? Iríamos escrever a mesma linha de código várias vezes? E pior: o problema pode exigir que a ação seja executada um número variável de vezes.

Para resolver problemas como esse, em que ações precisam ser feitas repetidas vezes, é que devemos utilizar as estruturas de controle de repetição quantificadas. Essas estruturas são ditas quantificadas porque elas executam um número determinado de vezes.

Estruturas de controle de repetição quantificadas em Ruby

A linguagem Ruby possui três estruturas de controle de repetição quantificadas: o for, o each e o times.

Estrutura de repetição: for

O for (para) é uma estrutura de repetição muito comum e presente em quase todas as linguagens de programação. O Exemplo de código 2 ilustra a sintaxe do for.

  
    for variavel in expressao
      # Código a ser executado repetidamente
    end
  

Exemplo de código 2 - Sintaxe do for

O Exemplo de código 3 ilustra um exemplo de uso do for.

  
    for i in 1..10
      puts "O valor de i é #{i}"
    end
  

Exemplo de código 3 - Exemplo de uso do for

Conforme explicamos anteriormente, o for é uma estrutura de repetição que executa um trecho de código várias vezes. Cada execução do for é chamada de iteração. Portanto dizemos que um for que executa 10 vezes possui 10 iterações. Observe, no Exemplo de código 3, que declaramos a variável i. Essa variável só existe dentro do for e ela assume um valor entre 1 e 10 a cada iteração. Na primeira execução do for, o valor de i é 1; na segunda execução do for, o valor de i é 2; na terceira execução do for, o valor de i é 3, e assim sucessivamente. O último valor que a variável i vai receber é 10.

Ao executar o código apresentado no Exemplo de código 3, você deverá observar o resultado abaixo.

  
    O valor de i é 1
    O valor de i é 2
    O valor de i é 3
    O valor de i é 4
    O valor de i é 5
    O valor de i é 6
    O valor de i é 7
    O valor de i é 8
    O valor de i é 9
    O valor de i é 10
  

Observe que o trecho de código dentro do for foi executado 10 vezes, e a cada iteração foi apresentado o valor da variável i.

Atividade 8.2

Resolva o problema proposto na Atividade 8.1 utilizando o for.

O Exemplo de código 4 ilustra uma solução para o problema proposto na Atividade 8.2.

  
    puts "Digite um número: "
    numero = gets.chomp.to_i

    for i in 1..10
      puts "#{numero} x #{i} = #{numero * i}"
    end
  

Exemplo de código 4 - Solução do problema proposto na Atividade 8.2

Observe, no Exemplo de código 4, que a linha de código que se repetia no Exemplo de código 1 foi usada apenas uma vez dentro do for. O for vai se encarregar de executar o que está dentro dele 10 vezes, conforme o intervalo definido na linha 4 (1..10).

Atividade 8.3

Crie um script em Ruby que leia um número inteiro X e mostre os números pares entre 1 e X.

Estrutura de repetição: each

O each (cada), na realidade, não é uma estrutura de repetição, mas sim um método. Os métodos serão abordados na Unidade II - Programação Orientada a Objetos, mas, como o método each se assemelha muito e pode ser usado como uma estrutura de repetição, ele será apresentado nessa seção.

O each se parece muito com o for, contudo, existem duas formas de se escrever o each, apresentadas no Exemplo de código 5 e no Exemplo de código 6.

  
    expressao.each do |variavel|
      # Trecho de código executado repetidamente
    end
  

Exemplo de código 5 - Sintaxe da estrutura de repetição each

  
    expressao.each { |variavel|
      # Trecho de código executado repetidamente
    }
  

Exemplo de código 6 - Sintaxe da estrutura de repetição each

Não há diferença de comportamento entre as duas formas de construir o each, portanto, escolha aquela que preferir. O Exemplo de código 7 ilustra um exemplo de uso do each: uma contagem de 1 a 10.

  
    (1..10).each do |i|
      puts "O valor de i é #{i}"
    end
  

Exemplo de código 7 - Exemplo de uso do each

Ao executar o Exemplo de código 7, você vai observar uma contagem de 1 a 10, pois esse foi o intervalo definido na linha 1 (1..10). O Exemplo de código 8 ilustra uma solução da Atividade 8.1 usando o each.

  
    puts "Digite um número: "
    numero = gets.chomp.to_i

    (1..10).each do |i|
      puts "#{numero} x #{i} = #{numero * i}"
    end
  

Exemplo de código 8 - Solução da Atividade 8.1 usando o each

Observe que, novamente, não há repetição de linhas de código, pois o each vai se encarregar de executar a linha 5 repetidamente (10 vezes).

Atividade 8.4

Crie um script em Ruby que leia um número inteiro X e mostre todos os números entre 1 e X que são divisíveis por 3 ou por 5.

Estrutura de repetição: times

O times (vezes) também não é uma estrutura de controle de repetição, mas sim um método da classe Integer, conforme vamos estudar mais à frente, quando estivermos aprendendo sobre Programação Orientada a Objetos. Contudo, o método times também é muito utilizado para executar trechos de código repetidamente. Assim como o each, também existem duas formas de se construir o times. Observe a sintaxe do times no Exemplo de código 9 e no Exemplo de código 10.

  
    expressao.times do
      # Trecho de código executado repetidamente
    end
  

Exemplo de código 9 - Sintaxe do times

  
    expressao.times { |variavel|
      # Trecho de código executado repetidamente
    }
  

Exemplo de código 10 - Sintaxe do times

Uma diferença entre as duas formas de construir o times é que a primeira forma, ilustrada no Exemplo de código 9, dispensa o uso de uma variável auxiliar. Para ilustrar o exemplo da contagem usando o times, observe o Exemplo de código 11.

  
    10.times { |i|
      puts "O valor de i é #{i}"
    }
  

Exemplo de código 11 - Exemplo de uso do times

Ao executar o Exemplo de código 11, você deverá observar o seguinte resultado.

  
    O valor de i é 0
    O valor de i é 1
    O valor de i é 2
    O valor de i é 3
    O valor de i é 4
    O valor de i é 5
    O valor de i é 6
    O valor de i é 7
    O valor de i é 8
    O valor de i é 9
  

Observe que, diferentemente das estruturas for e each, o times iniciou o valor da variável auxiliar em 0 (zero). Isso ocorre porque, no for e no each, nós podemos configurar o valor inicial e final da variável auxiliar, contudo não podemos fazer o mesmo no times. A variável auxiliar do times sempre irá começar com o valor 0 (zero).

O Exemplo de código 12 ilustra uma solução da Atividade 8.1 usando o times.

  
    puts "Digite um número: "
    numero = gets.chomp.to_i

    11.times { |i|
      puts "#{numero} x #{i} = #{numero * i}"
    }
  

Exemplo de código 12 - Solução da Atividade 8.1 usando o times

Observe, na linha 4, que precisamos usar 11.times para que o valor da variável auxiliar varie entre 0 e 10. Ao executar o Exemplo de código 12, você deverá observar algo parecido com o seguinte.

  
    Digite um número:
    2
    2 x 0 = 0
    2 x 1 = 2
    2 x 2 = 4
    2 x 3 = 6
    2 x 4 = 8
    2 x 5 = 10
    2 x 6 = 12
    2 x 7 = 14
    2 x 8 = 16
    2 x 9 = 18
    2 x 10 = 20
  

Controlando a Execução de Laços

As execuções dos laços podem ser controladas através dos comandos break, next e redo. Cada uma tem uma utilidade específica para controle de execução das estruturas de repetição, conforme será apresentado a seguir (RANGEL, 2014).

O comando break

O comando break (quebrar/romper) interrompe a execução do laço. O Exemplo de código 13 ilustra um exemplo de uso do comando break.

  
    for i in 1..10
      if i == 7
        break
      end
      puts "O valor de i é #{i}"
    end
  

Exemplo de código 13 - Exemplo de uso do break

Observe, no Exemplo de código 13, que o each está configurado para executar 10 vezes. Dentro do each há um if para verificar se o valor da variável i é igual a 7. Se for, o break é executado, interrompendo a execução do each. O resultado da execução do Exemplo de código 13 é apresentado abaixo.

  
    O valor de i é 1
    O valor de i é 2
    O valor de i é 3
    O valor de i é 4
    O valor de i é 5
    O valor de i é 6
  

Observe que o laço é executado 6 vezes. Na 7ª execução do laço, na qual o valor de i é 7, a execução é interrompida com a execução do break. Vale salientar que, se houverem dois laços aninhados (um laço dentro do outro), o break irá interromper apenas a execução do laço interno. Observe o Exemplo de código 14, que ilustra esse cenário.

  
    for i in 1..10
      puts "i = #{i}"
      for j in 1..10
        puts "j = #{j}"
        if j > 5
          break
        end
      end
    end
  

Exemplo de código 14 - Exemplo de uso do break

O código apresentado no Exemplo de código 14 possui dois for, um externo (no qual a variável auxiliar é i) e um interno (no qual a variável auxiliar é j). Quando o break for executado na linha 6, ele irá interromper apenas a execução do for interno, mas não do externo.

O comando next

O comando next (próximo) é usado para pular a execução de uma iteração. O Exemplo de código 15 ilustra um exemplo de uso do comando next.

  
    for i in 1..10
      if i == 7
        next
      end
      puts "O valor de i é #{i}"
    end
  

Exemplo de código 15 - Exemplo de uso do next

Observe, no Exemplo de código 15, que o for está configurado para executar 10 vezes. Na 7ª iteração, na qual o valor de i é 7, o comando next é executado, interrompendo a execução da 7ª iteração e pulando para a próxima. Abaixo é apresentado o resultado da execução do Exemplo de código 15. Observe a ausência do "O valor de i é 7".

  
    O valor de i é 1
    O valor de i é 2
    O valor de i é 3
    O valor de i é 4
    O valor de i é 5
    O valor de i é 6
    O valor de i é 8
    O valor de i é 9
    O valor de i é 10
  

Vale salientar que, quando o comando next é executado dentro de um laço aninhado (um laço dentro de outro), ele irá pular a iteração apenas do laço interno, assim como ocorre com o break.

O comando redo

O comando redo (refazer) reexecuta a iteração atual. Observe o comportamento do redo no Exemplo de código 16

  
    for i in 1..10
      puts "O valor de i é #{i}"
      if i == 3
        redo
      end
    end
  

Exemplo de código 16 - Exemplo de uso do redo

O for está configurado para executar 10 vezes (linha 1). Contudo, quando o valor de i for igual a 3, o redo será executado (linha 4). Isso fará com que a 3ª iteração seja executada infinitamente. Isso é chamado de loop infinito: um laço que nunca para de executar. Portanto, ao executar o Exemplo de código 16, não espere a execução terminar, apenas feche a janela. Abaixo é apresentado o resultado da execução do Exemplo de código 16.

  
    O valor de i é 1
    O valor de i é 2
    O valor de i é 3
    O valor de i é 3
    O valor de i é 3
    O valor de i é 3
    O valor de i é 3
    O valor de i é 3
    ...
  

Observe que as duas primeiras iterações são executadas normalmente, e ao chegar na 3ª iteração, o laço for fica preso num loop infinito.

Referências

POINT, T. Ruby Tutorial. Tutorials Point. 2015. Disponivel em: http://www.tutorialspoint.com/ruby/. Acesso em: 12 nov. 2015.

RANGEL, E. Conhecendo Ruby. [S.l.]: Leanpub, 2014.

SOUZA, L. Ruby: aprenda a programar na linguagem mais divertida. 1. ed. São Paulo: Casa do Código, 2012. v. I.