Ir para o conteúdo

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 ifs aninhados e se queira, por algum motivo, sair destes ciclos e ifs todos de uma vez. Neste caso um goto resolve o problema mais elegantemente que vários breaks, sem contar que os breaks 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.