Uma linguagem de Alto Nível: ANSI C
A linguagem de programação que utilizaremos para implementar nossos algoritmos será a ANSI C, desenvolvida na década de 70 por Dennis Ritchie. O ANSI C é uma linguagem estruturada muito poderosa e possui compiladores em praticamente todas as arquiteturas existentes.
Este texto não é um curso completo de C e sim apenas uma grande “cola” para quem está fazendo o curso de algoritmos. Para maiores informações sobre a linguagem consulte a bibliografia recomendada nas referências.
A estrutura básica de um programa em ANSI C é:
int main() { Declarações de variáveis</i> Comando; Comando; Blocos de comandos; } |
Quando quisermos utilizar passagem de parâmetros e algum retorno para o sistema operacional, usamos a seguinte estrutura:
int main(int argc, char* argv) { Declarações de variáveis</i> Comando; Comando; Blocos de comandos; return 0; } |
3.1 – Tipos básicos
A maioria dos tipos básicos do portugol têm suas representações diretas em ANSI C:
PORTUGOL inteiro: idade; idade ← 18; real: peso; peso ← 56.4; lógico: aprovado, emCurso; aprovado ← verdadeiro; emCurso ← falso;
ANSI C
int idade; idade = 17; float peso; peso = 56.4; int aprovado, emCurso; aprovado = 1; // Verdadeiro emCurso = 0; // Falso |
3.2 – Conjunto de caracteres
O tipo caractere em PORTUGOL se limita a um tipo no ANSI C representando apenas uma letra: o char para guardar apenas um símbolo. O conjunto de caracteres “string” para se guardar uma seqüência de símbolos será construído posteriormente. Os valores literais para caracteres devem ser delmitados por aspas simples (‘a’) e os literais string por aspas duplas (“palavra”).
PORTUGOL caractere: letra; letra ← "A" caractere: nome; nome ← "Manoel da Silva"
ANSI C
char letra; letra = 'A'; char[16] nome; nome = "Manoel da Silva"; |
As strings são terminadas com um caractere vazio ‘\0’ e por isso quando formos definir uma variável deste tipo, devemos lembrar de adicionar um elemento a mais para este caractere. No nosso exemplo acima, “Manoel da Silva” tem 15 letras, mas a string para guardar este literal tem que ter 16 posições, mas cuidado para não confundir na hora de acessar as letras: o primeiro termo tem o índice 0. Quando passamos uma literal, o próprio C inclui o ‘\0’ para nós.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
‘M’ | ‘a’ | ‘n’ | ‘o’ | ‘e’ | ‘l’ | ‘ ‘ | ‘d’ | ‘a’ | ‘ ‘ | ‘S’ | ‘i’ | ‘l’ | ‘v’ | ‘a’ | ‘\0’ |
3.3 – Variáveis
A declaração de variáveis começa pela palavra reservada referente ao tipo e pode ser definida em qualquer parte do bloco de instruções.
int main(){ int idade; float peso; idade = 18; peso = 56.7; char aprovado, emCurso; aprovado = 1; emCurso = 0; } |
3.4 – Constantes
As constantes são um recurso para se evitar incluir literais em seu código. Na prática são variáveis que têm seu valor iniciado apenas no início do programa (em tempo de compilação). São declaradas como variáveis comuns, mas com palavra reservada const antes do tipo.
int main(){ const float pi = 3.14; const char[28] msgErro = 'Dados de entrada inválidos!'; int idade; float peso; } |
3.5 – Expressões e Operadores
Uma expressão segue combina operandos e operadores para retornar um único valor. A ordem de operadores pode ser descrita pela tabela abaixo:
Operadores | Tipo |
---|---|
++ — |
Incremento, Decremento (unários) |
() | Parênteses |
+ – |
Positivo e Negativo (unários) |
! | Não (unário) |
* / % |
Produto, Divisão e Módulo |
+ – |
Adição e Subtração |
> >= |
Maior que, Maior ou igual a |
< <= |
Menor que, Menor ou igual a |
== != |
Igual a, Diferente de |
&& || |
E , OU |
No C não temos o operador para potências X**Y. Para isto usaremos uma biblioteca externa
3.6 – Comando de atribuição
O comando de atribuição de valores em ANSI C é o “=” ao invés do “←” do PORTUGOL. Este comando joga o valor do resultado da expressão à esquerda na posição de memória correspondente ao identificador à direita:
PORTUGOL
idade ← 18; media ← (N1+N2)/2;
ANSI C
idade = 18; media = (N1+N2)/2; |
3.8 – Declaração de entrada e saída
Os comandos de entrada e saída leia() e escreva() devem ser substituídos pelas funções de leitura e escrita formatada: scanf() e printf() da biblioteca
PORTUGOL
leia(idade); leia(peso,altura); escreva(idade); escreva(peso," ",altura);
ANSI C
scanf("%d", &idade); scanf("%f %f", &peso, &altura); printf("%d", idade); printf("%f %f", peso, altura); |
O scanf() com várias variáveis lê os valores digitados no teclado separados por espaço. Para leitura de textos que possuem espaços em seus valores usamos o scanf(“%[^\n]”, &linha) que espera que o ENTER seja pressionado.
E de forma similar, prinft(“\n”) imprime o conteúdo com uma quebra de linha no final.
Para mais detalhes sobre as funções scanf() e printf() confira a apostila.
PORTUGOL
leia(nomeCompleto); escreva(idade);
ANSI C
scanf("%[^\n]", nomeCompleto); printf("%d\n", idade); |
3.9 – Estruturas de controle
As estrutura de controle são praticamente traduções dos comandos em PORTUGOL. Uma seqüência de comandos simples podem ser agrupadas em um único comando pelo chamado bloco de código. Os comandos são escritos separados por “;” e devem estar dentro de um {…}.
Condicional
PORTUGOL
se<condição> então comando1; comando2; ... fim-se;
ANSI C
if(condição) { comando1; comando2; ... } |
PORTUGOL
se condição então comando1; comando2; ... senão comandoA; comandoB; ... fim-se;
ANSI C
if(condição) { comandoA1; comandoA2; ... } else { comandoB1; comandoB2; ... } |
escolha <Expressão> caso v11,v12,...v1n: C1; caso v21,v22,...v2n: C2; ... caso vn1,vn2,...vnn: Cn; senão Cs; fim-escolha;
switch(Expressão){ case v11,v12,...v1n: comando1; break; case v21,v22,...v2n: comando2; break; case v31,v32,...v3n: comando3; break; case v41,v42,...v4n: comando4; break; ... case vn1,vn2,...vnn: comandoN; else comandoT; } |
Repetição
PORTUGOL enquanto (condição) comando1; comando2; ... fim-enquanto;
ANSI C
while(condição){ comando1; comando2; ... } |
repita comando1; comando2; ... até<condição>
do { comando1; comando2; ... } while (condição) |
para<variável> de<início> até<fim> faça comando1; comando2; ... fim-para
for(variável=início; condição; incremento) { comando1; comando2; ... } |
3.10 – Estruturas de dados
Tipo definidos pelo usuário são os vetores, matrizes e registros. O ANSI C dá os recursos para que o usuário crie estas estruturas deixando seus dados em um nível de abstração mais alto, mais próximo da realidade.
Vetores
Um vetor em ANSI C é um tipo de dados declarado pelo programador que agrupa várias variáveis do mesmo tipo em uma única declaração. Cada elemento deve ser referenciado através do índice. Os índices começam de 0.
Em PORTUGOL: tipo <identificador> = vetor[<inicio>:<fim>] <tipo>; tipo TReais = vetor[1:40] real; TReais: notas; tipo TTextos = vetor[1:40] caracter; TTextos: nomes;
Em ANSI C:
float notas[40]; notas[39] = 98.9; char nomes[40][255]; nomes[5] = "Pedro"; |
Matrizes
Uma matriz em ANSI C é definida como um vetor de mais uma dimensão. Para cada dimensão há um índice associado.
tipo <identificador> = matriz[d1i:d1f, d2i:d2f, ...] de <tipo>; tipo TReais = matriz[1:40, 1:3] de real; tipo TReais: notas;
float notas[40][4]; notas[23][0] = 100.00; notas[23][1] = 90.00; notas[23][2] = 80.00; notas[23][3] = 100.00; |
Registros
Os registros ou estruturas são tipos não homogêneos definidos pelo programador. Devem ser definidos usando o comando struct antes de se ter variáveis declaradas.
Em PORTUGOL: tipo TPessoa = registro caracter: nome; inteiro: idade; lógico: sexo; real: peso; fim-registro;
Em ANSI C:
struct TPessoa { char nome[255]; int idade; char sexo; float peso; <u>}</u>; struct TPessoa p; |
3.11 – Procedimentos e funções
Os procedimentos e funções devem estar definidos antes dos blocos onde serão utilizados e seguem a sintaxe abaixo:
Em PORTUGOL:
procedimento <identificador>(<parâmetros>); <declaraçao de parâmetros> início C1; C2; ... Cn; fim;
Em ANSI C:
void identificador(tipo parâmetro){ C1; C2; ... Cn; } |
Onde a declaração dos parâmetros é feita como uma definição das variáveis
normal em ANSI C, mas separados por vírgulas “,”. Se o identificador de uma declaração de parâmetro for precedida por um asterísco * este parâmetro é passado por referência e caso contrário, por cópia. Parâmetros passados
por referência podem ter seu valor global ao procedimento alterado, sendo muito utilizados
como variáveis de retorno de procedimentos e funções.
Um função se comporta exatamente como um procedimento, exceto pelo fato de ela própria ter
um valor de retorno. O valor de retorno de uma função é definido dentro do seu corpo quando
se usa o comando return. Este comando é obrigatório em funções mas proibido em procedimentos!
Em PORTUGOL:
função <identificador>(<parâmetros>):<tipo>; <declaraçao de parâmetros> início C1; C2; ... <identificador> ← <valor>; ... Cn; fim;
Em ANSI C:
tipo identificador(declaraçao de parâmetros){ { C1; C2; ... ... Cn; return valor; } |
Exemplo:
int somaDosPrimeiros(int n){ int soma = 0; int c; for(c = 0; c<n; c++){ soma = soma+c; } return soma; } |
Deixe uma resposta