VOLPITI - Tecnologia da Informação
 
Busca
Tópicos
  Cadastre-se :: Hospedagem LinuxDicas :: Acessórios LinuxDicas :: Fórum LinuxDicas   

Usuários LinuxDicas
· AvantGO
· Backend XML (RSS)
· Contato/Publicidade
· Enviar Notícias/Artigos
· Fórum LinuxDicas
· Lista de Discussão
· Mensagens Privadas

Casa do Linux


Lista de Discussão
·[linuxdicas] quetão de linux
·Ferramenta de Backup
·redes
·Search Engine

Leia mais...

Artigos LinuxDicas
· Resistência ao Linux
· Guia para o Novato
· Licenciamento do SuSE
· Foca GNU/Linux - Iniciante
· Foca GNU/Linux - Intermediário
· Foca GNU/Linux - Avançadoe
· Curso C
· Outras Seções de Artigos

FAQ LinuxDicas
· Licença
· Servidores
· Ambiente X
· Hardware
· Instalação
· Internet
· Aplicativos
· Sistema
· StarOffice

Notícias Velhas
Segunda, abril 21
· MON - Monitorando a disponibilidade de serviços
Quinta, abril 17
· Últimos dias para Inscrições de Palestras no Flisol Campinas
· Acessando seus arquivos de sua máquina de qualquer computador do mundo
Terça, abril 15
· Artigo sobre o Moregroupware
Segunda, abril 14
· Análise do Mandriva Xtreme2 Pack
Terça, março 18
· Como migrar dados do msaccess para mysql
· A verdadeira razão para usarmos Linux
· usando o rsync 3.0.0 para fazer backup entre linux e xp
· Firefox3 : Como Instalar manualmente.
Sábado, fevereiro 09
· Configurando um DNS CHROOTED Primário e Reverso para o seu site.
Quinta, dezembro 27
· Censurando a internet com o OpenDNS
Domingo, outubro 14
· Bandwidth Monitoring Tools For Linux
Quinta, outubro 11
· Variáveis de ambiente
Quinta, agosto 02
· Rodando processos em múltiplos servidores, Cluster!!!
· Instalando XEN no seu Ubuntu/Debian
Domingo, junho 17
· Vovó, faz backup pra mim?
Quarta, junho 13
· Canetas: Idealismo Antártico
Quinta, junho 07
· CA confiável com certificados digitais
Domingo, junho 03
· Equações Matemáticas via Shell
Sábado, junho 02
· Permanent Link to Garimpar é preciso [2]: Confira seu e-mail

Notícias antigas

Versões Estáveis
· Kernel Linux
· *nix e *BSD ISOs da Unicamp
· Linux ISO
· FreeBSD Releases

Curso de C - 7. Estruturas de Repetição

(2743 total de palavras neste texto)
(4230 vizualização(ões))   Imprimir




Curso de C - 7. Estruturas de Repetição

Suponhamos que você queira fazer um programa que lê 100 números do teclado e para cada número verifique se é múltiplo de 3, imprimindo a resposta para cada um. Como você escreveria este programa?

Seria assim?

  #include <stdio.h>

  
  main()
  {
  	int num;
  	
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	if ((num %3) == 0)
  		printf("é múltiplo de 3\n");
  	else
  		printf("não é múltiplo de 3\n");
  		
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	if ((num %3) == 0)
  		printf("é múltiplo de 3\n");
  	else
  		printf("não é múltiplo de 3\n");
  		
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	if ((num %3) == 0)
  		printf("é múltiplo de 3\n");
  	else
  		printf("não é múltiplo de 3\n");
  		
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	if ((num %3) == 0)
  		printf("é múltiplo de 3\n");
  	else
  		printf("não é múltiplo de 3\n");
  		
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	if ((num %3) == 0)
  		printf("é múltiplo de 3\n");
  	else
  		printf("não é múltiplo de 3\n");
  	
  	
  	etc .....................
  }

