C

De Física Computacional
Revisão de 14h34min de 19 de setembro de 2011 por Tekkito (discussão | contribs) (Criou página com 'Esta é a pagina dedicada à linguagem de programação C. A estrutura da página segue de muito perto a estrutura da página anterior que explica a linguagem Fortran. Assim os ...')
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegação Ir para pesquisar

Esta é a pagina dedicada à linguagem de programação C. A estrutura da página segue de muito perto a estrutura da página anterior que explica a linguagem Fortran. Assim os que desejarem compará-las poderão fazê-lo com maior facilidade.


Olá Mundo

Já é um divertida tradição que o primeiro programa de um iniciante a uma linguagem de programação é um programa que ao ser acionado responde escrevendo a expressão "Hello World" ou em português "Olá Mundo". Você pode até achar na Wikipedia uma página com este programa escrito em mais de 30 linguagens conhecidas.

Para o C este código é

#include <stdio.h>
void main(void)
{
printf("Ola mundo! \n"); 
}

O código acima mostra pelo menos dois elementos essenciais da gramática de C. Primeiro a existência de instruções para incluir funções. Diferente de alguns compiladores, como o Fortran, o compilador C necessita de instruções explícitas dizendo quais funções estarão presentes no programa, mesmo que estas funções sejam as mais óbvias. No caso do código acima a diretiva de compilação "#include" indicou a inclusão de um grupo de funções de entrada e saída, contidas no arquivo "stdio.h". Se tal instrução não fosse passada ao compilador ele não reconheceria a função "printf", que permite ao programa escrever "Ola Mundo!".

Um segundo elemento da linguagem C é o programa principal. Todo o código C deve ter um programa principal indicado pela expressão "main" e contido entre chaves "{" "}". A ordem temporal das intruções realizadas pelo programa são lidas dentro deste programa principal. Vocês vão observar que um código em C pode ser até bem desordenado fora do programa principal, mas funcionará se estiver em ordem dentro dele. Assim para entendermos um programa em C o primeiro passo é olhar dentro do "main".

A função "printf" permite a impressão formatada da saída do programa. Veremos mais adiante todas as possibilidades desta função. Por hora observe que o formato é escrito entre aspas e que a instrução "\n" representa a mudança de linha. Ou seja, o programa escreve "Ola Mundo!" e o cursor muda de linha.

Editar

Estas linhas devem estar dentro de um arquivo (ex: ola.c), isto pode ser feito com cat linha por linha ou com um editor de texto (jed,emacs ou view)

Compilar

ola.c deve ser compilado, isto é traduzido da linguagem C (código fonte) para Assembler (código objeto ou de maquina) com a seguinte instrução:

> gcc ola.c -o ola

gcc invoca o compilador que faz a dita conversão

-o nome é uma opção para nomear o código objeto (o programa executável) que no exemplo terá o nome ola

sem essa opção o executável criado terá o nome a.out

Rodar

ola.c não é executável, o computador não sabe o que fazer com ele, para isso o compilador traduz para uma série de instruções que o computador sim sabe executar.

Para rodar fazemos:

> ./ola  

./ na frente é necessário para o interprete de comandos (shell) saber que o programa está no diretório de trabalho (veremos depois como configurar a sessão para não ter que digitar esses caracteres)

> Ola Mundo! 

será a saída na tela

Desta forma completamos o processo de ter criado nosso primeiro código C, compilado e executado o mesmo.

Tipos de Variáveis

Por diversas razões entre as quais o bom gerenciamento da memória, ou a correta interpretação de um caractere, a linguagem C exige que o tipo de cada variável seja definido no programa. Não existem "defaults", toda a variável deve ser definida caso contrário o compilador acusa erro. As mais comuns são


char   - Caracter. O valor armazenado é um caracter usualmente em código ASCII.
int    - Número inteiro.
float  - Numero de ponto flutuante de precisão simples.
double - Número de ponto flutuante de precisão dupla.
void   - Tipo indefinido, cuja utilidade veremos mais adiante.

Operadores matemáticos

. ponto decimal (vírgula *NÃO*)
+ - * /  soma subtração multiplicação e divisão (igual que uma calculadora)


Diferente do Fortran o C não tem um operador básico associado a potenciação. A potenciação é feita por uma função matemática.

Funções Matemáticas

