Na linguagem C o fluxo de
controle passa sequencialmente de um comando para o seguinte na ordem
convencional de leitura. Este é o tipo de estruturação mais simples do fluxo de
controle e é denominado seqüência. Considere o seguinte trecho de programa:
int a=2;
int b=3;
int c=4;
Quando o fluxo de controle
atinge a sentença int a=2; ocorre sua execução, em seguida ou na
seqüência o fluxo de controle se dirige para a sentença int b=3; e ocorre sua execução e na
seqüência o fluxo de execução atinge a sentença int c=4;
Na linguagem C podemos
agrupar uma seqüência de comandos através do uso de abre e fecha chaves - {}.
Os comandos assim agrupados passam a formar o que é denominado um bloco.
Quando o fluxo de controle atinge um bloco cada um dos comandos que formam o
bloco são executados em seqüência. O uso de blocos é especialmente importante
no caso de comandos condicionais e iterativos.
Nas linguagens de alto-nível
existem vários tipos de comandos denominados comandos condicionais que permitem
ao programador expressar que, em função do resultado de uma expressão, ele quer
que o fluxo de controle vá para diferentes grupos de comandos. Na linguagem C
um destes comandos é o comando if. O comando if tem a seguinte
forma:
if(<expressão>
) <comando1>; else <comando2>;
Quando o fluxo de controle atinge o comando if:
Ou seja, dependendo do valor da <expressão> , o fluxo de controle irá para <comando1> ou <comando2 de forma mutuamente exclusiva.
Abaixo são mostradas algumas formas do comando if:
if(<expressão>)
<comando1>; /* não tem a cláusula else */
A cláusula else é
opcional. Quando o fluxo de controle atinge um comando if que não contém a
clausula else, o fluxo de controle passa para a avaliação da expressão. Se o
resultado final da avaliação da expressão for (diferente de zero) true o fluxo
de controle passa para o <comando1> e após a execução do <comando1>
o fluxo de controle deixa o comando if. Se a expressão for (zero) false o fluxo
de controle deixa o comando if e o único efeito foi a avaliação da expressão.
if(<expressão>)
{ <c1>; <c2>; <c3>;} /* uso do bloco */
Quando queremos executar vários comandos juntos ao “então” ou vários comandos
juntos ao “senão” temos que usar o bloco - {}, para agrupá-los.
A seguir exemplificamos com alguns trechos de programa o uso do comando se-então-senão
na linguagem C
Obter o valor absoluto da
variável x:
if(x<0) valorAbsoluto=-x; else valorAbsoluto=x;
(equivale a valorAbsoluto= x<0 ? -x : x; )
Obter o maior valor entre x
e y:
if(x>y) maior=x;
else maior=y; /ou
if(x<=y) maior=y;
else maior=x;
Uma possível forma de generalização do comando se-então-senão é o
comando escolha. Podemos pensar no comando se-então-senão como
sendo um comando que tem uma expressão e que tem um comando associado ao valor (diferente
de zero) verdadeiro e um comando associado ao valor (zero) falso.
Quando a expressão é avaliada será executado o comando associado ao valor
resultante. No comando escolha temos uma expressão do tipo inteiro e
temos vários comandos associados a rótulos que correspondem a constantes
inteiras. O comando escolha na Linguagem C corresponde ao comando switch.
O comando switch permite a transferência do fluxo de controle para um de
vários pontos rotulados com uma constante inteira. A forma geral do comando é:
switch (<expressão>)
{
case <constante1>: <seqüência de comandos1>
case <constante2>: <seqüência de comandos2>
...
case <contanteN>: <seqüência de comandosN>
default: <seqüência de comandos default>
}
Quando o fluxo de controle
atinge o comando switch:
1.
a
expressão inteira é avaliada
2.
o
fluxo de controle passa para o comando rotulado com um valor correspondente ao
resultado da expressão avaliada. Caso não exista uma constante inteira com
rótulo correspondente ao valor da expressão inteira o fluxo de controle é
desviado para o comando rotulado com a palavra chave default.
3.
o
fluxo de controle passa a percorrer os comandos dentro do bloco e quando o
controle atinge o final do bloco o fluxo de controle deixa o comando switch. O fluxo de controle deixa o
comando switch quando não existe
rótulo com o valor da expressão inteira e também sem o rótulo default.
A parte do comando switch
entre abre e fecha chaves é conhecida como bloco do switch. O
bloco do switch pode ter comandos que sejam prefixados com rótulos
prefixados com a palavra chave case. Quando o fluxo de controle atinge o
comando switch a <expressão> é avaliada e o fluxo de controle será desviado
para a seqüência de comandos cuja constante do rótulo case tenha o mesmo
valor da <expressão>. O fluxo de controle continua ao longo de todo os comandos a partir
deste ponto, incluindo as outras seqüências de comandos. Se não existir um
rótulo case com uma constante que pareie (faça par, seja igual) ao
resultado da <expressão> o fluxo de controle será desviado para a seqüência de comandos com
rótulo default. O rótulo default é opcional no bloco do switch
e caso o resultado da <expressão> não tenha um rótulo case com contante
que o pareie e não exista um rótulo default, todo o comando switch
é saltado e o único resultado terá sido a avaliação da <expressão>.
Trecho de programa
exemplificando um comando switch em C:
switch (a+b) {
case 1: printf("1\n");
case 2: printf("2\n");
default: printf("outro\n");
}
Se o resultado de a+b for 1 serão impressas as três cadeias de caracteres: 1,
2, outro. Se quisermos que cada seqüência de
comandos de cada rótulo seja excutada de forma mutuamente exclusiva temos que
usar o comando break. O comando break faz o fluxo de controle se
dirigir para o comando seguinte ao switch. Veja o trecho de programa C
abaixo:
switch (a+b) {
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("outro\n");
}
O comando enquanto é um dos denominados comandos iterativos ou comandos
de repetição ou ainda simplesmente um laço.
Os comandos iterativos prendem o fluxo de controle e permitem repetir a
execução de comandos. Um comando enquanto tem associado a ele uma expressão
e um comando ou seqüência de comandos. Quando o fluxo de controle atinge o enquanto
a expressão é avaliada e caso ela seja (diferente de zero)verdadeira o fluxo de
controle será transferido para o comando ou seqüência de comandos
associados ao enquanto. Ao terminar a execução do comando ou seqüência
de comandos o fluxo de controle retorna para o inicio do comando enquanto,
repetindo a avaliação da expressão e desviando o fluxo de controle para a
execução do comando ou seqüência de comandos caso a expressão seja verdadeira.
Esta repetição continua de forma indeterminada até que a avaliação da expressão
dê resultado falso. Somente quando o resultado da expressão é falso é que o
fluxo de controle deixa o comando enquanto e se dirige para o comando
seguinte (seqüência).
A forma geral do enquanto
(while) na linguagem C é :
while(<expressão>)
<comando>;
Temos que usar bloco - {} - para associar uma seqüência de comandos ao comando while.
Uma forma alternativa do comando enquanto é denominada faça-enquanto (do-while):
do
<comando> while(<expressão>);
No comando faça-enquanto o comando é executado pelo menos uma vez, no caso do
comando enquanto se a expressão for falsa o comando não é executado nem uma
vez.
Um comando para tem associado a ele três expressões e um comando. O
comando para é mais um dos comandos iterativos ou comandos de repetiçao.
Considere a seguinte forma geral do comando para (for) na
linguagem C:
for(<expressao1>
; <expressao2> ; <expressao3>) <comando>;
Podemos explicar a semântica deste comando utilizando o comando while. O
comando acima tem o mesmo efeito do trecho de programa abaixo:
<expressao1>;
while (<expressao2>)
{
<comando>;
<expressao3>;
}
A <expressao1> também
é referida como iniciação; A <expressao2> será avaliada e se for 0 é falsa e se for diferente de 0 é verdadeira.
A <expressao3> também é referida como atualização. Existem outras opções
sintáticas para o comando for.
Exemplos:
for(i=0;
i<20; i++) printf(“*”); //o código de iniciação tem uma atribuição e o código de atualização
tem uma atribuição(incremento)
for(i=0,
j=1; i!=j; ){ ... }; // o código de iniciação tem duas atribuições e o código de atualização
esta ausente.
Um programa pode ficar com
o fluxo de controle preso em um comando de iteração, o comando
while(TRUE);
Equivale ao comando
for(;;);
e corresponde a prender o fluxo de controle sem previsão explícita de saída do
controle. Observe que os itens 1 2 e 3 do comando for são opcionais, e a
ausência do <expressao2> faz o compilador interpretar o comando como
sendo
for(;TRUE;);
O
entendimento de um trecho de programa contendo comandos de iteração (fluxo de
execução laçado!) não é uma tarefa simples. O âmago de várias linguagens de
programação é substituir a iteração por outros tipos de construções. Existem
várias maneiras de enxergar uma iteração sendo que algumas são aplicáveis em alguns
casos e outras não. O chamado “desdobramento de um laço” muitas vezes ajuda no
entendimento inicial na leitura de programas. Não vamos mostrar um tratamento
sistemático deste assunto e ao invés disso vamos mostrar alguns exemplos
simples.
Considere o
seguinte trecho de programa:
for(i=0; i<3; i++) printf(“%d\n”, i);
este trecho
pode ser “substituido” por este trecho:
printf(“%d\n”,0);
printf(“%d\n”,1);
printf(“%d\n”,2);
Agora
considere este outro trecho:
scanf(“%d”, N);
for(i=0; i<N; i++) printf(“%d\n”, i);
este trecho
pode ser substituído por estre trecho:
printf(“%d\n”, 0);
printf(“%d\n”, 1);
…
printf(“%d\n”,N-1);
Mas agora
foi necessário usar “o poder das reticências”. Em algumas especificações de
iteração torna-se ainda mais difícil o entendimento do significado, mas a
técnica do “desdobramento” é uma importante ferramenta mental para entendimento
dos laços. A execução repetida de comandos, além da iteração, pode ser feita,
também, utilizando a “Recursão”,
conforme será visto mais à frente na disciplina.
Escreva um
programa em C que lê um valor inteiro N e desenha um quadrado feito com
asteriscos de tamanho NxN
exemplo
para N=2
**
**
Escreva um
programa em C que lê um valor inteiro N e desenha um triângulo feito com
asteriscos de altura N.