Como você pode ver, não é uma técnica nada viável, pois temos que repetir a mesma sequência de comandos várias vezes. Mas não se desespere... Nesta aula veremos que C, assim como outras linguagens, tem vários comandos que nos ajudam em tarefas repetitivas como esta. Estes comandos são conhecidos como estruturas de repetição ou laços. Veremos também algumas técnicas básicas que nos ajudarão a criar programas iterativos.

Para começar, vamos estudar o laço for.

7.1. O laço for

O laço for é uma estrutura de repetição controlada por variável, onde devemos saber de antemão a quantidade de iterações. O laço for tem a seguinte forma geral:

  for (inicialização; teste condicional; incremento ou decremento)
  {
  	comandos;
  }
   
   
  OU
  
  
  for (inicialização; teste condicional; incremento ou decremento)
  	comando único;

Veja este exemplo:

  #include <stdio.h>
  
  main()
  {
  	int i, num;
  	
  	for (i=0; i<100; i++)
  	{
  		printf("Digite um número: ");
  		scanf("%d", &num);
  		getchar();
  		if ((num %3) == 0)
  			printf("é múltiplo de 3\n");
  		else
  			printf("não é múltiplo de 3\n");
  	}
  	return 0;
  }

Veja só o nosso exemplo revisitado, com o uso de for.

Como você pode ver, o laço for contém 3 expressões entre parênteses, que controlarão o modo que o nosso laço trabalhará:

  • Na expressão inicialização, atribuímos valor inicial à variável de controle. No exemplo acima, inicializamos i com 0.
  • Em teste condicional, temos uma expressão relacional/lógica que definirá o critério de parada do nosso laço. No nosso //detector de múltiplos de 3//, o laço for ficará repetindo o bloco de comandos enquanto a variável i for menor que 100. Quando i tiver o valor 100, o laço não executará mais os comandos do bloco de comandos, e o programa continuará sua execução (no nosso caso, executará return 0 e depois terminará.).
  • A expressão incremento ou decremento deve dizer para o laço for como a variável vai "andar", se é de 1 em 1, de 2 em 2, de 10 em 10, etc. No nosso programa acima, a expressão i++ faz a variável i ser incrementada de 1 em 1.
Trocando em miúdos, no laço for do nosso programa, a variável i será inicializada com 1, andará de 1 em 1, e quando chegar a 100 sairá do laço.

Viu como é fácil?

7.2. Flexibilidade do laço for

Mas não é só isso... As 3 espressões do laço podem conter várias instruções separadas por vírgula. Vamos ver um exemplo:

  #include <stdio.h>

  
  main()
  {
  	int i, j, num;
  	
  	for (i=0, j=0; i+j <100; i++, j++)
  		printf("%d\n", i+j);
  	return 0;
  }

Veja que na inicialização, temos duas variáveis sendo atribuídas com 0: i e j, separadas por vírgula. Na parte de incremento, i e j são incrementadas com 1, também separadas por vírgula. Isto torna o laço for bastante flexível, onde o limite é a sua criatividade... Mas cuidado para não construir laços for monstros, com expressões enormes e de difícil compreensão...

Além disso, podemos omitir qualquer uma das expressões do laço for. Por exemplo:

  for ( ; i<100; i++)
  {
  	comandos;
  }

Nesse caso, não haverá a inicialização.

Outro exemplo:

  for (i=0; i<100; )
  {
  	comandos;
  }

Aqui, não há o incremento... Ele pode ser feito dentro do bloco de código do laço.

Em alguns casos, podemos usar o laço for como um laço infinito. Veja como:

  for ( ; ; )
  {
  	comandos;
  }

Este é um laço for infinito. Sua execução nunca terminará, a menos que haja um return ou um break dentro dele.

Ou então, você pode usar o laço for sem o bloco de código. Por exemplo, em um compilador, que lê os caracteres do código fonte e deseja ignorar os espaços, podemos fazer assim:

  for ( ; *str == ' '; str++);