Estas são as funções fazem parte da biblioteca de funções do compilador C, contidas em math.h. Ou seja o compilador C as reconhece se a instrução

#include <math.h>

estiver presente nas primeiras linhas no código.

A sintaxe de uso é o nome da função (geralmente três letras) e o argumento entre parêntesis:

sqrt(x)                - raiz quadrada: 
pow(x,y)               - x elevado na potencia y
sin(x), cos(x), tan(x) - funções trigonométricas 
exp(x)                 - exponencial
log(x)                 - logarítmo natural

Ciclos (loop)

O grande lance dos programas (e do computador claro) é poder repetir operações. Ou seja, utilizando a lógica para repetir tarefas que podem ter variações especificadas pelo programador dentro de um ciclo. Vejamos um exemplo usando a instrução for:

int i;
float x,y;
...
for(i=1;i<=100;i++)
   {
   x = i*0.1;   
   y = pow(x,2);
   printf("%f %f\n",x,y);
   }
...

a interpretação do for é a seguinte:

   * comece com i=1
   * faça o que esta entre chaves.
   * incremente i em 1 ( i++ ) e veja se ultrapassou o valor máximo de i (no exemplo 100)
   * se a resposta é não faça de novo  com o novo valor de i
   * o ciclo se repete até o valor máximo de i (= 100 no exemplo)
   * quando i ultrapassa esse valor o laço é interrompido e o programa prossegue

Observe que assim como no comando main todas as instruções dentro do comando if devem estar entre chaves. A presença das chaves só é facultativa se houver uma única instrução dentro do ciclo. As chaves são essenciais para organizar a estrutura de encadeamentos dentro de um código C. Quando o código é muito grande é usual que o programador use certas regras de identação ou alinhamento das chaves para melhor visualizá-lo ( Por exemplo, no exemplo acima a chave fecha diretamente abaixo de onde ela abriu). Editores tradicionais como o emacs ou o gvim ajudam o programador a verificar se o fechamento das chaves está correto.


Pergunta: Qual será no exemplo acima o valor da variável i finalizado o laço?

Notas em sintaxe - Maísculas, Abrevições e printf

Mauísculas

No C como no shell maiúsculas são diferentes de minúsculas. Por exemplo em C , não existe o commando "Printf" e sim "printf". Isto também vale para variáveis definidas dentro do programa, por exemplo a variável a é diferente da variável A.

Abreviações

O C é uma linguagem que possui muitas notações abreviadas para melhorar a dinâmica de escrita. Por exemplo "i++" é uma abreviação de "i = i+1" ou seja o incremento de 1 de uma variável. A notação para um incremento genérico é "x += a" onde "a" é um valor qualquer. Isto também serve para multiplicações e divisões, por exemplo. "x *= a" é equivalente a "x = x*a" e assim por diante.

printf - Impressão formatada

