Programação 1 - Engenharia - Comandos de Repetição no C
Objetivos
Após esta aula o aluno deverá:
- conhecer a sintaxe e a semântica dos comandos de repetição do C: while, do while, for e goto.
- utilizar comando break para sair de loops e o continue para interromper um laço específico;
- identificar quando usar variáveis inteiras com maior ou menor capacidade de armazenamento (char, unsigned, long).
- mapear estruturas simples de repetição especificadas em fluxogramas ou pseudo-código em estruturas em linguagem C.
Estruturas de Repetição
Existem 4 estruturas/comandos que permitem implementar loops ou repetições de blocos de código:
- while()
- do while()
- for()
- goto label
NOTA: Observe que repetir o código significa voltar a executá-lo (sem ter que escrevê-lo novamente) e normalmente sobre o controle de uma expressão lógica.
O comando 'while()': TESTE da REPETIÇÃO no começo
O comando while permite implementar loops com controle no início.
A semântica do while é a seguinte: ao entrar no comando a EXPRESSÃO entre parênteses é AVALIADA. Caso resulte em uma valor VERDADEIRO o LAÇO do loop é executado uma vez. O programa testa então novamente a expressão. LEMBRAR que:
- VERDADEIRO é qualquer valor diferente de ZERO;
- DENTRO do laço NORMALMENTE existe uma modificação de alguma parte da expressão de teste de forma que em algum momento o LOOP se encerra.
- Ao se encerrar o programa continua na próxima instrução APÓS o comando "while()";
- ANTES DE entrar no comando while SEMPRE tenha certeza que as variáveis estão com valores adequados de forma que a expressão SEJA AVALIADA sempre corretamente.
No exemplo que se segue existe UMA única instrução simples (terminada em ";").
#include <stdio.h>
int main()
{
int contador;
contador=0;
while (contador<5)
contador=contador+1;
printf("valor do contador = %d\n", contador);
return 0;
}
OBSERVE a seguir uma variação do exemplo anterior usando um bloco de instruções delimitado por "{" e "}"
#include <stdio.h>
int main()
{
int contador;
contador=0;
while (contador<5) {
printf("valor da expressão = contador < 5 é %d\n", contador<5);
printf("valor do contador = %d\n", contador);
contador=contador+1;
}
printf("NO FINAL a expressão contador < 5 é %d\n", contador<5);
return 0;
}
Notar que a expressão contador<5 assume valor 0 (falso) e 1 (verdadeiro).
A estrutura do comando, informalmente, é:
while (expressão) instrução_simples;
ou
while (expressão) { lista_de_instruções }
Vamos ver a correspondência do comando while com um fluxograma:
NOTE que no exemplo anterior o contador inicialmente DEVE conter um valor válido.
Exemplo 1
PROBLEMA: Elaborar um programa C para imprimir os números pares em ordem decrescente (até atingir 0 inclusive) a partir de um número N fornecido como entrada. Seguir o fluxograma mostrada abaixo.
DADOS DE ENTRADA: N (variável inteira)
DADOS DE SAÌDA: números pares impressos
SOLUÇÃO:
NOTE que existem outras soluções. Por exemplo, detectar se o número é par (ou ímpar) e depos fazer um loop decrementando de dois em dois (sugestão dos alunos). Esta última opção é mais eficiente em termos de tempo de execução.
#include <stdio.h>
int main()
{
int N,i;
printf("Entre com o valode N\n");
scanf ("%d", &N);
i=N;
while(i>=0) {
if (i%2==0) { /* parênteses em (i%2) é opcional porque o operador de resto tem precedência */
printf("%d\n", i);
}
i=i-1;
}
return 0;
}
Exemplo 2
PROBLEMA: Elaborar um programa C para computação do fatorial de um número conforme definição abaixo:
DADOS DE ENTRADA:número N (numero inteiro)
DADOS DE SAÌDA: FATORIAL computado
O fatorial é definido por:
SOLUÇÃO:
NOTE que a solução abaixo é simplificada pois não testa se a entrada é menor que ZERO.
#include <stdio.h>
int main()
{
int N,i,FAT;
printf("Entre com o valor de N\n");
scanf ("%d", &N);
i=N;
FAT=1;
while(i>1) {
FAT=FAT*i;
i=i-1;
}
printf("Valor de FAT de %d é %d\n", N, FAT);
return 0;
}
Exercício 1
Modificar o exercício do FATORIAL apresentado anteriormente para caso sejam lidos números negativos o programa pergunte novamente o número N. Usar um comando "while" adicional.
Antes de entrar com o valor de N, atribua um valor NEGATIVO, por exemplo -1 a N. A expressão de teste no comando "while" deve ser verdadeira enquanto N for negativo. Coloque o scanf dentro deste "while".
Solução Ex. 1 |
---|
#include <stdio.h>
int main()
{
int N,i,FAT;
printf("Entre com o valor de N\n");
scanf ("%d", &N);
while (N < 0){
printf("Entre com um novo valor de N\n");
scanf ("%d", &N);
}
i=N;
FAT=1;
while(i>1) {
FAT=FAT*i;
i=i-1;
}
printf("Valor de FAT de %d é %d\n", N, FAT);
return 0;
}
|
Exercício 2
Elaborar um programa C para computar a SOMA do fatorial de dois números inteiros fornecidos como entrada. O programa deve prever a entrada somente de números não negativos. Olhe as soluções acima e reproduza as estruturas propostas.
Solução Ex. 2 |
---|
#include <stdio.h>
int main()
{
int n1, n2,i,fat1, fat2;
printf("Entre com o valor do fatorial 1\n");
scanf ("%d", &n1);
printf("Entre com o valor do fatorial 2\n");
scanf ("%d", &n2);
while (n1 < 0){
printf("Entre com um novo valor de N1\n");
scanf ("%d", &n1);
}
while (n2 < 0){
printf("Entre com um novo valor de N1\n");
scanf ("%d", &n2);
}
i=n1;
fat1=1;
while(i>1) {
fat1=fat1*i;
i=i-1;
}
i=n2;
fat2=1;
while(i>1) {
fat2=fat2*i;
i=i-1;
}
printf("A soma dos fatoriais de N1 e N2 é %d\n", (fat1+fat2));
return 0;
}
|
Exercício 3
Elabore uma versão otimizada do programa que computa a soma do fatorial de dois números. Observe que poderíamos "economizar" laços de repetição se calcularmos o fatorial do menor número e depois computar o fatorial do maior usando o menor número como ponto de parada na repetição.
Solução Ex. 3 |
---|
#include <stdio.h>
int main()
{
int maior, menor, n1, n2,i,fat1, fat2;
printf("Entre com o valor do fatorial 1\n");
scanf ("%d", &n1);
printf("Entre com o valor do fatorial 2\n");
scanf ("%d", &n2);
while (n1 < 0){
printf("Entre com um novo valor de N1\n");
scanf ("%d", &n1);
}
while (n2 < 0){
printf("Entre com um novo valor de N1\n");
scanf ("%d", &n2);
}
if (n2>n1) {
maior = n2;
menor = n1;
} else {
maior = n1;
menor = n2;
}
i=menor;
fat1=1;
while(i>1) {
fat1=fat1*i;
i=i-1;
}
i=maior;
fat2=1;
while(i>menor) {
fat2=fat2*i;
i=i-1;
}
fat2=fat2*fat1;
printf("A soma dos fatoriais de N1 (%d)e N2(%d) é %d\n", fat1, fat2, (fat1+fat2));
return 0;
}
|
Desenhando no terminal MODO texto
A saída de um programa em um terminal modo TEXTO possui algumas limitações. Além da questão da definição, o programa escreve sempre na posição de um CURSOR que avança automaticamente. Em condições normais não é possível retornar o cursor para linhas acima. Deve-se portanto planejar cuidadosamente o desenho de figuras levando em consideração estas restrições. As instruções de repetição ajudarão bastante neste processo.
Exemplo: imprimir uma linha com 10 caracteres 'A'
AAAAAAAAA
#include <stdio.h>
int main()
{
int i;
i=0;
while (i<10) {
printf("A");
i=i+1;
}
printf("\n");
}
Exercício 1
Elaborar um programa para imprimir uma linha CUSTOMIZADA em 3 partes. Cada parte imprime um número variável de caracteres. O número de caracteres e o caracter a ser impresso em cada parte deve ser informado.
Solução Ex. 1 |
---|
#include <stdio.h>
int main(){
int p1,p2,p3,i;
char c1, c2, c3;
printf("Carcater a ser desenhado na primeira parte da linha\n");
scanf("%c", &c1);
printf("Quantidade de caracteres a ser desenhado na primeira parte da linha\n");
scanf("%d", &p1);
printf("Carcater a ser desenhado na segunda parte da linha\n");
scanf(" %c", &c2);
printf("Quantidade de caracteres a ser desenhado na segunda parte da linha\n");
scanf("%d", &p2);
printf("Carcater a ser desenhado na terceira parte da linha\n");
scanf(" %c", &c3);
printf("Quantidade de caracteres a ser desenhado na terceira parte da linha\n");
scanf("%d", &p3);
i=0;
while (i < p1) {
printf("%c", c1);
i=i+1;
}
i=0;
while (i < p2) {
printf("%c", c2);
i=i+1;
}
i=0;
while (i < p3) {
printf("%c", c3);
i=i+1;
}
printf("\n");
return 0;
}
|
Exercício 2
Modificar o exercício anterior para imprimir uma quantidade variável de LINHAS. As linhas são exatamente iguais.
Solução Ex. 2 |
---|
#include <stdio.h>
int main(){
int p1,p2,p3,i,j,linhas;
char c1, c2, c3;
printf("Carcater a ser desenhado na primeira parte da linha\n");
scanf("%c", &c1);
printf("Quantidade de caracteres a ser desenhado na primeira parte da linha\n");
scanf("%d", &p1);
printf("Carcater a ser desenhado na segunda parte da linha\n");
scanf(" %c", &c2);
printf("Quantidade de caracteres a ser desenhado na segunda parte da linha\n");
scanf("%d", &p2);
printf("Carcater a ser desenhado na terceira parte da linha\n");
scanf(" %c", &c3);
printf("Quantidade de caracteres a ser desenhado na terceira parte da linha\n");
scanf("%d", &p3);
printf("Informe a quantidade de linhas\n");
scanf("%d", &linhas);
j=0;
while (j < linhas){
i=0;
while (i < p1) {
printf("%c", c1);
i=i+1;
}
i=0;
while (i < p2) {
printf("%c", c2);
i=i+1;
}
i=0;
while (i < p3) {
printf("%c", c3);
i=i+1;
}
printf("\n");
j = j+1;
}
printf("\n");
return 0;
}
|
Comando do while: controle do loop no final
O comando do while() permite a repetição de uma ou mais instruções, com controle do loop no final. Isto permite que o bloco seja executado pelo menos uma vez.
#include <stdio.h>
main()
{
int contador;
contador=0;
do {
printf("valor do contador = %d\n", contador);
contador=contador+1;
} while (contador<5);
}
A estrutura do comando, informalmente, é:
do instrução_simples; while (expressão);
ou
do { lista_de_instruções } while (expressão);
Exemplo 1
Modificar o exemplo do cálculo do FATORIAL apresentado anteriormente para caso sejam lidos números negativos o programa pergunte novamente o número N. Usar um comando "do while" para construir o loop onde será realizado o scanf().
#include <stdio.h>
int main()
{
int N,i,FAT;
/* Leitura do número e
verificação se o número é negativo */
do {
printf("Entre com o valor de N\n");
scanf ("%d", &N);
if (N<0)
printf("Número negativo...");
} while (N<0);
/* computação do fatorial */
i=N;
FAT=1;
while(i>1) {
FAT=FAT*i;
i=i-1;
}
printf("Valor de FAT de %d é %d\n", N, FAT);
return 0;
}
Um problema na computação do fatorial é que rapidamente pode existir overflow', ou seja, ultrapassar a capacidade da da variável do tipo 'int'. VEJA a tabela abaixo com alternativas de inteiros com seus respectivos tamanhos.
TIPO | bytes | RANGE | COMENTÁRIO |
---|---|---|---|
char | 1 | -128 até 127 | um bit para o sinal |
short int | 2 | 32,768 to 32,767 | um bit para o sinal |
int | 4 | -2147483648 até 2147483647 | um bit para o sinal. Dependendo da máquina poderia ser 8 bytes |
long int | 8 | -9223372036854775808 até 9223372036854775807 | um bit para o sinal |
unsigned char | 1 | 0 to 255 | |
unsigned short | 2 | 0 to 65,535 | |
unsigned int | 4 | 0 to 4294967295 | |
unsigned long | 8 | 0 até 18446744073709551615 |
Execute o programa abaixo para conferir.
#include <stdio.h>
int main()
{
char num0;
short num1;
int num2;
long int num3;
/* Leitura do número e
verificação se o número é negativo */
printf ("tamanho de num0 = %ld\n", sizeof (num0));
printf ("tamanho de num1 = %ld\n", sizeof (num1));
printf ("tamanho de num2 = %ld\n", sizeof (num2));
printf ("tamanho de num3 = %ld\n", sizeof (num3));
return 0;
}
Exercício
Reimplementar o exemplo anterior usando o long int para computar o fatorial.
Exemplo 2
O programa abaixo foi extraído de (referência). Ele permite realizar a adivinhação de um número entre 1 e 10. Observe que as instruções permitem a geração do número randômico.
srand ( time(NULL) ); /* inicia o gerador com a semente baseada no relógio local */
iSecret = rand() % 10 + 1 /* gera o número */
// exemplo de geração randômica
// extracted and adapted from www.stackoverflow.com
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int segredo, sugestao;
/* iniciar semente: */
srand ( time(NULL) );
/* gerar o número secreto: */
segredo = rand() % 10 + 1;
do {
printf ("Adivinhe um número entre (1 a 10): ");
scanf ("%d",&sugestao);
if (segredo<sugestao)
printf ("O número secreto é menor\n");
else {
if (segredo>sugestao)
printf ("O número secreto é maior\n");
}
} while (segredo!=sugestao);
printf ("Parabéns!\n");
return 0;
}
Comando for()
O comando for() permite uma forma mais elaborada de loop, com controle no início do bloco de repetição.
#include <stdio.h>
main()
{
int i;
for (i=0;i<10;i=i+1)
printf("i =%d\n",i);
}
A estrutura do comando é:
for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) instrução_simples;
ou
for(expressão_inicial;expressão_de_controle; expressão_de_final_de _bloco) { lista_de_instruções }
|
ExemploElaborar um programa que lê um número inteiro e imprime todos os números pares entre 1 e este número INCLUSIVE. #include <stdio.h>
int main()
{
int i, N;
printf("Entre com o número\n");
scanf ("%d", &N);
for (i=1;i<=N;i=i+1) {
if (i%2==0)
printf("número par ====> %d\n", i);
}
printf("FIM\n");
return 0;
}
Aninhamento de loopsÉ muito comum que a solução de problemas exijam o aninhamento de loops. Neste caso, as instruções são aninhadas normalmente usando, se necessário, o recurso de bloco de instruções. Observe no código abaixo que para cada laço mais externo o comando for interno é executado integralmente. #include <stdio.h>
int main()
{
int i,j;
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
printf("valor de j = %d\n", j);
}
printf("valor de i = %d\n", i);
}
return 0;
}
Comando gotoO comando goto é um dos mais antigos da programação. A ideia é comandar um salto para um determinado ponto específico do programa marcado por um rótulo (LABEL). Para utilizá-lo deve-se, portanto, marcar o ponto para onde será feito o salto usando um LABEL. Exemplo: #include <stdio.h>
main()
{
int i;
i=0;
PONTO1:
printf("Laço de número %d\n", i);
i++;
if (i<10)
goto PONTO1;
}
Devido a ser uma instrução "desestruturante", em geral NÂO se recomenda o uso deste comando. Em alguns casos de tratamento de erro pode ser interessante o uso do goto. Leia um pouco mais sobre o goto aqui. Loop InfinitoÉ possível implementar loops infinitos com qualquer uma das instruções acima. Exemplo com comando for: main()
{
for(;;) {
/* Este bloco se executará infinitamente */
}
}
ou com o comando while: main()
{
while(1) {
/* Este bloco se executará infinitamente */
}
}
Uso de break para sair de loopsEm exercícios anteriores, a finalização de um loop normalmente se dá pela expressão de controle de loop associado a instrução usada. É possível sair de um loop na força bruta usando a instrução break: #include <stdio.h>
main()
{
int i,j;
for (i=0;i<10;i=i+1) {
if (i==5)
break;
}
printf("valor de i=%d\n", i);
}
Note que o break sempre sai do loop mais próximo a ele.
#include <stdio.h>
int main()
{
//break -> simplesmente interrompe o nosso ciclo
//continue -> interrompe o laço (desvia o fluxo para o início do laço)
int x;
for(x = 0; x<=10; x++){
//qndo x == 2, interrompa somente o laço atual
if(x == 2){
printf("Valor de x é 2 - fazendo continue...\n");
continue;
}
//Quando chegamos a 8 o looping será finalizado
if(x == 8){
printf("Valor de x é 8 - fazendo continue...\n", x);
break;
}
printf("%d\n", x);
}
}
ExercícioElabore um programa em C que leia no máximo 5 números inteiros positivos. Caso um número negativo seja digitado no meio da seqüência uma mensagem deve ser impressa uma mensagem de aviso no terminal e o laço é encerrado de imediato. Uso do continue para prosseguir no início do loop#include <stdio.h>
main()
{
int i,j;
for (i=0;i<3;i++) {
if (i==1) {
continue;
}
printf("valor de i = %d\n", i);
for (j=0;j<4;j++) {
if (j==1) {
continue;
}
printf("valor de j = %d\n", j);
}
}
}
Usando funções da biblioteca matemáticaPara usar as funções matemáticas da biblioteca padrão, fazer os seguintes passos:
#include <stdio.h>
#include <math.h>
main()
{
float x,y; /* declaração de duas variáveis reais */
printf ("Entre com o valor de x ");
scanf("%f",&x);
y = sqrtf(x);
printf ("Raiz de x = %.2lf", y);
}
NOTA: a maior parte de parâmetros e valores de retorno das funções matemáticas são reais de dupla precisão (double).
gcc ex1.c -o ex1 -lm EXERCÍCIOS - nível INICIANTE
EXERCÍCIOS - nível MÉDIO
|
---|