Elegante, não? Ou digamos que você queira ignorar as quebras de linha:

  for ( ; *str == '\n'; str++);

Ou as tabulações:

  for ( ; *str == '\t'; str++);

Ou então, chutando o balde e colocando tudo em um só for:

  for ( ; ((*str == ' ') || (*str == '\n') || (*str == '\t')); str++);

Diferente de outras linguagens, C permite uma grande flexibilidade do laço for, o que o torna uma ferramenta bastante poderosa para o programador.

7.3. O laço while

O laço while é uma estrutura de repetição que só repetirá o bloco de código se a condição, entre parênteses, for verdadeira. Esta condição pode ser qualquer expressão, onde falso é 0 e verdadeiro é diferente de 0. Se a condição for falsa logo no início do while, o laço não será executado.

Forma geral:

  while (condição)
  {
  	comandos;
  }
  
  
  	OU
  
  while (condição)
  	comando único;

Quando o programa chega no while, ele verifica a condição entre parênteses. Se for verdadeira, ele executa o bloco de códigos. Quando termina de executar os comandos do bloco de código, ele volta para o while novamente, testa a condição de novo e, se for verdadeira, executa o bloco de código novamente. Faz isso até a condição entre parênteses ser falsa, momento em que o programa continua a execução normalmente, depois do while.

Vamos ver alguns exemplos:

  #include <stdio.h>

  #include <ctype.h>
  
  main()
  {
  	int cont=0, i= 0;
  	char ch;
  
  	while (i < 10)
  	{
  		printf("Digite um caractere: ");
  		scanf("%c", &ch);
  		getchar();
  		if (isdigit(ch))
  			cont++;
  		i++;
  	}
  	printf("Você digitou %d caracteres numéricos\n", cont);
  	return 0;
  }

Aqui, o programa utiliza a função isdigit(), presente no arquivo de cabecalho ctype.h. O ctype.h contém funções para teste e conversão de caracteres.

Neste programa, o while executará 10 vezes, só terminando quando i chegar ao valor 10. Aqui vemos uma técnica que usamos muito em várias aplicações: um contador. A variável cont é inicializada com zero; quando, dentro do while, o cara digitar um caractere numérico, esta variável é incrementada de 1. Ao final da execução, ela terá o número exato de caracteres numéricos que foram digitados.

Outro exemplo:

  #include <stdio.h>

  
  main()
  {
  	int i=0, num, res= 0;
  	
  	while (i < 5)
  	{
  		printf("Digite um número: ");
  		scanf("%d", &num);
  		res= res+num;
  		i++;
  	}
  	printf("Somatória: %d\n", res);
  	return 0;
  }

Neste, outra técnica bastante utilizada: a somatória de um conjunto de números.

Funciona assim: ao entrar no while, o cara digita um número, que será armazenado na variável num. Esse número é somado com o valor da variável res (que na primeira iteração é 0) e armazenado em res. Na próxima iteração, o valor da variável res (a soma da iteração passada) é somada com num e armazenada em res novamente, assim sucessivamente até acabar o laço. Ao final do laço, o que temos em res é a somatória de todos os números digitados.

Mais uma técnica: imagine que você queira somar os números digitados até que seja digitado um número maior que 100. Você pode criar uma variável que muda de valor quando essa condição for satisfeita. É o que chamamos de flag. Exemplo:

  int num;
  int flag= 0;
  
  while (flag == 0)
  {
  	printf("Digite um número: ");
  	scanf("%d", &num);
  	getchar();
  	
  	if (num > 100)
  		flag= 1;	/* flag muda de valor (indica que loop deve parar) */
  }

Lembrando que estas técnicas podem ser exploradas em qualquer tipo de laço, desde que sejam adaptadas para cada situação.

Assim como for, podemos fazer um laço infinito com o while também. Basta fazer o seguinte:

  while(1)	/* 1 é verdadeiro em C */
  {
  	comandos;
  }

