FIXME Rever o texto, e se necessário corrigir alguns pormenores
Alguns comandos em C
O comando if
A sua forma geral é:
if (condição) declaração;
A expressão, na condição, será avaliada. Se ela for zero, ou tiver um valor booleano falso, a declaração não será executada. Caso contrário, a declaração será executada. Aqui apresentamos o exemplo de um uso do comando if
:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num>10)
printf ("\n\nO numero e maior que 10");
if (num==10)
{
printf ("\n\nVoce acertou!\n");
printf ("O numero e igual a 10.");
}
if (num<10)
printf ("\n\nO numero e menor que 10");
return(0);
}
O else
Podemos pensar no comando else
como sendo um complemento do comando if
. O comando if
completo tem a seguinte forma geral:
if (condição)
declaração_1;
else
declaração_2;
A expressão da condição será avaliada. Se ela for diferente de zero a declaração 1 será executada. Se for zero a declaração 2 será executada. É importante nunca esquecer que, quando usamos a estrutura if
-else
, estamos a garantir quem pelo menos uma das duas declarações será executada. Nunca serão executadas as duas ou nenhuma delas. Abaixo está um exemplo do uso do if
-else
que deve funcionar como o programa da secção anterior:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num==10)
{
printf ("\n\nVoce acertou!\n");
printf ("O numero e igual a 10.\n");
}
else
{
printf ("\n\nVoce errou!\n");
printf ("O numero e diferente de 10.\n");
}
return(0);
}
O if-else-if
A estrutura if
-else
-if
é apenas uma extensão da estrutura if
-else
. A sua forma geral pode ser escrita como sendo:
if (condição_1)
declaração_1;
else if (condição_2) declaração_2;
else if (condição_3) declaração_3;
else if (condição_n) declaração_n;
else declaração_default;
A estrutura acima funciona da seguinte maneira: o programa começa a testar as condições começando pela 1 e continua a testar até que ele ache uma expressão cujo resultado dê diferente de zero. Neste caso ele executa a declaração correspondente. Só uma declaração será executada, ou seja, só será executada a declaração equivalente à primeira condição que der diferente de zero. A última declaração (default) é a que será executada no caso de todas as condições darem zero e é opcional. Um exemplo da estrutura acima:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num>10)
printf ("\n\nO numero e maior que 10");
else if (num==10)
{
printf ("\n\nVoce acertou!\n");
printf ("O numero e igual a 10.");
}
else if (num<10)
printf ("\n\nO numero e menor que 10");
return(0);
}
Quando o compilador avalia uma condição, ele quer um valor de retorno para poder tomar a decisão. Mas esta expressão não necessita ser uma expressão no sentido convencional. Uma variável sozinha pode ser uma "expressão" e esta retorna o seu próprio valor. Isto quer dizer que teremos as seguintes expressões:
int num;
if (num!=0) ....
if (num==0) ....
é equivalente a:
int num;
if (num) ....
if (!num) ....
Isto quer dizer que podemos simplificar algumas expressões de modo a ficarem mais simples.
ifs aninhados
Um if
aninhado é simplesmente um if
dentro da declaração dum outro if
externo. O único cuidado que devemos ter é o de saber exactamente a qual if
um determinado else
está ligado. Vejamos um exemplo:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num==10)
{
printf ("\n\nVoce acertou!\n");
printf ("O numero e igual a 10.\n");
}
else
{
if (num>10)
{
printf ("O numero e maior que 10.");
}
else
{
printf ("O numero e menor que 10.");
}
}
return(0);
}
O Comando switch
O comando if
-else
e o comando switch
são os dois comandos de tomada de decisão. O comando switch
tem aplicações valiosas. Mais uma vez vale lembrar que devemos usar o comando certo no local certo. Isto assegura um código limpo e de fácil entendimento. O comando switch
é próprio para se testar uma variável em relação a diversos valores pré-estabelecidos. A sua forma geral é:
switch (variável)
{
case constante_1:
declaração_1;
break;
case constante_2:
declaração_2;
break;
.
.
.
case constante_n:
declaração_n;
break;
default:
declaração_default;
}
Podemos fazer uma analogia entre o switch
e a estrutura if
-else
-if
apresentada anteriormente. A diferença fundamental é que a estrutura switch
não aceita expressões. Aceita apenas constantes. O switch
testa a variável e executa a declaração cujo case corresponda ao valor atual da variável. A declaração default
é opcional e será executada apenas se a variável que está a ser testada não for igual a nenhuma das constantes. O comando break
, faz com que o switch
seja interrompido assim que uma das declarações seja executada. Mas ele não é essencial ao comando switch
. Se após a execução da declaração não houver um break
, o programa continuará a executar. Isto pode ser útil em algumas situações, mas é preciso cuidado. Veremos agora um exemplo do comando switch
:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
switch (num)
{
case 9:
printf ("\n\nO numero e igual a 9.\n");
break;
case 10:
printf ("\n\nO numero e igual a 10.\n");
break;
case 11:
printf ("\n\nO numero e igual a 11.\n");
break;
default:
printf ("\n\nO numero nao e nem 9 nem 10 nem 11.\n");
}
return(0);
}
O Comando for
for
é a primeira de uma série de três estruturas para se trabalhar com ciclos de repetição. As outras são while
e do
. As três compõem a segunda família de comandos de controlo de fluxo. Podemos pensar nesta família como sendo a das estruturas de repetição controlada. Como já foi dito, o ciclo for
é usado para repetir um comando, ou bloco de comandos, diversas vezes, de maneira que se possa ter um bom controle sobre o ciclo. A sua forma geral é:
for (inicialização;condição;incremento) declaração;
O melhor modo de se entender o ciclo for
é ver como ele funciona "por dentro". O ciclo for
é equivalente a se fazer o seguinte:
inicialização;
if (condição)
{declaração;
incremento;
"Volte para o comando if"
}
Podemos ver, então, que o for
executa a inicialização incondicionalmente e testa a condição. Se a condição for falsa ele não faz mais nada. Se a condição for verdadeira ele executa a declaração, faz o incremento e volta a testar a condição. Ele fica a repetir estas operações até que a condição seja falsa. Um ponto importante é que podemos omitir qualquer um dos elementos do for
, isto é, se não quisermos uma inicialização poderemos omiti-la. Abaixo vemos um programa que coloca os primeiros 100 números inteiros na tela:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int count;
for (count=1; count<=100; count++) printf ("%d ",count);
return(0);
}
Note que, no exemplo acima, há uma diferença em relação ao exemplo anterior. O incremento da variável count
é feito usando o operador de incremento que nós agora já conhecemos. Esta é a forma usual de se fazer o incremento (ou decremento) num ciclo for
.
O for
na linguagem C é bastante flexível. Temos acesso à inicialização, à condição e ao incremento. Qualquer uma destas partes do for
pode ser uma expressão qualquer do C, desde que seja válida. Isto nos permite fazer o que quisermos com o comando. As três formas do for
abaixo são válidas:
for ( count = 1; count < 100 ; count++) { ... }
for (count = 1; count < NUMERO_DE_ELEMENTOS ; count++) { ... }
for (count = 1; count < BusqueNumeroDeElementos() ; count+=2) { ... }
etc ...
Preste atenção ao último exemplo: o incremento está a ser feito de dois em dois. Além disto, no teste está a ser utilizada uma função (BusqueNumeroDeElementos()
) que retorna um valor que está a ser comparado com count
.
O Comando while
O comando while
tem a seguinte forma geral:
while (condição) declaração;
Assim como fizemos para o comando for
, vamos tentar mostrar como o while
funciona fazendo uma analogia. Então o while
seria equivalente a:
if (condição)
{
declaração;
"Volte para o comando if"
}
Podemos ver que a estrutura while
testa uma condição. Se esta for verdadeira a declaração é executada e faz-se o teste novamente, e assim por diante. Assim como no caso do for
, podemos fazer um ciclo infinito. Para tanto basta colocar uma expressão eternamente verdadeira na condição. Pode-se também omitir a declaração e fazer um ciclo sem conteúdo. Vamos ver um exemplo do uso do while
. O programa abaixo é executado enquanto i
for menor que 100
. Veja que ele seria implementado mais naturalmente com um for
.
#include <stdio.h>
int main ()
{
int i = 0;
while ( i < 100)
{
printf(" %d", i);
i++;
}
return(0);
}
O programa abaixo espera o usuário digitar a tecla q
e só depois finaliza:
#include <stdio.h>
int main ()
{
char Ch;
Ch='\0';
while (Ch!='q')
{
Ch = getch();
}
return(0);
}
O Comando do-while
A terceira estrutura de repetição que veremos é o do
-while
de forma geral:
do
{
declaração;
}
while (condição);
Mesmo que a declaração seja apenas um comando é uma boa prática deixar as chaves. O ponto-e-vírgula final é obrigatório. Vamos, como anteriormente, ver o funcionamento da estrutura do
-while
"por dentro":
if (condição) "Volta para a declaração"
Vemos pela análise do bloco acima que a estrutura do
-while
executa a declaração, testa a condição e, se esta for verdadeira, volta para a declaração. A grande novidade no comando do
-while
é que ele, ao contrário do for
e do while
, garante que a declaração será executada pelo menos uma vez. Um dos usos da extrutura do
-while
é em menus, nos quais você quer garantir que o valor digitado pelo utilizador seja válido, conforme apresentado abaixo:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int i;
do
{
printf ("\n\nEscolha a fruta pelo numero:\n\n");
printf ("\t(1)...Mamao\n");
printf ("\t(2)...Abacaxi\n");
printf ("\t(3)...Laranja\n\n");
scanf("%d", &i);
} while ((i<1)||(i>3));
switch (i)
{
case 1:
printf ("\t\tVoce escolheu Mamao.\n");
break;
case 2:
printf ("\t\tVoce escolheu Abacaxi.\n");
break;
case 3:
printf ("\t\tVoce escolheu Laranja.\n");
break;
}
return(0);
}
O Comando break
Nós já vimos dois usos para o comando break
: interrompendo os comandos switch
e ciclos. Na verdade, estes são os dois usos do comando break
: ele pode quebrar a execução de um comando (como no caso do switch
) ou interromper a execução de qualquer ciclo (como no caso do for
, do while
ou do do
-while
). O break
faz com que a execução do programa continue na primeira linha seguinte ao ciclo ou bloco que está a ser interrompido. Observe que um break
causará uma saída somente do laço mais interno. Por exemplo:
for(t=0; t<100; ++t)
{
count=1;
for(;;)
{
printf("%d", count);
count++;
if(count==10) break;
}
}
O código acima imprimirá os números de 1 a 10 cem vezes na tela. Toda vez que o break
é encontrado, o controle é devolvido para o laço for externo. Outra observação é o fato que um break
usado dentro de uma declaração switch
afetará somente os dados relacionados com o switch
e não qualquer outro laço em que o switch
estiver.
O Comando continue
O comando continue
pode ser visto como sendo o oposto do break
. Ele só funciona dentro de um ciclo. Quando o comando continue
é encontrado, o ciclo salta para a próxima iteração, sem o abandono do ciclo, ao contrário do que acontecia no comando break
. O programa abaixo exemplifica o uso do continue
:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int opcao;
while (opcao != 5)
{
printf("\n\n Escolha uma opcao entre 1 e 5: ");
scanf("%d", &opcao);
if ((opcao > 5)||(opcao <1)) continue; /* Opcao invalida: volta ao inicio do loop */
switch (opcao)
{
case 1:
printf("\n --> Primeira opcao..");
break;
case 2:
printf("\n --> Segunda opcao..");
break;
case 3:
printf("\n --> Terceira opcao..");
break;
case 4:
printf("\n --> Quarta opcao..");
break;
case 5:
printf("\n --> Abandonando..");
break;
}
}
return(0);
}
O programa acima ilustra uma aplicação simples para o continue
. Ele recebe uma opção do utilizador. Se esta opção for inválida, o continue
faz com que o fluxo seja desviado de volta ao início do ciclo. Caso a opção escolhida seja válida, o programa segue normalmente.
O Comando goto
Vamos mencionar o goto
apenas para que você saiba que ele existe. O goto
é o último comando de controlo de fluxo. Ele pertence a uma classe à parte: a dos comandos de salto incondicional. O goto
realiza um salto para um local especificado. Este local é determinado por um rótulo. Um rótulo, na linguagem C, é uma marca no programa. Você dá o nome que quiser a esta marca. Podemos tentar escrever uma forma geral:
nome_do_rótulo:
...
goto nome_do_rótulo;
...
Devemos declarar o nome do rótulo na posição para a qual vamos dar o salto seguido de :
. O goto pode saltar para um rótulo que esteja mais à frente ou para trás no programa. Uma observação importante é que o rótulo e o goto
devem estar dentro da mesma função. Como exemplo do uso do goto
vamos reescrever o equivalente ao comando for
apresentado na seção equivalente ao mesmo:
inicialização;
início_do_loop:
if (condição)
{
declaração;
incremento;
goto início_do_loop;
}
O comando goto
deve ser utilizado com parcimónia, pois o abuso no seu uso tende a tornar o código confuso. O goto
não é um comando necessário, podendo sempre ser substituído por outras estruturas de controlo. Recomendamos que o goto
nunca seja usado. Existem algumas situações muito específicas onde o comando goto
pode tornar um código mais fácil de se entender se ele for bem empregado. Um caso em que ele pode ser útil é quando temos vários ciclos e if
s aninhados e se queira, por algum motivo, sair destes ciclos e if
s todos de uma vez. Neste caso um goto
resolve o problema mais elegantemente que vários break
s, sem contar que os break
s exigiriam muito mais testes. Ou seja, neste caso o goto
é mais elegante e mais rápido. O exemplo anterior pode ser reescrito usando-se o goto
:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
int opcao;
while (opcao != 5)
{
REFAZ: printf("\n\n Escolha uma opcao entre 1 e 5: ");
scanf("%d", &opcao);
if ((opcao > 5)||(opcao <1)) goto REFAZ; /* Opcao invalida: volta ao rotulo REFAZ */
switch (opcao)
{
case 1:
printf("\n --> Primeira opcao..");
break;
case 2:
printf("\n --> Segunda opcao..");
break;
case 3:
printf("\n --> Terceira opcao..");
break;
case 4:
printf("\n --> Quarta opção..");
break;
case 5:
printf("\n --> Abandonando..");
break;
}
}
return(0);
}
fgets
A função fgets()
lê uma string do teclado. A sua forma geral é:
fgets (nome_da_string, tamanho, stdin);
O programa abaixo demonstra o funcionamento da função fgets()
:
#include <stdio.h>
int main ()
{
char string[100];
printf ("Digite o seu nome: ");
fgets(string, 100, stdin);
printf ("\n\n Ola %s",string);
return(0);
}
Repare que é válido passar para a função printf()
o nome da string. Verá mais adiante por que é que isto é válido. Como o primeiro argumento da função printf()
é uma string, também é válido fazer:
printf (string);
Isto simplesmente imprimirá a string.
strcpy
A sua forma geral é:
strcpy (string_destino,string_origem);
A função strcpy()
copia a string_origem
para a string_destino
. O seu funcionamento é semelhante ao da rotina apresentada na seção anterior. As funções apresentadas nestas seções estão no arquivo cabeçalho string.h
. A seguir apresentamos um exemplo de uso da função strcpy()
:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[100],str2[100],str3[100];
printf ("Entre com uma string: ");
fgets (str1, 100, stdin);
strcpy (str2,str1); /* Copia str1 em str2 */
strcpy (str3,"Voce digitou a string "); /* Copia "Voce digitou a string" em str3 */
printf ("\n\n%s%s",str3,str2);
return(0);
}
strcat
A função strcat()
tem a seguinte forma geral:
strcat (string_destino,string_origem);
A string de origem permanecerá inalterada e será anexada ao fim da string de destino. Um exemplo:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[100],str2[100];
printf ("Entre com uma string: ");
fgets (str1, 100, stdin);
strcpy (str2,"Voce digitou a string ");
strcat (str2,str1); /* str2 armazenara' Voce digitou a string + o conteudo de str1 */
printf ("\n\n%s",str2);
return(0);
}
strlen
A sua forma geral é:
strlen (string);
A função strlen()
retorna o comprimento da string fornecida. O terminador nulo não é contado. Isto quer dizer que, de facto, o comprimento do vetor da string deve ser um a mais que o inteiro retornado por strlen()
. Um exemplo do seu uso:
#include <stdio.h>
#include <string.h>
int main ()
{
int size;
char str[100];
printf ("Entre com uma string: ");
fgets (str, 100, stdin);
size=strlen (str);
printf ("\n\nA string que voce digitou tem tamanho %d",size);
return(0);
}
strcmp
A sua forma geral é:
strcmp (string1,string2);
A função strcmp()
compara a string1
com a string2
. Se as duas forem idênticas, a função retorna zero. Se elas forem diferentes a função retorna não-zero. Um exemplo da sua utilização:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[100],str2[100];
printf ("Entre com uma string: ");
fgets (str1, 100, stdin);
printf ("\n\nEntre com outra string: ");
fgets (str2, 100, stdin);
if (strcmp(str1,str2))
printf ("\n\nAs duas strings são diferentes.");
else printf ("\n\nAs duas strings são iguais.");
return(0);
}
O return
O comando return
tem a seguinte forma geral:
return valor_de_retorno; ou return;
Digamos que uma função está a ser executada. Quando se chega a uma declaração return
, a função é encerrada imediatamente e, se o valor de retorno é informado, a função retorna este valor. É importante lembrar que o valor de retorno fornecido tem que ser compatível com o tipo de retorno declarado para a função. Uma função pode ter mais de uma declaração return
. Isto se torna claro quando pensamos que a função é terminada quando o programa chega à primeira declaração return
. Abaixo estão dois exemplos de uso do return
:
#include <stdio.h>
int Square (int a)
{
return (a*a);
}
int main ()
{
int num;
printf ("Entre com um numero: ");
scanf ("%d",&num);
num=Square(num);
printf ("\n\nO seu quadrado vale: %d\n",num);
return 0;
}
#include <stdio.h>
int EPar (int a)
{
if (a%2) /* Verifica se a e divisivel por dois */
return 0; /* Retorna 0 se nao for divisivel */
else
return 1; /* Retorna 1 se for divisivel */
}
int main ()
{
int num;
printf ("Entre com numero: ");
scanf ("%d",&num);
if (EPar(num))
printf ("\n\nO numero e par.\n");
else
printf ("\n\nO numero e impar.\n");
return 0;
}
É importante notar que, como as funções retornam valores, podemos aproveitá-los para fazer atribuições, ou mesmo para que estes valores participem de expressões. Mas não podemos fazer:
func(a,b)=x; /* Errado! */
No segundo exemplo vemos o uso de mais do que um return
numa função. Facto importante: se uma função retorna um valor, não precisa aproveitar este valor. Se não fizer nada com o valor de retorno de uma função, ele será descartado. Por exemplo, a função printf()
retorna um inteiro que nós por vezes não usamos. Ele é descartado.