MC102MN

Introdução a Algoritmos e programação de computadores

Aula VI, laços e repetição

Até agora, sempre era possível linearizar o fluxo dos programas que fizemos (ou seja: ordenar as linhas e qualquer execução do programa vai ou executar ou não executar uma dada linha). Isso não é a regra em programas de computador: inclusive, é um problema dificílimo determinar se um dado programa termina ou roda pra sempre.

Na aula de hoje vamos estudar estruturas de repetição, que são o jeito mais simples de fazer programas que fazem mais ou menos coisas dependendo do que o usuário faça. Da mesma forma que num "if" o bloco de código que vem depois do if ou else vai ser ou não executado a depender do valor de alguma variável, nos comandos de repetição os blocos de código podem ser executados várias vezes (ou nenhuma vez) a depender do valor das variáveis. Em C existem três comandos de repetição básicos: while, do…while e for.

O comando while

A estrutura do comando while é

while (<condicao>) {
 <bloco de codigo>
}
Da mesma forma como no if, as { } podem ser omitidas caso o bloco de código seja de apenas uma linha,
while (<condicao>)
  <expressão>;
mas é necessário tomar cuidado com esse tipo de construção para não introduzir o mesmo tipo de bug que pode ser colocado com ifs.

O bloco de código depois da expressão while vai ser executado enquanto a condição for verdadeira. Por exemplo, o programa seguinte soma o inteiro a ao inteiro b usando apenas incrementos e decrementos:

int soma(int a, int b) {
  while (b > 0) {
    a--;
    b++;
  }
  return a;
}

E a função a seguir calcula o piso do logaritmo de x na base 3:

int plog3(int x) {
  int p = 0;
  while (x > 1) {
    x /= 3;
    p += 1;
  }
  return p;
}

Alguns laços while podem nunca ser executados:

x = 1
while (x < 0) {
  printf("Ha!");
}
outros podem executar para sempre
x = 11
while (x != 0) {
  --x;
  y = 2 + x--;
}
e outros normalmente acabam, mas ninguém sabe explicar por que:
while (x > 1) {
  if (x % 2 == 0) {
    x /= 2;
  } else {
    x = 3*x+1;
  }
}

Por fim, uma função para elevar um número x a uma potência inteira:

double eleva(double x, int p) {
  int i = 0, res = 1;
  while (i < p) {
    res *= x;
  }
  return res;
}

O comando do…while

O do…while, ao contrário do while, sempre executa pelo menos uma vez. A forma do do…while é

do {
  <bloco de código>
} while (<condicao>);

No do…while você não pode omitir as {}.

Um exemplo é

int valor = 0, soma = 0;
do {
  soma += valor;
  scanf("%d", &valor);
} while (valor != -1);
que soma todos os valores digitados pelo usuário antes dele digitar -1.

O comando for

O comando for encapsula a fórmula mais comum para você utilizar um laço. A sua forma é

for (<inicializa>; <testa>; <atualiza>) {
  <bloco de código>;
}
(onde os {} são opcionais) e é equivalente a
<inicializa>;
while (<testa>) {
  <bloco de código>;
  <atualiza>;
}

Por exemplo, uma função para calcular x! é

int fatorial(int x) {
  int i, f = 1;
  for (i = 1; i <= x; ++i) {
    f *= i;
  }
  return f;
}

Qualquer um dos itens do for pode ser omitido, então você pode fazer

for(; i < 10; ++i) {
se i já estiver inicializado, por exemplo.

Sair de um laço

C possui dois comandos que podem sair de um laço: break e continue. Break sai de um laço no ponto em que você está, e continue volta para o começo do laço. Por exemplo, o trecho de programa a seguir soma todos os números positivos da entrada até que o usuário digite -99:

int soma = 0, i, n;
while (1) {
  scanf("%d", &n);
  if (n == -99) break;
  if (n <= 0) continue;
  s += n
}
printf("A soma é: %d\n", s);

Nota: como while checa uma condição até ela ser verdadeira e em C 1 é verdadeiro e 0 é falso, while (1) é um laço do qual vc só pode sair com break ou return.

Mais um exemplo

Vocês talvez saibam que . Como a precisão de um computador é finita, podemos calcular exp(x) somando essa série de taylor. Um jeito fácil de fazer isso é usando um for:

#define NTERMOS 10

double my_exp(double x) {
  int i, e = 0;
  for (i = 0; i < NTERMOS; ++i) {
    e += eleva(x,i)/fatorial(i);
  }
  return e;
}

Onde fatorial e eleva podem usar as definições acima.

Author: Alexandre Tachard Passos <alexandre.tp@gmail.com>

Date: 2010-08-19 13:47:51 BRT

HTML generated by org-mode 6.21b in emacs 23