É claro que em comandos deve haver alguma forma de sair do while, como um break, um return, um exit(), etc.

OBS: Evite usar comandos como break ou exit() dentro de laços, pois é uma prática pouco elegante. Só use quando não houver outro jeito.

7.4. O laço do-while

Diferente do while, que testa a condição antes de executar o seu bloco de código, o do-while primeiro executa o seu bloco de código para depois testar a condição. Ele é útil quando temos que executar no mínimo UMA VEZ o bloco de código do laço.

Forma geral:

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

No caso de haver um comando único, não é necessário delimitar com chaves, mas é recomendável, para não haver confusão e para deixar o código mais legível.

Vamos para os exemplos:

  #include <stdio.h>

  
  main()
  {
  	int num;
  	
  	do
  	{
  		scanf("%d", &num);
  		getchar();		
  	} while(num < 50);
  	return 0; 
  }

Neste programa, que não faz nada de útil, o bloco de código deve ser executado pelo menos uma vez, já que dependemos do valor da variável num para processar a condição, no final do laço. Aqui, o programa só sai do laço quando for digitado algum número maior ou igual a 50.

Agora um exemplo mais prático:

  #include <stdio.h>
  
  main()
  {
  	int opt;
  	
  	do
  	{
  		do
  		{
  			printf("**** Menu ****\n");
  			printf("1) Cadastrar\n");
  			printf("2) Buscar\n");
  			printf("3) Exibir Relatório\n");
  			printf("4) Sair\n");
  			printf("Digite sua opção: ");
  			scanf("%d", &opt);
  			getchar();
  		} while ((opt < 1) || (opt > 4));	/* o cara fica preso até digitar um número válido */
  		
  		switch(opt)
  		{
  			case 1:
  				cadastra();
  				break;
  			case 2:
  				busca();
  				break;
  			case 3: 
  				relat();
  				break;
  		}
  	} while (opt != 4);	/* laço principal, só sai quando opt for igual a 4 */
  	return 0;
  }

Como você pode ver, temos dois do-while. O mais externo e principal fica vigiando se o cara digitou 4 (se quer sair). Caso contrário, volta e executa tudo novamente.

O laço mais interno é uma técnica usada quando o usuário tem um menu, e tem que digitar uma opção para definir para que lado o programa vai. No nosso caso, se o espertinho do usuário digitar algum número maior que 4 ou menor que 1 (inválidos), o laço volta e joga tudo de novo na tela, esperando o "esperto" do usuário escolher a opção certa.

As funções cadastra(), busca() e relat() são fictícias e só serviram para ilustrar a situação.

Você viu que neste exemplo temos dois laços aninhados. Agora vamos falar um pouco sobre eles.

7.5. Laços aninhados

Laços aninhados não são laços dentro de ninhos... :) São laços dentro de laços (isso vai dar nó...).

Exemplo de laços for aninhados:

  for (i=1; i<=10; i++)
  {
  	for (j=1; j<=10; j++)
  	{
  		printf("%d X %d = %d\n", i, j, i*j);
  	}
  	printf("\n\n");
  	ch= getchar();
  }

Vejam que poder: com apenas 9 linhas imprimimos as tabuadas de 1 a 10!!

Exemplo de laços while aninhados:

  while(i <= 10)
  {
  	while(j <= 10)
  	{
  		printf("%d x %d = %d\n", i, j, i*j);
  		j++;
  	}
  	printf("\n\n");
  	ch= getchar();
  	i++;
  }

O mesmo exemplo das tabuadas usando while.

A lógica dos laços aninhados é a seguinte:

  • O laço mais externo entra em execução;
  • São executados os comandos do bloco até que o programa encontra o laço mais interno;
  • O laço mais interno também entra em execução;
  • Agora o laço mais interno fará todas as iterações possíveis, até acabar;
  • Acabando a execução do laço mais interno, o laço mais externo continua executando seu bloco de código;
  • Quando o último código do bloco de código é executado, o laço mais externo volta, testa e entra em execução novamente;
  • Aí encontra o laço mais interno novamente, que entra em execução até terminar;
  • E assim vai, até a condição de parada do laço mais externo ser satisfeita (the end).