Neste exemplo vemos que para imprimir dois números do tipo float a expressão %f deve estar no argumento de printf. O que indica o comando acima é que os dois números de ponto flutuante serão impressos na mesma linha com um único espaço entre eles (já que tem um único espaço entre as duas expressões "%f". Para os demais formatos temos

%c  variável tipo char
%d  variável tipo int
%f  variável tipo float
%lf variável tipo double

Exemplo: MRUA

Neste exemplo criamos um programa que gera a trajetória x(t) (uma dimensão) de um objeto com aceleração constante:

x(t) = x(0) + v(0)*t + 0.5*a*t²
// Programa mrua  --- isto é um comentário, não é interpretado pelo compilador
#include <stdio.h>
#include <math.h>

void main(void)
{               
float x0, x, v0, a, t, dt;                   //  variáveis ponto flutuante
int   i,N;                                   //  variáveis inteiras   
printf("entre x0, v0, a, t, N\n");          
scanf("%f %f %f %d",&x0, &v0, &a, &t, &N);   // leitura dos dados
dt = t/N;                    // passo de tempo: definido pelo tempo máximo e o número de pontos da trajetória
t = 0;
for(i = 1; i<= N; i++)
   {
   x = x0 + v*t + 0.5*a*pow(t,2);
   printf("%f %f\n", t, x);                  // saída de dados
   t += dt;
   }
}

Nota: este programa tem um erro que você deve descobrir

Notas em sintaxe - Pointers ou apontadores

O C é uma linguagem que possibilita o usuário ter acesso não só ao valor de uma variável (ou seja o conteúdo da memória onde esta variável é armazenada) mas também ao endereço na memória onde esta armazenada a variável. A existência destes dois tipos de informação introduz certas regras de sintaxe em C que se não são seguidas causam muita dor de cabeça. Por exemplo, se você utilizar o valor de uma certa variável x como argumento de um comando (ou função) de forma que este o valor seja usado mas não moficado pelo comando (ou função) você escreve simplesmente

func(x);

Mas se no entanto func for modificar x você deverá forçosamente escrever

func(&x);

onde "&x" é o valor do apontador da variável "x"( endereço na memória onde está o valor de "x"). E é esta a razão pela qual os argumentos do comando de leitura formatada "scanf" são os apontadores e não as variáveis. Um comando de leitura sempre modifica valores de variáveis.

Funções e comandos são sensíveis aos tipos de variáveis em seus argumentos. Colocar a variável onde deveria estar seu apontador ( e vice versa ) causam erro no programa.

Isto no começo parece mais dificultar do que ajudar o programador. Mas veremos mais adiante que a existência de apontadores possibilita escrever programas muito mais eficientes sendo isto uma das grandes vantagens da linguagem C.

Controle de Fluxo (if)

Possibilitam a escolha de rumos diferentes no programa dependendo de valores de variáveis ou condições entre elas. Sintaxe:

if (condição)
    { instruções executadas quando condição verdadeira }
else
    { instruções executadas quando condição falsa }

Operadores relacionais e lógicos

==   igual
!=   diferente
>    maior
<    menor
>=   maior ou igual
<=   menor ou igual
&&   E lógico
||   OU lógico
!    NÃO lógico


Eles são usados junto com as instrucões de controle como o if (se), exemplo:

// exemplo de divisão a x b:
float a,b,c;
...
scanf("%f %f",&a, &b);

if (b != 0) 
    c = a/b;
else
    break;
printf(" a/b= %f/n",c);
...

Ciclos (Avançado)

Muitas vezes quando estamos lidando com um ciclo é conveniente poder interrompê-lo antes do número previsto de iterações. Isto pode acontecer porque algum erro é detectado ou porque o resultado desejado já foi obtido sendo desnecessário continuar no ciclo. O comando for em princípio aceita a introdução de uma série de condições de parada além do limite da variável contadora. Por exemplo

int i;
float x;
...
for( i=1; ( i < 100 && x > 3.1 );i++)
   {
   instrução1;
   instrução2;
   }
...

No exemplo acima se x assumir um valor menor que 3.1 o ciclo não é repetido novamente não importa o valor de i, isto porque a condição para a realização de um ciclo é que "i" seja menor que 100 e "x" seja maior que 3.1.

Quebra - Break

Outras vezes uma interrupção mais abrupta é necessária. Ou seja, talvez seja conveniente deixarmos um ciclo no meio dele, não realizando todas as instruções até o fim. Isto se pode fazer usando o comando break como é exemplificado abaixo

int i;
float x;
...
for( i=1; i < 100 ;i++)
   {
    instrução1
    if( x < 3.1) break;
    instrução2
   }
...

Os dois exemplos acima são quase iguais, salvo pelo fato que no último somente a instrução1 é realizada.

Ciclo condicionais - do-while e while

Os ciclos podem ser controlados de diversas formas. Como vimos anteriormente o for no seu uso mais simples repete um conjunto de instruções um número definido de vezes. Mas podemos adicionar mais condições de parada a ele.

Existem dois outros comandos equivalentes ao for que produzem ciclos. Nestes comandos os ciclos são interrompidos quando uma condição deixar de ser válida. São eles o do-while escrito como

...
do{
  instrução1;
  ...
  instruçãoN;
  } while( condição );
...

e o while escrito como

...
while( condição )
     {
     instrução1;
     ...
     instruçãoN;
     }
...

A única diferença entre os dois esta no momento onde a condição é testada. Por exemplo, o do-while realiza as suas instruções pelo menos uma vez já que a condição é sempre testada ao final.

Não existe nada novo nos comandos acima, eles podem ser facilmente implementados com a combinação de comandos for e if.

Exercício - Tente escrever um do-while usando um for e if, e um for usando um while.


Links