Aula por Rogério Júnior e João Pedro Castro
Na última aula exploramos as estruturas condicionais e aprendemos a direcionar o programa a partir de condições. Agora vamos aprender sobre os Loops, também conhecidos como laços ou estruturas de repetição. Com eles poderemos fazer nossos códigos repetirem determinadas tarefas quantas vezes quisermos, e é (mais uma vez) um dos pilares da programação, aparecendo na imensa maioria dos problemas; seja para receber um valor vezes, para realizar um cálculo mais complexo, etc.
Operadores de Atribuição
Esta breve sessão é só para introduzir operadores que servem para "economizar" código, ou seja, escrever menos e deixar ele mais fácil de ser lido. Eles são usados por todo programador de nível médio para cima, então é uma ótima ideia os aprender.
Já vimos algumas expressões como x = x + 1
, que significa: faça com que a variável x
tenha seu valor antigo adicionado em um. Por exemplo, se x = 5
, então depois dessa linha o valor de x
vira 6. Mas podemos escrever de outro jeito; no caso específico de expressões no formato x = x + y
(onde x
é uma variável e y
é um valor qualquer, podendo ser uma variável também) podemos fazer: x += y
. Outros exemplos:
x = x - y
x -= y
x = x * y
x *= y
x = x / y
x /= y
x = x % y
x %= y
No caso específico de adicionar 1 ou subtrair 1 de uma variável também existem outros tipos de operadores. Para acrescentar existe o x++
e o ++x
, assim como para subtrair existe o x--
e o --x
. Se essas expressões forem usadas com o objetivo exclusivo de incrementar/decrementar em 1 a variável, tanto faz usar a com o símbolo para direita ou esquerda (pós e pré incremento/decremento, respectivamente). Mas caso esse valor esteja sendo impresso, por exemplo, em cout << x++;
a ordem das operações é:
- Imprime o valor de x.
- Incrementa o valor de x em 1.
Enquanto no cout << ++x;
temos a ordem inversa. Então para um x = 7
, teríamos sendo impresso o 7 para o x++
, enquanto no caso do ++x
8 é impresso, mas depois do cout
em ambos os casos x
terá seu valor alterado para 8.
While
O while
se traduz para enquanto, e diferente do if
(se) é possível perceber pelo nome que ele é usado para um código ser repetido várias vezes. A sua estrutura básica é:
A condição segue o exato mesmo modelo da condição do if
, e o código é executado enquanto a condição for verdadeira. Cada repetição é chamada de iteração, podendo existir nenhuma, dez, um milhão, ou até infinitas iterações (loops infinitos, que devem ser evitados, afinal o código nunca termina de rodar). O fluxograma do while
é:
Seguem alguns exemplos de uso abaixo.
Imprimir os números de 1 até N
O que esse código está fazendo é inicializando uma variável auxiliar i
que começa em 1, e então declara um loop while que testa enquanto i <= n
. Para o caso de n = 10
temos a primeira checagem como 1 <= 10
que é verdadeiro, então entramos no código e 1
é impresso, assim como i
é incrementado em 1, virando 2 (se o i
não tivesse sido incrementado teríamos um loop infinito, que imprimiria infinitos 1).
Agora voltamos para a condição, que se tornou 2 <= 10
, que também é verdadeira; e assim segue até i = 10
, onde a condição de 10 <= 10
ainda é verdadeira, mas ao incrementar i
em 1, temos i = 11
, que torna a condição 11 <= 10
falsa, e quebra o loop. Perceba que poderíamos fazer esse mesmo código sem o while
, supondo que nas restrições do problema são n <= 100000
podemos fazer:
E o código ainda funcionaria da mesma forma. Obviamente escrever esse if
cem mil vezes é impraticável, mas é uma boa maneira de perceber como o while são só muitos (as vezes infinitos) if
juntos.
Contagem regressiva
Da mesma forma que fizemos no exemplo passado podemos realizar a contagem de até 1, dessa forma:
A lógica é a mesma, mas começamos com o i = 10
, e enquanto o i > 0
imprimimos o i
e depois o diminuímos em 1. Começando pelo 10, depois indo para o 9, etc, até o 1, e ao chegar no 0 o loop quebra.
Soma até parar
Adivinhe o número secreto
Tabuada - Problema para focar
Resolva esse problema antes de prosseguir. Não recomendo olhar a solução antes de tentar resolver por um bom tempo, sinta-se livre para voltar na aula e reler o conteúdo já passado.
For
O loop for
serve para deixar o código mais conciso em alguns casos específicos, como percorrer estruturas de dados (que iremos falar na próxima aula), e também códigos onde uma inicialização é necessária (como uma variável auxiliar), juntamente da condição e atualização, tudo em uma única linha. Essa é sua estrutura básica:
Ele acaba sendo o loop principal, pois essas três características são usuais em quase todo loop. Porém, lembre-se que é possível fazer qualquer loop somente com o while
, ou somente com o for
, a questão é que em alguns casos é mais confortável usar um, ou outro. Esse é o seu fluxograma:
Note que a inicialização ocorre somente uma vez, no começo, enquanto a condição é checada antes de toda iteração, e a atualização ocorre depois de toda iteração. Um aviso muito importante, que já falei na aula anterior, é o de que variáveis declaradas dentro de um loop ou estrutura condicional só existem dentro daquele único loop ou estrutura condicional, e tentar usar elas fora receberá um erro ao compilar de was not declared in this scope
. Segue alguns exemplos de uso.
Imprimir os números de 1 até N
Viu como o código fica bem mais curto? O i = 1
é colocado na inicialização, e a condição é a mesma do while
(i <= n
); por fim, a atualização é i++
, e ocorre depois de toda iteração. A lógica é a mesma do while
, então não acho que tenha necessidade de explicar.
Fibonacci
Podemos calcular quantos termos quisermos da sequência de fibonacci com loops. Se você não sabe o que ela é, basicamente é uma sequência infinita que começa com 1, 1
e o próximo termo é achado somando os dois anteriores, por exemplo, os primeiros 7 termos são: 1, 1, 2, 3, 5, 8, 13, ...
. Vamos fazer um programa que ache os primeiros termos da sequência de fibonacci.
Primeiro vemos o caso de e , já que nós começamos imprimindo 1, 1
na solução geral. Depois, para um fazemos o processo de guardar o penúltimo e o último termo da sequência, e então imprimimos a soma deles, e atualizamos o seus valores usando de uma variável auxiliar. Perceba que por mais que declaremos o i
no for
, não o usamos em momento algum no cálculo, mas sim somente para ter certeza que passamos por um número determinado de iterações (nesse caso passamos por já que imprimimos 2 números logo no começo).
Comandos de Controle do Loop
Esses dois comandos servem para controlar o loop durante sua execução, e geralmente aparecem dentro de estruturas condicionais para em alguns casos específicos interromper o loop ou pular uma iteração. Ambos podem ser utilizados tanto no while
quanto no for
.
Break
Quando o comando break
é encontrado dentro de um loop, ele interrompe imediatamente a execução desse loop e o programa continua a partir do próximo comando após o loop. Por exemplo, no seguinte código:
O loop for
segue até o i = 5
onde a execução do mesmo é finalizada, e a execução segue para o próximo comando (e como ele não existia o execução acaba). Note que caso o comando break
viesse depois do cout
a saída seria 0 1 2 3 4 5
, já que o loop só seria finalizado após a impressão do 5.
Continue
O comando continue
é usado para pular a iteração atual do loop e continuar com a próxima iteração, ignorando o restante do código dentro do loop para a iteração atual. Quando o continue
é encontrado, o controle do loop é passado imediatamente para a próxima iteração. Segue um código de exemplo:
O loop for
segue até o i = 5
onde a iteração é pulada, e a execução segue para a próxima iteração, ignorando o restante do código que continha a impressão. Note que caso o continue
viesse após a impressão, a saída seria exatamente igual à aquela sem o continue
, já que o mesmo se encontraria no final do código, e portanto não pularia nada na iteração do i = 5
.
Extra - Loop dentro de loop
Esse assunto só vai ser usado quando você chegar na parte de matrizes do curso, mas irei explicar logo agora já que é parte do assunto de loops. Imagine que no planeta Nlog temos horas em um dia, e minutos em cada hora. Caso quiséssemos simular todos os horários dentro de um dia possíveis, como em um relógio digital, como faríamos? A maneira mais direta seria usando um loop dentro de outro loop. O código fica assim:
Ao rodar localmente e colocar a entrada como 3 5
, por exemplo, você tem:
Assim, pode ficar mais fácil de perceber que um loop dentro de outro funciona da mesma forma que um relógio. O loop "interior" é como o ponteiro menor, e somente quando o loop interior dá uma "volta" completa uma iteração do exterior é concluída e a próxima começa, ou loop termina se não existe próxima.
Fim
Agora o universo de problemas que você pode resolver se expandiu novamente, parabéns! Vá para página anterior e resolva os problemas recomendados para continuar sua jornada de aprendizado ?