Podemos ter vários laços aninhados, não somente 2. Podemos também ter laços for dentro de while ou do-while, e etc... Só tem uma coisa: quanto mais laços aninhados, mais lento será seu programa.

7.6. Comandos de desvio

C possui 4 comandos de desvio incondicional: return, goto, brek e continue.

O comando return é um velho conhecido nosso. Ele retorna de uma função, voltando para o local de onde a função foi chamada. Na função main(), ele faz encerrar o programa. Se estiver acompanhado de uma expressão, ele devolve o valor de uma expressão. Se estiver sozinho, é retornado lixo (alguns compiladores retornam 0 quando return está sozinho, mas não espere isso). Veremos mais sua utilização na aula sobre funções.

Forma geral:

  return expressão;

O comando goto é um comando escomungado pelos programadores, que evitam a sua utilização. Na prática, não existe nenhum caso que precise de goto, podendo ser usadas quaisquer estruturas para controle de fluxo (for, while, if, switch, etc...). Mas em algumas situações, se o goto for bem empregado, há um ganho de performance. Podemos ver que os programadores do kernel do Linux usam o goto em algumas construções, para obter melhor desempenho.

Forma geral:

  	rotulo:
  		comandos;
  		   .
  		   .
  		   .
  	goto rotulo;

O goto salta de onde o programa está para o rótulo, executando os comandos daí em diante.

De qualquer forma, evite usar goto.

O comando break pode ser usado no comando switch (já vimos exemplos) ou em laços. Nos dois casos, ele causa a imediata interrupção na execução, saltando para o próximo código após o switch ou o laço.

O comando continue é um pouco parecido com o break. Sua única diferença é que, ao invés de encerrar o laço e continuar do próximo comando em diante, ele força o laço ir imediatamente para a próxima iteração.

Além destes comandos, existe a função exit() que provoca uma terminação imediata do programa. Ela possui apenas um argumento, que é o código de retorno para o sistema operacional (como já sabemos, retornar 0 para o sistema operacional indica sucesso, e outros valores vários tipos de erros). Geralmente a função exit() é usada se uma condição obrigatória para a execução do programa não acontecer.

Por esta semana é só... Na próxima aula falaremos sobre Matrizes e Strings, com exemplos e exercícios. Até lá!


Exercícios

1) Faça um programa que imprima o maior e o menor número de uma sequência de 10 números lidos do teclado.

2) Faça um programa que leia as seguintes informações de 50 vacas: seu nome, seu peso, sua idade e a quantidade de litros de leite que cada uma dá por dia. Imprima o nome da vaca mais velha e da vaca que mais produz leite.

3) Faça um programa que leia um número e calcule o seu fatorial, lembrando que o fatorial de um número é: número * fatorial(número-1). Por exemplo, fatorial de 5: 5*4*3*2*1= 120; fatorial de 1: 1; fatorial de 0: 1.

4) Faça um programa que dados leia 10 caracteres e conte quantos caracteres 'a' aparecem (somente minúsculo).

5) Faça um programa que imprima a sequência de Fibonacci: 0 1 1 2 3 5 8 13 21 31 ... Como você pode ver, cada número é a soma dos dois números anteriores. O programa primeiro vai ler um número, que será a quantidade de iterações do laço.


Powered by txt2tags

  

[ Voltar Curso C | Índice de Seções ]


Copyright © 2002 - 2007 LinuxDicas - Todos Os Direitos Reservados.
LinuxDicas: lucas.martinez @linuxdicas.com.br
Web site engine's code is Copyright © 2003 by PHP-Nuke. All Rights Reserved. PHP-Nuke is Free Software released under the GNU/GPL license.
Tempo para gerar esta página: 0.049 segundos.