Bases de Programação em C – Parte III

Noções básicas para começar a programar:

Vamos então à sintaxe propriamente dita:

Todas as instruções são seguidas de ‘;’, excepto casos que serão referidos mais à frente.

Muitas vezes é útil escrever no compilador o que se está a fazer, para que mais tarde se perceba o que se fez. Para o fazer tem que se usar comentários, nos quais o programador escreve informações, as quais apenas poderão ser visualizadas pelo mesmo, no source code e nunca no programa. Estes comentários podem ser feitos em qualquer lado, e fazem-se do seguinte modo:

//comentário

Ou

/*comentário*/

Em que no primeiro comentário, o compilador reconhece o comentário até ao fim da linha, enquanto que no segundo, reconhece como comentário tudo o que estiver entre ‘/*’ e ‘*/’, podendo o utilizador usar várias linhas se assim o pretender. Como se pode depreender, é preferível usar a segunda sintaxe, pois a possibilidade de errar será supostamente menor. (Tenham em atenção as cores, estão lá para facilitar a visualização de potenciais erros, quer nesta, quer noutras instruções que seguidamente apresentarei.

Além de os comentários serem de elevado proveito para a compreensão futura do programa, também permitem ao utilizador “comentar” certas partes do programa, para depois o compilador não correr essas mesmas partes. Este procedimento é normalmente usado para encontrar erros no código.

A partir daqui opto por introduzir exemplos de programas simples, explicando-os devidamente.

A base da programação são métodos numéricos, lógica e álgebra, como tal os dados de entrada são geralmente números, bem como os de saída. Associados a estes podem estar caracteres. O que poderemos então fazer com isto?

Começando por algo muito simples (e totalmente inútil):

[Para poupar espaço, vou omitir a parte do “código inicial”, dando-vos a garantia que todo o código que se segue deverá ser colocado após o “int main() {” e antes do “system (“PAUSE”);”]

Exemplo nº 1 – printf

printf("Que porcaria de tutorial!\n");

Como podem confirmar, ao colocar este código no compilador, e ao correrem, aparecer-vos-á a mensagem que está entre parentesis, sem o ‘\n’. Sugiro que experimentem a retirá-lo. O que sucede é que o compilador não muda de linha, ou seja, estes chamados caracteres especiais servem para mudar de linha. Existem mais, como é o caso:

  • ‘ \b ‘ – retrocesso
  • ‘ \r ‘ – enter
  • ‘ \t ‘ – tabulação horizontal
  • ‘ \v ‘ – tabulação vertical
  • ‘ \? ‘ – ponto de interrogação
  • ‘ \’ ‘ – plica
  • ‘ \” ‘ – aspas
  • ‘ %%’ – caracter de percentagem
  • ‘ \a ‘ ou ‘ \7 ‘ – bell
  • ‘ \\’ – barra

Como podem reparar, para colocar certos caracteres é preciso ter um cuidado especial, isto deve-se ao facto de estes estarem associados a certas instruções, como é o caso de ‘%’, que como será visto mais à frente, tem uma função especial. (É possível que alguns não funcionem em certos compiladores, nomeadamente no que eu propus que sacassem.)

Se não perceberam para que servia algum, o melhor será experimentarem e verem.

Concluindo este exemplo, temos que a instrução ‘printf’ serve para colocar mensagens para o utilizador que usa o programa. Normalmente é usado para pedir input ao utilizador e para guiar este na utilização do programa, como compreenderão com os seguintes exemplos. O modo de o usar é escrever: ‘printf(“ mensagem a mostrar no ecrãn “);‘, não esquecendo o ponto e virgula no final da instrução. Quero ainda referir, que o uso de acentos, ou outros caracteres, não é recomendado, uma vez que o compilador não os “decifra” bem, como podem experimentar.

Recomendo ainda que de todos os caracteres especiais apresentados em cima, tenham particular interesse no que usei no exemplo 1, visto que para um mais fácil leitura do programa será importante que se usem oportunas mudanças de linha.

Exemplo nº 2 – scanf

int a;
printf("Coloca um valor inteiro para a variavel \'a\'. \n");
scanf("%d", &a);
printf("O valor que colocou em \'a\' foi %d.\n",a);

Comecem por experimentar a usar o programa. Primeiro este pede que se coloque um valor inteiro para a variável. Depois de colocado o número, deve-se carregar no ‘enter’ para que o programa receba o número. De seguida este apresenta-nos o número colocado.

Passando para o código, temos a instrução ‘int a;’ que serve para indicarmos ao compilador que existe uma variável ‘a’. Este procedimento é fundamental: no princípio do nosso código devemos sempre (salvo excepções que agora não interessam) apresentar as variáveis. Primeiro temos que dizer de que tipo é essa variável. Neste caso era um inteiro, daí usar o ‘int’. Depois faz-se espaço e coloca-se um nome para a nossa variável. Este nome não pode começar por algarismos, nem conter certos caracteres, que creio não valer a pena referir quais são especificamente, deixo apenas o apelo para que usem letras (mas não o ‘ç’), números e o ‘ _ ’ que dá sempre jeito para dividir palavras, caso seja necessário (notar que não se pode usar o espaço). Acrescento ainda que tenham cuidado com o nome que dão, pois existem nomes que estão associados a certas instruções e que portanto não devem ser usados.

Além do ‘int’ para inteiros, tem-se outro tipo de variáveis:

‘char’ – para caracteres

‘double’ – para números reais

‘float’ – para números reais, mas com uma escala menor que o double (gasta menos bits, mas está mais limitado)

Seguidamente tem-se um ‘printf’ que como explicara anteriormente serve, neste caso, para pedir ao utilizador para ele colocar o número. Podem achar isto um pouco estúpido, na medida em que quem usa o programa poderão ser vocês e portanto sabem o que colocaram no código e portanto não precisam de instruções, mas a verdade é que os programas aumentam de tamanho e estas instruções são cruciais.

Apresenta-se então uma instrução nova: ‘scanf’, serve para o utilizador colocar a partir do teclado um número/ caracter para a variável que está dentro deste ‘scanf’. Passo então a explicar esta sintaxe: depois de escrever ‘scanf’ abre-se parêntesis e coloca-se de imediato entre aspas a simbologia de programação associada à variável. Ou seja, sendo neste caso um inteiro (‘int’), é “%d”, se fosse um caracter (char) seria “%c”, se fosse double teríamos “%lf” e um float seria “%g”. Faz-se virgula, para de seguida colocar ‘&’ seguido do nome da variável, concluindo com o fechar de parêntesis e o inevitável ponto e virgula. (O ‘&’ nem sempre é necessário, pois por vezes trabalha-se com ponteiros, os quais são muito úteis quando se criam funções, no entanto eles não serão tratados neste tutorial, quem quiser saber o que são e para que servem, perguntem depois, ou pesquisem nos link’s que indico no final do tutorial.)

Por fim, mais um ‘printf’, tendo este a particularidade de ser capaz de apresentar o valor de variáveis. Para se fazer isto basta usar a tal simbologia que indica o tipo de variável, sendo que o compilador ao correr o programa, vai colocar no sítio onde metemos o (neste caso) ‘%d’ o valor da variável que esteja após a mensagem, mas dentro do ‘printf’. Para separar a mensagem da variável, tem que se usar uma vírgula. Caso se pretenda ter várias variáveis, basta coloca-las todas pela ordem que se desejar a serem apresentadas na mensagem. Por exemplo:

int a=1;
double b=1.2;
char c='L';
float d=1.2;
printf("A:%d.\nB:%lf.\nC:%c.\nD:%g.\n",a,b,c,d);

Tenham em atenção no facto de que para apresentar números decimais se usa o ponto e não a virgula, bem como no facto de que enquanto num número, este poderá ter quantos algarismos se desejar, que será sempre apenas um número, já no caso de caracteres o mesmo não acontece. Um conjunto de caracteres será uma string, as quais serão abordadas mais à frente. Ter ainda em atenção no modo em como eu aqui fiz a declaração das variáveis, usando apenas o identificador igual (=), tendo especial atenção em que no caso de caracteres não se pode esquecer de colocar estas entre pelicas. Este tipo de declaração é muito usual e dá jeito quando não se pretende que o utilizador dê o valor para a variável, mas sim que esta tenha um valor independente do procedimento que se der ao programa, tendo o cuidado de não repetir nomes de variáveis, nem de usar variáveis já definidas, em ‘scanf’, embora tal procedimento não seja errado.

Notar que fazer ‘int a=1;’ ou ‘ int a;’ <mudar de linha> ‘a=1;’ é exactamente a mesma coisa, podendo talvez por vezes ser preferível usar a segunda possibilidade na medida em que o ‘a=1;’ poderá ser colocado em qualquer parte do programa, o que poderá em certos casos ser uma mais valia. (Nota: o ‘<mudar de linha>’ não é obrigatório, mas muito aconselhável, na medida em que se se colocar o código todo seguido, a sua «leitura» será grandemente dificultada.)

Exemplo nº 3 – Operações I

int a;
double b,c;
printf("Introduza um valor para \'a\'.\n");
scanf("%d",&a);
printf("Introduza um valor para \'b\'.\n");
scanf("%lf",&b);
printf("O valor da soma de \'a\' com \'b\' e' %lf.\n",a+b);
c=a+b;
printf("O valor de \'c\' e' %lf.\n",c);

Como podem testar, este programa pede dois números ao utilizador e depois soma-os, mostrando também que o que tem na variável ‘c’ é o resultado dessa soma.

Peço primeiro atenção para a inicialização das variáveis, em que digo que ‘b’ e ‘c’ são do tipo double, sem que para isso tenha que escrever duas vezes double, ou seja, pode-se agrupar todas as variáveis que se tenham do mesmo tipo, separadas por virgulas. O outro procedimento ( ‘double b;’ <mudar de linha> ‘double c’) é igualmente correcto, mas convém sempre economizar espaço, tempo e trabalho.

Como depois podem constatar, é possível colocar uma operação dentro do próprio ‘printf’, embora eu não recomende tal procedimento.

Realço ainda outra questão: sendo b do tipo ‘double’, mas a do tipo ‘int’, convém que o resultado da soma venha em ‘double’, como penso ser evidente, embora seja um erro algo frequente, que não se tenha o cuidado de verificar se a variável resultado está em consonância com o tipo de variáveis das quais depende.

Além da operação soma (e atribuição =), temos também:

  • – -> Subtracção
  • * -> Multiplicação
  • / -> Divisão (inteira)
  • % -> Resto da divisão
  • ++ -> Incremento
  • — -> Decremento

As últimas duas é possível que não percebam para que sirvam, mas são a mesma coisa que ter:

X=X+1;
X++;

De modo similar para o decremento.

Como já podem ter reparado, eu fiz sempre a atribuição de uma variável do lado esquerdo, para algo que está do lado direito, ou seja, é correcto fazer: a=2+3;, mas incorrecto fazer 2+3=a;.

Quanto ao que fiz em cima, é muito usual fazê-lo em ciclos, como poderão ver mais à frente, refiro-me ao incremento, em que se soma uma unidade à variável x.

Referi-me à divisão, como sendo divisão inteira, isto porque se fizerem:

A=3/2;

O resultado não será 1.5, mas 1, ou seja, é a parte inteira do resultado. Caso se pretenda o número real, ter-se-á que fazer A=(double) 3/2;. Notar que o % usa-se do seguinte modo:

D=3%2;

O resultado de D será 1, isto porque se fizermos a divisão de 3 por 2, o resto inteiro será 1.

Como na matemática, também aqui existe a precedência de operadores:

Parêntesis sobrepõe-se a tudo, segue-se a multiplicação, divisão e resto da divisão, acabando na soma e subtracção, ou seja, é exactamente como a matemática, a diferença surge nos operadores incremento e decremento.

Vejamos o próximo exemplo:

Exemplo nº 4 – Operações II

int a,b;
double c,d;
a=2;
b=6;
c=1.5;
d=--a*b/c+a*c+++a--;
printf("%lf\n %lf \n %d \n",d,c,a);

Se correrem, verão que ‘d’ será igual a 6.5, ‘c’ igual a 2.5 e ‘a’ igual a 0.

Ora isto parece não fazer sentido, pois se logo no principio é subtraído a ‘a’ uma unidade, este ao multiplicar por c deveria ser neutro, mas tal não acontece, embora ao operar sobre a divisão de b por c, já toma o valor de 1. Ou seja, o que se passa é, começando pelo fim, a- – só é feito após o ciclo, pois caso se o retirarmos, podem ver que o valor de d passa para 5.5, ou seja, o ‘a’ valia 1 e não zero, ou seja, o decremento é só feito depois da soma com tudo o resto. Antes disso, sabemos pelo valor que toma o ‘c’ e ‘d’, que ‘a’ já era 1, ou seja, o decremento “- -a” já tinha sido feito, assim podemos concluir de tudo isto que o decremento/ incremento feitos atrás da variável (– a) têm precedência em relação à multiplicação, enquanto que o decremento/ incremento feitos a seguir à variável são os últimos a serem feitos, mesmo após a adição/ subtracção.

Assim, a instrução “d=–a*b/c+a*c+++a–;” poderia ser escrita na seguinte forma:

a=a-1;
d=a*b/c+a*c+a;
c=c+1;
a=a-1;

Quem não percebeu, que tente exemplos no compilador, que rapidamente irá compreender.

Para outras operações que se desejem, como a raiz, expoente, logaritmo, etc, deverá ser incluída uma biblioteca que contenha essas funções (por exemplo #include <math.h>, quem estiver interessado nisso que procure nos link’s que estão no final do tutorial).

Exemplo nº 5 – Instruções Condicionais (if … else)

int a,b;
char i;
printf("Quer somar ou subtrair dois numeros?\n");
printf("Se quer somar, clique 1 e \'enter\'.\n");
printf("Se quer subtrair, clique outra tecla que nao 1 e \'enter\'.\n");
scanf("%c",&i);
if (i=='1')
{
printf("Coloque dois numeros inteiros.\n");
scanf("%d", &a);
scanf("%d", &b);
printf("A soma de %d com %d e' %d.\n",a,b,a+b);
}
else
{
printf("Coloque dois numeros inteiros.\n");
scanf("%d", &a);
scanf("%d", &b);
printf("A subtraccao de %d com %d e' %d.\n",a,b,a-b);
}

O que podem fazer com este programa? Somar ou subtrair dois números, podendo escolher o que fazer. Ou seja, existe uma condição. Se o utilizador colocar 1, o programa irá seguir um certo rumo, se colocar outra coisa, irá seguir outro rumo. Para isto se tem lá o ‘if’, que como sabem significa “se”, ou seja, se o utilizador colocar ‘1’ na variável i, irá seguir o rumo que está entre { }, se não fará o ‘else’ que significa “senão”, ou seja, se ‘i’ não é ‘1’, então irá fazer o que se segue entre {}.

Por outras palavras, a sintaxe da condição é muito simples e intuitiva:

if (condição) /*condição tem que estar entre parêntesis*/
{ instruções }
else {
instruções}

Notar que o ‘else’ pode ser omitido, quando se pretenda que o programa não faça nada, caso a condição não se verifique.

Quanto à condição, temos ‘==’ ou seja, significa que o que está de um lado é igual ao que está ao de outro, portanto nada tem a ver com a atribuição ‘=’, pois nesse caso estar-se-ia não a verificar uma condição, mas a criá-la, sendo sempre certa, portanto não esquecer que numa condição de igualdade não se usa ‘=’, mas sim ‘==’.

Podemos ter outras condições, como:

  • > maior
  • < menor
  • >= maior ou igual
  • <= menor ou igual
  • != diferente

Além do if, temos também o switch, que serve para selecção múltipla, ou seja, para quando se quer colocar vários casos, e o uso do if se torna um pouco trabalhoso e espaçoso no programa.

Vejamos então o próximo exemplo.

Exemplo 6 – Instruções Condicionais (switch)

int a,b,c,i;
a=1;
b=2;
c=3;
printf("Se deseja somar 1 com 1, clique 1.\n");
printf("Se deseja subtair 3 com 2, clique 2.\n");
printf("Se deseja multiplicar 1 com 3, clique 3.\n");
scanf("%d",&i);
switch (i)
{
 case 1:
 c=a+a;
 printf("1+1=%d\n",c);
 break;
 case 2:
 a=c-b;
 printf("3-2=%d\n",a);
 break;
 case 3:
 b=a*c;
 printf("1*3=%d\n",b);
 break;
 default:
 printf("Ups, nao existe essa opcao.\n");
 break;
}

Como podem constatar, se fossem meter um if para cada caso, dava-vos mais trabalho, além de piorarem a leitura do programa.

O modo de usar o switch também é intuitivo:

switch (variável a verificar) {
case /*caso*/ valor_que_a_variável_pode_tomar 
/*notar que se fosse um caracter necessitaria das pelicas*/
instruções /*aqui não é necessário o uso dos parêntesis { } */
break; /*serve para terminar o caso*/
(um todo outro conjunto de case’s, e caso se queira: )
default: 
/*para todos os outros casos não incluídos nos anteriores, 
ou seja, como se fosse um ‘else’*/
instruções
break;
} /*fim do switch*/

O ‘if’ é muito importante também para uma outra coisa: e se o utilizador se engana a colocar, no exemplo anterior um número, ou seja, por exemplo, em vez de um número coloca um caracter.

Ora, com o if poder-se-á verificar se o utilizador se enganou e mandá-lo recolocar o número, caso tal tenha acontecido, no entanto, como podem pensar, este tipo de procedimento não faria sentido, pois o utilizador poderia continuar a enganar-se e nós que fazemos o código, não saberíamos quantos if, precisaríamos, para isso serão de grande utilidade as condições repetitivas, ou seja, ciclos, que serão vistos de seguida.

Exemplo nº 7 – Ciclos (while I)

int i,a;
a=1;
while(a){
    printf("Coloque o numero 1.\n");
    fflush(stdin);
    scanf("%d",&i);
    if (i==1)
        a=0;
}

Antes de mais, importa dizer que em programação, 1 significa verdadeiro e 0 falso.

Como sabem, ‘while’ significa “enquanto”, portanto, enquanto uma certa condição for verdadeira, o ciclo que se segue será processado, ou não, se a condição deixar de ser verificada. Como podem depreender pelo o que disse inicialmente e pelo código que apresento, while (verdadeiro) faz correr as instruções que o ciclo tem dentro dos parêntesis { }. Dentro do while o que tenho é um printf que não levanta dúvidas, seguido de um fflush(stdin);. Não vou perder muito tempo a explicar o que isto é, digo-vos apenas que deve ser usado quando se dá a uma certa variável valores segundo ciclos, ou seja, serve para limpar a memoria, pois se experimentarem a neste caso a retirarem isto e a correrem o código, se na primeira vez se não colocarem o 1, então não terão oportunidade de voltar a tentar, pois começará a aparecer sem parar a mensagem do printf, ou seja, o scanf é feito automaticamente com a memoria do que foi colocado automaticamente, assim, se a memoria for limpa em cada ciclo, o programa chega ao scanf e volta a precisar que o utilizador dê um novo valor para a variável i.

Seguidamente tenho um if, em que vai ver se o que foi colocado foi mesmo o 1 que se pretendia, se foi, então será processada a instrução: ‘a’ passará a ser igual a 0. Então, ao voltar ao while, a condição deixará de ser verdadeira, para ser falsa, logo o que está dentro do while não será corrido, e portanto o programa acabará, visto que não tem nada mais além do while.

Com este “artifício” (ou com algo similar), poderão verificar sempre se o que foi colocado pelo utilizador está correcto. Se não perceberam, não se preocupem, que utilizarei esse procedimento em exemplos posteriores.

Algo também muito usual, é querer fazer um ciclo que repita um dado número de vezes. Como poderão ver no seguinte exemplo:

Exemplo nº 8 – Ciclos (while II)

int a,contador,c;
contador=0;
a=2;
printf("Vejam a tabuada do 2:\n");
while(contador<10)
{
  contador++;
  c=a*contador;
  printf("%d\n",c);
}

Como podem ver, o ciclo irá ser executado até que o contador tenha adquirido o número 10.

Um outro modo de fazer exactamente a mesma coisa e que encurta espaço é usar um ciclo for.

No próximo exemplo mostro um programa um pouco mais complexo e que engloba algumas das coisas que já referi que estes ciclos permitem fazer, além de um outro tipo de ciclo parecido com o while, que é o do… while.

Exemplo nº 9 – Ciclos (do … while)

int a, contador, b;
do{
printf("Introduza o numero positivo e menor que 100");
printf(" para o qual pretende ver a tabuada.\n");
fflush(stdin);
scanf("%d",&a);
} while (a<=0 || a>=100);
printf("Tabuada do %d:\n",a);
for(contador=1; contador<11; contador++)
{
 b=contador*a;
 printf("%d\n",b);
}

Suponho que estejam a pensar: finalmente algo pode ser minimamente útil, a verdade é que com os conhecimentos que já têm, poderão já efectuar programas bem úteis, principalmente para quem trabalha com somatórios, os quais não passam de um ciclo como estes que tenham apresentado.

Mas voltando ao código, como podem comprovar, este programa começa por pedir um número entre 1 e 99, sendo que se não o colocarem, ele voltará a pedir até que lhe façam a vontade.

Se experimentarem a retirar a condição do while, verificam que se colocarem uma letra, o programa pegará num número “esquisito” e fará a tabuada desse. Ora isto deve-se ao código ascii, no qual a cada caracter está associado um número. No fim de lerem este tutorial e de o testarem, sugiro (caso ainda tenham vontade) que pesquisem no google por esse código e depois tentem fazer programas com base nesse código de modo a poderem manipular como desejarem os caracteres.

Ora, temos então aqui algo novo: ‘do{ instruções} while( condição || condição);. Este tipo de ciclo é muito semelhante ao while, tendo a particularidade de que a condição é apenas testada no fim das instruções serem corridas e não o contrário, o que implica que a primeira vez será sempre corrida, independentemente das condições. Na parte da condição está lá algo que me esquecera de referir logo nos if’s: podemos ter mais que uma condição, separadas por || (duas barras verticais) que significa “ou”, ou então separadas por && que significa “e”. Podem então questionar: neste caso era suposto termos ‘uma condição’ <e> ‘outra’ e não uma <ou> outra, como lá está. No entanto, como podem verificar: o ciclo será repetido se a condição for verdadeira, e não repetido quando for falso, deste modo, o que se pretende é que o utilizador coloque algo que satisfaça a negação da condição. (Para quem não percebeu, recomendo vivamente que estude um pouco de lógica, ou que me peça para a explicar em mais detalhe.)

Seguidamente o programa faz o mesmo que o do exemplo 8, com a diferença que em vez de se usar o while, usa-se for (para), o qual tem uma sintaxe um pouco mais complicada e menos intuitiva.

Ora bem um for funciona do seguinte modo:

for (inicio; condição; incremento/ decremento que altera a variável de inicio)
{ instruções
}

Ou seja, um for é uma forma condensada de fazer o mesmo que se fazia com o while nas situações em que se usava um contador. Notar que no local da condição podemos, ter várias, bem como no inicio podemos ter varias variáveis de inicio, as quais são alteradas por mais expressões no local a seguir à condição.

Exemplo nº 10 – Ciclos (for)

int i,j,a,contador;
for(i=0, j=6,contador=1; i<10 && j>3; i++, j=j-i,contador=contador+1)
{
a=j*i;
printf("\'a\' toma o valor de %d no ciclo numero %d\n",a,contador);
}

Como podem ver, podem-se ter várias variáveis dentro da parte do inicio, bem como da do incremento/ decremento, separadas por virgulas.

Talvez seja importante interpretar este ciclo do ponto de vista do compilador, visto que ainda não o fiz e podem residir dúvidas sobre isso:

Primeiro ciclo:

Inicializado i=0, j=6 e contador=1.

São verificadas as condições:

i é menor que 10, visto que i é 0, j é maior que 3, visto que j é 6.

a=i*j, ou seja, a=0*6=0.

Segundo ciclo:

É executada a instrução de incremento/ decremento:

i++, ou seja, i=0+1=1

j=j-i, ou seja, j=6-1=5

contador=2 (notar que esta variável serve para que no printf se indique o numero do ciclo)

São verificas as condições:

i continua menor que 10 e j continua maior que 3

a=i*j, ou seja, a=1*5=5.

Terceiro ciclo:

i++, ou seja, i=1+1=2

j=j-i, ou seja, j=5-2=3

contador=3

As condições são apenas parcialmente verificadas, ou seja, embora o i continue inferior a 10, mas o j deixou de ser superior a 3. Deste modo, as instruções dentro do for não são executadas.

Falta ainda explicar melhor a instrução break, bem como a continue, para isso vejamos o próximo exemplo.

Exemplo nº 11 – Instruções break & continue

int c;
do
    {
     printf("Coloque um numero para ver o seu dobro.\n");
     printf("Coloque 0 para sair.\nSe colocar -1 para voltar a esta opcao\n");
     fflush(stdin);
     scanf("%d",&c);
     if (c==0)
        break;
     if (c==-1)
       continue;
     else
     {
      printf("O dobro de %d, e' %d\n",c,c*2);
     }
     }while(1);

Este exemplo serve apenas para introduzir o continue e consolidar o break. Como podem constatar ao usar o programa, ao carregarem -1, o programa volta atrás, ou seja, é executado o continue, o qual tem a função de passar à frente de tudo o que haja no ciclo, passando para a iteração (repetição) seguinte, no caso de um for, o continue iria fazer com que a condição de incremento/ decremento fosse executada e de seguida a condição de teste para que a iteração seja executada, ou não. O break, tal como no switch, produz uma saída imediata do ciclo, seja ele while, do… while, ou for.

Um à parte: proponho vivamente que quem está a ver programação pela primeira vez, e tem estado a seguir tudo até agora apenas copiando o código que tenho colocado, deva fazer uma pausa e começar a tentar fazer coisas que pensem, ou se não têm nenhuma ideia do que fazer, proponho que tentem fazer este exemplo simples: criar um programa que faça a média das vossas notas. Tentem complicar ao máximo, usando tudo o que já supostamente aprenderam, ou podiam ter aprendido, ou seja, façam um controlo dos dados de entrada do utilizador, sem saber quantas notas serão colocadas, mas usando um valor bandeira, como no exemplo 10. Se depois necessitarem, eu poderei colocar a solução do problema.

Se fizeram o que propus, talvez comecem a sentir falta de algo: vectores/ matrizes. Não é de modo algum viável criar cem variáveis, apenas porque se pretende manipular cem valores, portanto convém criar algo que as armazene, sem que sejam variáveis para cada valor.

Para quem nunca teve álgebra, é possível que desconheça o que é um vector, nesta situação, podendo estar a associar aos vectores da física, os quais estão relacionados, mas para agora, o melhor é considerarem que um vector neste contexto é um conjunto de números dispostos em linha, ou coluna. Uma matriz será uma tabela de números, com duas ou mais dimensões.

Não irei mostrar como usar matrizes, mas se pedirem, depois poderei dar um exemplo usando-as.

Exemplo nº 12 – Vectores

int i,recibos[5],soma=0;
for(i=0; i<5; i++)
{
 printf("Coloque o valor que recebeu\n");
 scanf("%d",&recibos[i]);
}
 printf("Tudo o que recebeu foi:\n");
 for(i=0;i<5;i++)
   {
   printf("%d\n",recibos[i]);
   soma=soma+recibos[i];
   }
 printf("Tudo somado da:%d\n",soma);

Temos então a inicialização de algo novo: recibos[5]. Será então um vector com memória para 5 inteiros. Do mesmo modo se podia criar um float ou double, (quanto a char, é outra “conversa”, tratar-se-á de uma string, das quais falarei no exemplo seguinte).

Como podem reparar, para usar um vector, normalmente tem que se usar um ciclo, pois só deste modo se poderá percorrer o vector de modo a preenchê-lo. Um dado importante é o facto de i começar em zero e acabar em 4, em vez de começar em 1 e acabar em 5, como se poderia esperar. Em C tem-se que o índice do vector começa em zero e acaba uma unidade antes do seu comprimento. Notar que o número que faz de índice tem que ser um inteiro, caso contrário, o programa dará erro. Outro dado importante é que o vector tem que ser definido logo no início, o que implica algo que pode ser constrangedor: temos que saber até onde poderá ir o utilizador, dando a este um limite. Podem experimentar a alterar a condição no for, para que o i vá “mais longe”. Apesar de não dar erro, e de o programa parecer correr na perfeição, com o vector a ser aumentado além do que previamente fora predefinido, tal procedimento é errado e noutros casos causará erros.

Exemplo nº 13 – String

char frase[100];
printf("Escreve ai alguma coisa, ate um maximo de 100 caracteres.\n");
gets(frase);
printf("O que escreveu foi:\n");
puts(frase);
printf("\nA frase escrita teve %d caracteres.\n",strlen(frase));

Como podem deduzir, o gets é como que um scanf, mas para um conjunto de caracteres, sem precisar de criar um ciclo, como se fez para os vectores, embora tal procedimento esteja correcto. No entanto, se fizerem tal coisa, tenham em atenção algo que distingue uma string, de um vector de caracteres: a string precisa de um último espaço para um caracter especial que indica o fim da string: ‘’. Deste modo a string indicada não terá espaço para 100 caracteres, mas sim para 99. Caso usem um ciclo, que por vezes dá jeito, não se esqueçam portanto de na última iteração colocarem o ‘’ na string, senão esta não será uma string, mas sim um vector de caracteres o que significará que não a poderão manipular como tal.

O puts, como podem deduzir também, é como que um printf específico para string’s.

No último printf aparece outra coisa nova: strlen. Uma função que serve para verificar qual o tamanho de uma string. Notar que esta função devolve sempre um número inteiro.

Para poder manipular string’s de um modo mais amplo, convém adicionar uma biblioteca: #include <string.h>. Caso tenham interesse nisto, procurem nos link’s que estão no final do tutorial esta biblioteca, para verificarem quais as suas potencialidades.

Acrescento ainda que uma string funciona como um ponteiro, daí, caso se não pretenda usar o ‘gets’, pode-se usar na mesma o scanf, da seguinte forma: scanf(“%s”, frase); notar que não leva o ‘&’, por se tratar de um ponteiro, por outro lado o tipo string usa %s para ser invocado, do mesmo modo que num printf se pode colocar o %s para mostrar o que contem a string.

Exemplo nº 14 – Funções

#include <stdio.h>
#include <stdlib.h>
double factorial(double x)
{
int i,n;
double y;
for (i=1; i<=x; i++)
     {
     y=i;
     for (n=1; n<i; n++)
         y=y*n;
    }
 return y;
}
int main()
{
       double a;
     printf("Coloque um numero para ver o seu factorial.\n");
     scanf("%lf",&a);
     printf("O factorial de %lf e' %lf.\n",a,factorial(a));
      system("PAUSE");
      return 0;
}

Antes de mais, espero que saibam o que é o factorial de um número (o factorial de um número natural é igual à multiplicação de todos os números naturais menores que ele a multiplicar ainda por ele próprio. O factorial representa-se por um ponto de exclamação. Exemplo: 4!=4x3x2x1=24) .

Como podem ver, uma função apresenta-se fora do int main, ou seja, fora da função principal, exactamente porque é uma função. Esta função pode ser chamada sempre que se deseje, sem que alguma vez seja alterada. Qual a estrutura de uma função?

<Tipo dado de saída> <nome da função> (<tipo dado de entrada> <x> )  
/*Poderá ser mais que um que dado, sendo que nesse caso estarão
 separados por vírgulas.
x - um nome qualquer que o dado de entrada tomará dentro da função*/
{ intruções, 
notar que as variáveis aqui são independentes do int main, 
e têm que ser inicializadas, tal como o são na função principal ;
return <variável que se pretenda que seja o output da função>;
}

Notar que a função não precisa de obrigatoriamente ter output. Nesse caso não poderemos definir o tipo de variável será o de saída, logo no princípio. Nesses casos usa-se void, ou seja, no sítio onde colocariam o tipo de variável de saída, colocam ‘void’.

Do mesmo modo uma função pode não ter dados de entrada, ficando por isso livre o espaço entre parêntesis após o nome da função, não podendo por isso omitir os parêntesis. Acrescento ainda que não é de modo algum incorrecto usar scanf, printf, etc, dentro de uma função. A única coisa que não pode ser esquecida, é que a função só será corrida através do int main, portanto não esquecer de aí a “chamar”, para ela ser executada.

Para “chamar” a função, basta usar o nome que lhe foi dada, colocando a seguir a este entre parêntesis os valores de entrada, caso os tenha, caso não os tenha, colocam-se apenas os parêntesis.

Bem, dou as explicações por concluídas, apesar de haver ainda muita coisa por falar, como o uso de estruturas – ‘struct’, a manipulação de ficheiros, nomeadamente de .txt, ponteiros, e todo um conjunto de particularidades que se poderiam acrescentar ao que disse, isto entre muitas outras coisas mais complexas e que poderão aprender apenas com a força da curiosidade e vontade de aprender mais. Receio que a dada altura do tutorial começaram a ver que as minhas explicações eram mais descuidadas, mas tal foi propositado, visto que se não entendem por poucas palavras, com algumas ideias implícitas que devem deduzir por vós, tal significa que o que está para trás não está totalmente assimilado, como tal devem voltar atrás e analisarem o que não perceberam, podendo recorrer a outros meios, além deste tutorial. O conselho é mesmo: experimentar e tentar inventar por vós. Programar não se aprende lendo, mas sim programando!

Alguns links úteis:

http://www.phim.unibe.ch/comp_doc/c_manual/C/FUNCTIONS/funcref.htm

http://www.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html

http://cclib.nsu.ru/projects/gnudocs/gnudocs/glibc/libc_514.html

Foi um prazer fazer este tutorial, (se não o fosse não o teria feito), portanto espero que gostem e que possa servir a alguém que se esteja a iniciar na programação. Sei que está um pouco longo, mas mais pequeno significaria ainda mais incompleto (como sei que este está, mas não poderia falar de tudo).

P.S.: Cortei vários printf’s em dois printf’s seguidos em vários exemplos, apenas para o código ficar dentro da “caixa” (já que não posso editar o CSS deste blog).

Marinho Lopes

Anúncios

3 thoughts on “Bases de Programação em C – Parte III

  1. Pingback: Índice de Artigos | Sophia of Nature

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s