




























Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
- - -
Tipologia: Notas de estudo
1 / 36
Esta página não é visível na pré-visualização
Não perca as partes importantes!





























Este pequeno apontamento serve para apresentar rapidamente as funcionalidades básicas da linguagem C. No entanto, muito fica por cobrir, devendo o interessado pro- curar outras fontes para aprender esta linguagem poderosa. O meu livro preferido é ’The C Programming Language’ de Brian Kernighan e Dennis Ritchie (edição da Prentice Hall). O manual do UNIX (comando ’man’) é um companheiro inseparável durante a escrita de um programa, pelo que é outra fonte que vivamente recomendo.
Durante a segunda metade do século XX, o papel dos sistemas informáticos na soci- edade teve um crescimento impressionante. Os computadores têm sido fundamentais no desenvolvimento científico e tecnológico (e.g. exploração espacial, projecto do Ge- noma Humano), mas tem também influenciado a sociedade em geral (e.g. telecomuni- cações, operações bancárias, Internet). Um computador é uma máquina electrónica com memória, capaz de realizar vários cálculos aritméticos e lógicos por segundo. Porém, para cada aplicação que se pretenda que o computador realize, é necessário instruí-lo sobre as tarefas que deverá realizar com os dados. A esta tarefa chama-se Programação. Um programa é uma sequência de instruções que o computador deve realizar de forma a processar os dados e obter os resultados correctamente.
O primeiro computador electrónico foi o ENIAC. Construído nos EUA durante a II Guerra Mundial e concluído em 1946, tinha por finalidade calcular rapidamente as ta- belas de tiro para peças de artilharia e bombardeamentos. Era uma máquina enorme construída por 18000 válvulas e 1500 relés, ocupando várias salas. A sua fiabilidade era reduzida, dado que as válvulas fundiam facilmente, devida à potência irradiada por estes componentes. Os programas eram inseridos através de um leitor de cartões perfurados (da IBM), sendo escritos directamente em código-máquina (utilizando uni- camente os dois únicos símbolos binários zero e um ). Adicionalmente, o ENIAC não era capaz de armazenar os programas em memória, pelo que era necessário configurar um conjunto de interruptores e ligações por cabos (trabalho realizado por seis técnicas) de acordo com o programa a ser executado. No entanto era capaz de calcular uma tra- jectória de 60 segundos em apenas 30 segundos, em oposição às 20 horas tomadas por um técnico-matemático com uma calculadora de secretária. A linguagem máquina, sendo a única que os computadores entendem, oferece gran- des dificuldades aos programadores:
Dado que o nível de programação se situa muito acima da linguagem-máquina, a apli- cação de simples tradutores como um assembler já não seria possível. Surgiram en- tão os compiladores, aplicações capazes de procurar erros de sintaxe e concepção nos textos dos programas e transformar as instruções em linguagem quase-natural para lin- guagem máquina. Uma única instrução como
PRINT "Olá, tudo bem?"
em BASIC (ordenando o computador para imprimir uma frase no ecrã), seria traduzida em algumas dezenas de instruções em código máquina.
1.2 Os sistemas operativos.
Um computador é constituído por um conjunto de dispositivos electrónicos (placa grá- fica, impressora, teclado, disco, etc.). De computador para computador, é normal en- contrarmos placas gráficas diferentes, discos de diferentes capacidades ou fabricantes, pelo que seria muito difícil a um programador construir aplicações (por exemplo, um processador de texto) para uma máquina específica, e ter que rescrever o programa só para que ele funcionasse num outro computador com uma placa gráfica diferente. Sur- giu então a necessidade de um sistema operativo, que oferecesse um serviço de acesso uniforme aos dispositivos físicos para as aplicações. Com a existência de um sistema operativo, uma aplicação como um editor de texto só precisa de saber ordenar ao sistema operativo que quer que um dado documento seja impresso: caberá ao sistema operativo a função de enviar para a impressora todos os dados necessários para a impressão (ver figura 1.1).
Figura 1.1: Camadas Aplicação / Sistema Operativo / Hardware.
O sistema operativo gere todas as actividades de um computador:
O sistema operativo depende da arquitectura do computador, existindo para cada ar- quitectura pelo menos um sistema operativo. Na tabela 1.1 são apresentados alguns sistemas operativos para várias arquitecturas:
Tabela 1.1: Arquitecturas e Sistemas Operativos. Arquitecturas Sistemas operativos Intel x86 Windows UNIX (Linux, Free BSD, Solaris, etc) BeOS PowerPC (Mac) MacOS ver 7, 8, 9 MacOS X (UNIX) HP HP-UX (UNIX) SGI (Silicon Graphics) IRIX (UNIX) SUN Solaris (UNIX)
1.3 Compiladores.
Tal como referido anteriormente, os compiladores transformam os textos dos progra- mas (em linguagem de alto-nível) em código-máquina. Como o código-máquina é produzido para utilizar os recursos oferecidos pelo sistema operativo, facilmente se depreende que para cada sistema operativo deverá existir um compilador. Assumindo que se escreveu um programa em linguagem C. Se esse programa for compilado para Windows, o código-máquina gerado não será inteligível para o sistema operativo Linux, nem para o MacOS. Para o programa ser executável em vários siste- mas operativos, é pois então necessário compilá-lo para cada um dos sistemas. Num futuro capítulo, será explicado o processo de compilação de um programa.
int contador = 0;
float cateto1, cateto2, hipotenusa;
A primeira linha declara a variável contador para conter números inteiros e inicializa-a com o valor 0. Na segunda linha, são declaradas as variáveis cateto1, cateto2 e hipotenusa, para conter números com parte fraccionária.
2.3 As funções.
No último bloco escreve-se o código das funções (aquilo que realmente faz mexer o programa). As funções são declaradas através do tipo do valor retornado, o identifica- dor da função e a lista dos argumentos que a função recebe. No seguinte exemplo, teremos uma função que calcula o comprimento da hipote- nusa de um triângulo rectângulo, recebendo como argumentos os comprimentos dos catetos:
float calculahipotenusa (float cat1, float cat2)
A função chamada calculahipotenusa() devolve um resultado do tipo float (à esquerda do nome da função), aceitando como argumentos dois valores do tipo float, que serão identificados dentro da função pelos nomes cat1 e cat2. A sequência de instruções que a função deve realizar é encapsulada entre chavetas. Em C, as chavetas são utilizadas para agrupar sequências de instruções. Dentro do grupo de instruções, existe um primeiro bloco em que são declaradas as variáveis locais à função e, finalmente, a sequência de instruções. Continuando o exemplo, o código da função poderia ser o seguinte:
{ float hip; /* Declaração da variável local hip */
cat1 = cat1 * cat1; /* Eleva os catetos ao quadrado */
cat2 = cat2 * cat2;
hip = cat1 + cat2; /* Soma o quadrado dos catetos */
hip = sqtr(hip); /* e determina a raiz quadrada */
return(hip); /* Retorna o valor da variavel hip */ }
2.4 A função main().
O programa, depois de compilado, começa a executar as instruções contidas numa função especial: a função main(). Esta função deve conter o algoritmo principal, e chamar as funções necessárias à execução do algoritmo. Tendo em conta os exemplos anteriores, poderíamos escrever a seguinte função main():
main() { float c1, c2, hipotn; /* Declara as variáveis locais */
/* Escreve no ecrã a frase entre aspas */ printf("Cálculo de hipotenusa...\n");
/* O utilizador introduz os comprimentos dos catetos */ printf("Introduza o comprimento de um dos catetos: "); scanf("%f", &c1); printf("Introduza o comprimento do outro cateto: "); scanf("%f", &c2);
/* A hipotenusa é calculada, chamando a / / função calculahipotenusa() */ hipotn = calculahipotenusa(c1, c2);
printf("O comprimento da hipotenusa: %f\n", hipotn); }
2.5 Exercícios.
if (saldo < compra) { printf("O saldo é insuficiente para realizar a compra.\n"); printf("Por favor, efectue um carregamento do seu cartão.\n"); }
No seguinte caso, é avaliada a relação maior-igual-menor entre dois números:
if (a > b) printf("%d é maior que %d.\n", a, b); else if (a < b) printf("%d é menor que %d.\n", a, b); else printf("São iguais.\n");
Quando o leque de acções a realizar depende do valor de uma variável, podemos utilizar a instrução switch(). Atendendo ao seguinte exemplo:
printf("Qual a operação que pretende efectuar? "); operador = getch(); switch (operador) { case ’+’: resultado = a + b; break; case ’-’: resultado = a - b; break; case ’*’: resultado = a * b; break; case ’/’: resultado = a / b; break; default: printf("Operação não permitida!\n"); break; }
Mediante o carácter teclado pelo utilizador, o programa irá realizar a operação preten- dida. Para cada caso previsto, é indicada a sequência de instruções a realizar. A palavra break termina a sequência de instruções para cada opção. A opção default é realizada sempre que nenhuma das condições anteriores não tenha sido satisfeita.
3.2 Ciclos.
As ciclos decorrem da necessidade de repetir a mesma sequência de acções até que determinada condição seja alcançada.
Os ciclos for() são utilizados quando as operações de inicialização e incremento são simples, normalmente utilizando uma variável como contador do ciclo. O método de declaração de um ciclo for() é o seguinte:
for(inicialização; condição; operação no fim de cada ciclo)
A inicialização é uma operação realizada antes de se iniciar a actividade do ciclo. O ciclo só é executado enquanto o valor da condição for ’verdade’. No final de cada ciclo, é executada a instrução que se encontra no terceiro argumento. O seguinte exemplo:
soma = 0; for(contador = 1; contador < 5; contador++) { printf("Contador: %d\n", contador); soma += contador; } printf("Somatório: %d\n", soma);
produziria a saída:
Contador: 1 Contador: 2 Contador: 3 Contador: 4 Somatório: 10
Os ciclos while() são realizados enquanto uma determinada condição é válida. Se a condição à partida for inválida, o ciclo não chega sequer a ser executado (o número mínimo de execuções do ciclo é ZERO).
total = 0;
while(total < 50000) { scanf("%d", &custo); total += custo; }
O exemplo acima, permite introduzir custos enquanto o total de custos é menor do que
Os ciclos do ... while() asseguram que o conjunto de instruções dentro do ciclo é exe- cutado pelo menos UMA vez, isto porque a condição de execução do ciclo é avaliada apenas no fim.
Uma função é um conjunto de instruções, capaz de realizar uma determinada tarefa. A grande vantagem de escrever funções num programa em C, é podermos escrever uma única vez o conjunto de instruções (função), e chamá-la várias vezes durante a execução do programa. As funções podem receber valores e realizar processamento sobre esses valores, retornando o resultado desse processamento.
Uma função é declarada no seu cabeçalho. O cabeçalho de uma função contém os seguintes elementos:
Após o cabeçalho da função, deverá vir o corpo da função. O corpo de uma função é o conjunto de instruções que a função deverá realizar, delimitado por chavetas.
As funções sem parâmetros têm por função realizar uma tarefa, independentemente de quaisquer dados. A seguinte função escreve um menu de selecção no ecrã. Imprimir estas quatro linhas de texto não requer a recepção de quaisquer valores.
void mensagem () { printf("\n\nEscolha a opção:\n");
printf("1 - Inserir\n"); printf("2 - Remover\n"); printf("3 - Sair\n\n"); }
4.3 Funções com parâmetros.
Grande parte das funções processam dados que lhes são passados como parâmetros. Uma função que calcule o comprimento de uma hipotenusa, terá que necessariamente receber os valores dos comprimentos dos catetos. Há duas formas de passar parâmetros:
Neste caso, a função recebe cópias dos valores que foram fornecidos aquando da cha- mada da função. Quaisquer alterações dos valores das cópias não afectarão os valores originais. Suponha o seguinte exemplo:
#include <math.h>
(...)
float hipotenusa (float cateto1, float cateto2) { float hipotenusa; cateto1 = cateto1 * cateto1; cateto2 = cateto2 * cateto2; hipotenusa = cateto1 + cateto2; hipotenusa = sqrt(hipotenusa); return (hipotenusa); }
(...)
main () { float cat1 = 3.00; float cat2 = 4.00; float hip;
hip = hipotenusa(cat1, cat2); (...) }
Neste exemplo, as variaveis cateto1 e cateto2 da função hipotenusa() recebem cópias dos valores das variáveis cat1 e cat2 e da função main(). As operações realizadas nas
Muitas vezes temos necessidade de operar com vários elementos que representam a mesma grandeza, e que se encontram relacionados: a posição de uma partícula ao longo do tempo, os valores de resistências eléctricas num circuito... Tomemos por um circuito eléctrico que contém 10 resistências. É necessário escre- ver um programa que efectue uma série de cálculos utilizando os valores das resistên- cias. Os valores das resistências deverão ser inseridos pelo utilizador. Logo à partida, confrontamo-nos com a necessidade de declarar 10 variáveis, uma para cada resistência. A tarefa ainda se complica mais quando tivermos que repetir 10 vezes as instruções de inserção dos valores das resistências. A utilização de vectores permite facilitar (e bastante) a escrita de programas que utilizem grandes quantidades de dados do mesmo tipo.
A declaração de um vector é semelhante à de uma variável. No entanto, teremos que indicar (entre parêntesis rectos) a dimensão do vector. Entenda-se por dimensão do vector, o número de valores que o vector suporta.
main() { float resistencias[10];
(...) }
No exemplo anterior, é definido um vector chamado resistencia, com capacidade para dez valores do tipo float.
A forma de aceder aos elementos de um vector é semelhante à forma de aceder ao con- teúdo de uma variável. No entanto, será necessário indicar qual o índice do elemento ao qual se pretende aceder. Considere um vector como uma rua, e o índice como o número de uma casa nessa rua.
O primeiro elemento do vector encontra-se no índice zero. Desta forma, o último elemento encontra-se no índice dimensão-1, em que dimensão é dimensão do vector. O seguinte exemplo demonstra alguns exemplos de utilização dos vectores.
main() { float resist[10];
/* Insere 6 valores de resistências para as / / posições de 0 a 5. */ for(i=0; i<6; i++) { printf("Insira o valor da resistência R%d: ", i); scanf("%f", &resist[i]); }
resist[7] = (resist[0] + resist[1]) * 0.63;
(...)
}