Você está na página 1de 61

ESCOLA SUPERIOR DE TECNOLOGIA E GESTÃO

INSTITUTO POLITÉCNICO DE LEIRIA

ENGENHARIA AUTOMÓVEL
ENGENHARIA E GESTÃO INDUSTRIAL

APONTAMENTOS DE APOIO ÀS AULAS DE

PROGRAMAÇÃO I
por
Filipe Neves
&
Micaela Esteves

Versão 1.3
2003/2004
Análise do problema e formulação de um algoritmo

GENERALIDADES SOBRE PROGRAMAÇÃO

O que é a programação?

O comportamento e o pensamento humano dão-se em sequências lógicas. Muito do que fazemos cada dia
fazemo-lo automaticamente, a um nível inconsciente. Felizmente não é necessário para nós pensarmos
conscientemente cada passo que damos em algo tão simples como mover esta página com a mão. Mas se
o fizermos conscientemente damo-nos conta das seguintes tarefas:
§ Levantar a mão
§ Mover a mão para a parte direita da folha
§ Agarrar a esquina da página
§ Mover a mão da direita para a esquerda
§ Soltar a página

Por sua vez, cada uma destas tarefas elementares é ainda composta por outras tarefas mais pequenas.

Outro exemplo de uma sequência lógica é a forma como limpamos os dentes. Tem-se o cuidado de
colocar a pasta de dentes na escova e depois escovar os dentes. Qualquer coisa que fazemos necessita de
uma sequência lógica de passos. Toda a nossa civilização está baseada na ordem das coisas e das acções.
A ordenação consciente ou inconsciente é uma parte importante das nossas vidas. Esta ordenação adquire-
se através de um processo que se pode chamar de programação.

Programação – É a planificação, projecção e execução de uma tarefa com sucesso.

Programação de um computador – É o processo de planificar uma sequência de instruções que o


computador deve seguir, com vista a executar uma determinada tarefa.

Para escrever uma sequência de instruções que um computador deve seguir é necessário seguir uma certa
estratégia. Este procedimento é composto por uma fase de resolução do problema e uma fase de
implementação.

Fase de resolução do problema (à mão)

Análise- Compreender (definir) o problema.

Micaela Esteves & Filipe Neves 2/61


Análise do problema e formulação de um algoritmo

O programador analisa o problema e desenvolve uma solução geral chamada de algoritmo.

Solução geral (algoritmo)- Desenrolar de uma sequência ló gica de passos utilizados para resolver o
problema.

Prova- Seguir a sequência de passos anteriormente determinada para ver se a solução resolve
verdadeiramente o problema.

Fase de implementação

O computador não é inteligente. Não pode analisar um problema e encontrar uma solução. O programador
é que deve encontrar uma solução e comunicá-la ao computador. Assim, é necessário que à máquina
sejam indicados todos os passos a seguir bem como os possíveis e diferentes caminhos pelos quais é
possível optar, a fim de se obter um determinado resultado. Torna-se pois, necessário conhecer todos
estes passos elementares e a respectiva sequência, por forma a dá-los a conhecer à máquina. É a esta
tarefa que chamamos programar, ou codificar, como veremos já à frente.

Solução específica (programa)- Traduzir o algoritmo numa linguagem de programação específica:


Pascal, C, Basic, Java, Cobol, ...

Prova- Fase em que o computador segue as instruções. Comprovar os resultados e fazer as correcções se
necessário.

Uso- Utilizar o programa.

Algoritmo

Mas voltemos ao assunto do algoritmo para o definir e usar na resolução de dois problemas.
Algoritmo é uma sequência ordenada e precisa de passos, acções ou operações, que conduzem à solução
de um dado problema.

Usamos algoritmos todos os dias. São simplesmente uma descrição verbal ou escrita de sequências
lógicas de acções. Receitas de cozinha, instruções para instalar um vídeo e para instalar uma impressora,
são exemplos de algoritmos escritos.

Micaela Esteves & Filipe Neves 3/61


Análise do problema e formulação de um algoritmo

EXEMPLO:
Quando se arranca com um carro realiza-se um procedimento passo a passo. O algoritmo pode ser:
§ Colocar a chave
§ Assegurar que o carro está em ponto morto
§ Dar à chave para a posição de arranque.
§ Se o motor arranca antes de 6 segundos, pode-se começar a andar.
§ Se o motor não arranca antes dos 6 segundos esperar 10 segundos e repetir os passos desde
o 3 até ao 5 (mas não mais do que cinco vezes).
§ Se o carro não arranca chamar um mecânico.

Sem a condição “não mais de cinco vezes” no passo 5, podia-se interpretar que estaríamos a tentar
arrancar com o carro para sempre. Porquê? Se algo falha no carro, a repetição dos passos 3 a 5 nunca
mais pára. Esta situação de nunca mais terminar chama-se de ciclo infinito. Um algoritmo deve terminar
ao fim de uma quantidade finita de tempo (ou de vezes, neste contexto chamadas de iterações) em todas
as possíveis condições.

EXEMPLO:
Um programador pode necessitar de um algoritmo para determinar o salário semanal de um empregado.
Se fizer mais que 35 horas, recebe o dobro pelas horas extra. O algoritmo deve reflectir como o faríamos
à mão:
§ Ir buscar o preço por hora do empregado.
§ Determinar o número de horas efectuadas durante a semana
§ Se o número de horas de trabalho durante a semana for menor ou igual a 35, multiplicar
esse número pelo preço de uma hora.
§ Se o número de horas for superior a 35 horas, multiplicar 35 horas pelo preço de uma hora
e às restantes pelo dobro do preço de uma hora, de forma a calcular o preço das horas
extras.
§ Somar o salário normal com as horas extras (se houver) obtendo-se assim o salário a pagar.

Destes exemplos podemos notar que um algoritmo deve possuir as seguintes características:
§ total ausência de ambiguidade, ou seja; a interpretação dada ao algoritmo é sempre a mesma,
independente da leitura que dele se faça ou de quem faça a sua leitura;
§ número finito de acções;
§ generalidade.

Micaela Esteves & Filipe Neves 4/61


Análise do problema e formulação de um algoritmo

Depois de encontrar uma solução geral, o programador percorre-a (o algoritmo) efectuando cada passo
manualmente ou mentalmente. Se esta prova não produz as respostas correctas, então repete-se o processo
analisando de novo o problema formando um outro algoritmo. Quando o programador está satisfeito com
o algoritmo, há que transcrevê-lo para a linguagem de programação que se pretende utilizar – trata-se da
operação de codificação: produzir uma mensagem ou conjunto de mensagens que designam acções em
conformidade com um determinado código que o computador entenda.

Sobre a resolução de problemas, pode-se resumir o que se disse anteriormente através do seguinte
esquema:
Início do programa

Análise da situação/problema

Formulação de um algoritmo

Prova:
Não
A solução resolve o
problema?

do
Sim

Revisão
Codificação:
do
Tradução do algoritmo numa linguagem de
programação específica
Revisão

Tradução (compilação / interpretação) do


programa fonte para código máquina e
verificação dos erros de escrita

Detecção de erros Não


de escrita?

Sim

Teste de verificação lógica do programa

Detecção de Não
erros de lógica

Sim

Programa terminado

Micaela Esteves & Filipe Neves 5/61


Análise do problema e formulação de um algoritmo

Estratégias de resolução de um problema

Quando se depara com um problema extenso e complexo, o ser humano mostra-se limitado no sentido de,
só conseguir compreender pequenas partes de cada vez. Uma estratégia para colmatar esta limitação
humana baseia-se no princípio «dividir para conquistar». Não é mais do que dividir o problema inicial em
subproblemas menores de modo a que este se torne mais facilmente compreensível e de mais fácil
interpretação e resolução. Nesta estratégia várias abordagens são possíveis. Entre elas podem contar-se a
de tentativas sucessivas, a abordagem ascendente e a abordagem descendente. No nosso estudo focaremos
a abordagem descendente ou “top-down”.

Abordagem “top-down”

Esta técnica leva-nos a adquirir um hábito essencial ao sucesso, que é a organização e método, obrigando-
nos à divisão do problema em módulos e cada módulo noutros mais simples e assim sucessivamente até
se compreender, sem qualquer ambiguidade, o significado dessa parte do problema. Este método é
conhecido como método descendente (ou “top-down”).
Pode-se dividir o método descendente do seguinte modo:
1. Análise do problema.
2. Algoritmo
3. Prova1

Análise do problema
1.1- Compreender o problema. Compreender o que se dá (dados de entrada) e o que se pede (dados
de saída).
1.2- Especificar os formatos de entrada e os de saída.
1.3- Pensar em como se pode resolver o problema à mão.

Algoritmo
2.1- Escrever o módulo principal
Se este módulo é demasiado grande é porque está com um nível demasiado baixo de detalhe, o
que é sinal que pode ser decomposto em módulos. Tudo o que se tem a fazer no módulo principal
é atribuir nomes aos módulos do nível inferior. Como nomes para os módulos, devem sempre
utilizar-se nomes com significado.
Este módulo é quase linguagem falada, à qual foram retiradas palavras redundantes.

1
Já conhecemos estes termos e nesta sequência. O que abordáramos antes fora uma introdução à abordagem
descendente.
Micaela Esteves & Filipe Neves 6/61
Análise do problema e formulação de um algoritmo

2.2- Escrever os restantes módulos


Os módulos de um nível podem especificar mais módulos de um nível inferior. Um módulo está
completo quando não faz referência a nenhum outro.

Prova
Trata-se da verificação mental para ver se a solução “funciona”.

EXEMPLO:
Para melhor compreender esta técnica vejamos um exemplo prático.
Pretende-se elaborar um programa que determine a média ponderada de três exames. Os dados são
inseridos na seguinte sequência: nota do exame; respectivo peso.
Para facilidade poderemos no fim fazer um teste considerando pesos de 30%, 30% e 40%
respectivamente.

Análise do problema
Dados de entrada: três grupos de dados, cada um composto por nota de exame e respectivo peso;
As notas de exame são sempre valores inteiros.
Peso dos exames podem ser números reais.

Dados de saída: imprimir a média ponderada dos três exames.


A média é um número real, uma vez que os pesos dos exames também são números reais.

Pensar em como resolver o problema à mão:


O conceito de dar pesos dif erentes a exames utiliza-se frequentemente para obter a nota final de um
estudante num curso.
Por exemplo, podemos pensar num peso de 30% para dois exames e outro exame com um peso de 40%.
Vamos supor que o aluno obteve a seguinte classificação nos exames:
1º exame: 15 valores
2º exame: 13 valores
3º exame: 16 valores.
Para obter a média ponderada multiplica-se a nota de exame pelo valor do peso. O valor obtido divide-se
por 100:

15*30 + 13*30 + 16*40=1480


1480/100=14.8

Micaela Esteves & Filipe Neves 7/61


Análise do problema e formulação de um algoritmo

O valor da média é de 14.8. Não nos esqueçamos que estivemos a raciocinar para o caso de os pesos
terem aqueles valores concretos.
O algoritmo deverá contemplar um caso genérico.

Escrever o módulo principal

Obter dados
Encontrar a média
Mostrar a média

Escrever os restantes módulos

Obter dados:

Ler a nota do 1º exame e peso 1


Ler a nota do 2º exame e peso 2
Ler a nota do 3º exame e peso 3

Encontrar a média

Cálculo intermédio = 1º exame*1º peso + 2º exame* 2º peso + 3º exame*3º peso


Média = Cálculo intermédio / 100

Imprimir a média

Escrever a Média

Embora este seja um problema de fácil resolução e possa portanto parecer desnecessário esta abordagem
exaustiva, o uso desta abordagem é crucial para a aprendizagem da programação. Com o evoluir da
complexidade dos problemas/programas, esta abordagem revelar-se-á útil e gratificante. Também com o
evoluir na tarefa de programar, o método irá progressivamente sendo assimilado e chega o ponto em que
o utilizaremos tão fácil e intuitivamente que já não nos damos conta do seu uso, nem mesmo da facilidade
que ele permite.

Micaela Esteves & Filipe Neves 8/61


Análise do problema e formulação de um algoritmo

Abordagem por tentativas

Por vezes a abordagem anterior revela-se impotente para resolver todos os problemas, tornando-se mais
evidente resolver o problema por tentativas sucessivas. Como exemplo apresenta-se o seguinte problema:
Maria tinha um cesto com maçãs e encontrou um amigo a quem deu metade das
maçãs e mais meia maçã. Depois encontrou outro amigo a quem deu igualmente
metade das maçãs que tinha e mais meia maçã e mais meia maçã. Por fim encontrou
um terceiro amigo a quem deu metade das maçãs que lhe restavam e mais meia maçã
e ficou sem nenhuma. Quantas maçãs tinha a Maria antes de encontrar o primeiro
amigo?

Podemos chegar à solução por tentativas sucessivas. Numa primeira tentativa imaginemos que Maria
tinha inicialmente 13 maçãs. Seguindo os passos apresentados no problema, chegamos a um resultado
final no qual Maria fica com ¾ de maçã. Concluímos que partimos dum valor demasiado elevado
inicialmente.
Na nova tentativa teremos que começar com um número menor. E assim por tentativas chegaremos à
solução.

Abordagem “bottom –up”

Esta técnica segue o sentido inverso da primeira para chegar à solução do problema, isto é, partimos do
resultado e tentamos atingir as condições iniciais do problema. Embora aparentemente absurda revela-se
muitas vezes útil. O problema anterior tem uma solução muito mais rápida se usarmos esta abordagem
pois conhecemos a quantidade final de maçãs que Maria tinha no cesto.

Para a nossa disciplina de programação interessa-mos sobretudo a primeira abordagem.

Micaela Esteves & Filipe Neves 9/61


Análise do problema e formulação de um algoritmo

Técnicas de representação de algoritmos

Existem algumas formas para representar algoritmos. De entre elas podem citar-se:
• pseudocódigo
• fluxogramas,
• tabelas de decisão,
• quadros estruturados,
• diagramas HIPO

Pseudocódigo

Na fase de escrita do algoritmo do problema anterior utilizámos uma linguagem muito próxima da falada
pelo ser humano. A esta técnica chamamos pseudocódigo e não consiste em mais que pegar no texto em
português que descreve a resolução do problema e retirar-lhe as redundâncias de linguagem bem como as
suas ambiguidades, ficando assim um texto ainda compreensível de forma inequívoca. Para este
pseudocódigo existem algumas palavras chave habitualmente escritas em maiúsculas, a saber:
• INÍCIO / FIM
• LER / ESCREVER
• SE ... ENTÃO ... SENÃO ...
• REPETIR ... ATÉ QUE ...
• ENQUANTO ... FAZER ...
• FAZER n VEZES ...

EXEMPLO:
* programa que lê um número, calcula o seu dobro e apresenta o resultado
INÍCIO
LER a
b=a*2
ESCREVER “o dobro de a é:” b
FIM

Neste exemplo note-se uma hierarquia de tabulação para explicitar um pedaço de pseudocódigo como
pertencendo a um troço funcionalmente independente. A esta forma de apresentação chamamos
identação, e é uma prática bastante útil para uma fácil legibilidade dum algoritmo.
Para referir uma linha como comentário, isto é, cujo conteúdo não tem qualquer significado em termos da
execução na resolução do problema, mas simplesmente constituindo notas para o leitor, usa-se o símbolo
asterisco no início de linha.

Micaela Esteves & Filipe Neves 10/61


Análise do problema e formulação de um algoritmo

Fluxogramas

Fluxogramas são diagramas que mostram as operações a realizar e a sequência segundo a qual as
diferentes operações que constituem o algoritmo deverão ser realizadas. Para tal recorre-se a um conjunto
de símbolos padrão, a saber :

• Processamento

• Leitura/escrita

• Linhas de fluxo

• Conector

• Decisão

• Decisão múltipla

• Início/fim

Estruturas algorítmicas

Perante a análise dum algoritmo com alguma atenção, podemos reparar que certas vezes o fluxo das
acções a desempenhar apresenta diversos padrões ou estruturas:
• Sequência: o fluxo do programa é linear, sendo as instruções executadas uma após outra.
• Selecção: o fluxo dum programa não é linear. Dependendo da avaliação de uma dada condição é
executada o fluxo é desviado numa direcção ou noutra, executando diferentes conjuntos de
instruções. É o caso do uso de SE... ENTÃO...SENÃO...
• Repetição: um dado conjunto de instruções é retomado várias vezes até que ou enquanto uma
dada condição seja verificada, sendo que o fluxo do programa tema forma cíclica. É o caso do uso
das expressões como ENQUANTO ... FAZER, REPETIR ... ATÉ QUE ... ou FAZER n VEZES.

Micaela Esteves & Filipe Neves 11/61


Análise do problema e formulação de um algoritmo

Dados e tipos de dados

Bem sabida agora a definição de algoritmo, podemos descrevê-lo como sendo uma “caixa” com uma
lógica implementada no seu interior, mas cujos pormenores nada conhecemos sob ponto de vista de
utilizadores (por isso se lhe chama uma caixa preta) que recebe valores de entrada (os dados; o input) e
apresenta valores à saída (os resultados; o output).

Os dados que um computador pode manipular podem ser de vários tipos. Basicamente podemos ter:
• Dados numéricos. São constituídos por números positivos, negativos, inteiros, reais. O tamanho
de um determinado dado tem um limite inferior e um limite superior.
• Dados alfabéticos. São constituídos unicamente por letras ou sequências de letras às quais se dá o
nome de cadeias ou “strings”.
• Ao conjunto de dados numéricos em união com o conjunto de dados alfabéticos dá-se o nome de
alfanuméricos, e é o dado mais frequentemente designado que qualquer um dos outros dois.
Como exemplo refira-se a cadeia “escola123”.
Para representar cadeias ou “strings” usam-se como seus delimitadores as aspas. Assim por
exemplo temos o caracter “4” que não é o mesmo que o número 4. Voltaremos a este assunto
mais tarde.
• Dados lógicos. Também são chamados booleanos, por homenagem ao matemático Boole. Só
podem tomar dois valores: Verdadeiro ou Falso, também muitas vezes representados por 1 (um)
ou 0 (zero), respectivamente.

EXEMPLOS:
a) 3,14 é numérico real
b) 244 é um numérico inteiro
c) “António” é um alfabético (e também alfanumérico, apesar de não ter números)
d) V (verdade) é um lógico
e) “3,14” é um alfanumérico: tem 3 numéricos e um alfabético – a vírgula.

Constantes, variáveis e expressões

Definimos como constante um objecto (uma entidade) do algoritmo que contém um valor imutável, que
nunca se altera qualquer que seja a ocasião onde aparece, onde aparece ou o número de vezes que o
algoritmo é executado. Pode ser de qualquer dos tipos de dados apresentados.

Micaela Esteves & Filipe Neves 12/61


Análise do problema e formulação de um algoritmo

Definimos variável como sendo um objecto cujo conteúdo é possível de ser alterado durante o decorrer
do algoritmo. Em instantes diferentes pode assumir distintos valores.
Uma expressão é obtida pela composição de variáveis e constantes com operadores aritméticos ou lógicos
de modo a permitir o cálculo daquilo que se pretende. Como exemplo pode citar-se a
“Cálculo intermédio”, já utilizada nas aulas. Outro exemplo relacionado com o cálculo da área dum
círculo: “PI*R*R”.
Que acontece então ao valor PI*R*R? Há que atribuí-lo a algo! Neste caso estamos mesmo a ver que é a
uma área. Podemos pois atribuí-lo a uma variável que a represente.

Operação de atribuição

Para o caso anterior o nome area seria bem escolhido, pois é um nome sugestivo.
Como forma de representarmos essa atribuição escrevemos: area ← PI*R*R.
O símbolo ← significa que o valor resultante da expressão PI*R*R é atribuído à variável area.
Uma instrução de atribuição é sempre feita da direita para a esquerda e armazenada no objecto à
esquerda. É uma operação destrutiva, isto é, o valor que antes estava na variável desaparece para dar lugar
ao novo. A uma variável podemos atribuir uma outra variável ou uma constante. Por exemplo, após
definida a variável var podemos fazer:
var ← 5 significa que var toma o valor 5
var ← var + 1 significa que var toma o valor 6

NOTA1
Uma regra de bom senso é que a declaração sempre seja feita no início do bloco de código em que seja
utilizada.

NOTA2
Não é possível atribuir diferentes tipos de valores à mesma variável: umas vezes números, outras vezes
alfanuméricos.
var ← 5 não se pode fazer as duas, pois trata-se de tipos diferentes. 5 é
var ← “António” numérico; “António” é alfabético.

Outros operadores

Além do operador de atribuição, outros existem para fazer cálculos, cujo tipo varia de acordo com o tipo
dos dados que estão a ser operados (os operandos). Estes operadores dividem-se nos seguintes tipos:

Micaela Esteves & Filipe Neves 13/61


Análise do problema e formulação de um algoritmo

• Aritméticos:
§ de soma (+)
§ de subtracção (-)
§ de multiplicação (*)
§ de divisão (/)
§ de potenciação (^)
• Lógicos:
§ conjunção (E), (AND)
§ disjunção (OU), (OR)
§ negação (NAO), (NOT)

Relativamente a estes operadores há a referir a regra das prioridades que diz que numa expressão são
feitas em primeiro lugar as potenciações, depois as multiplicações e divisões, consoante a ordem em que
aparecem e depois as somas e subtracções, também segundo a ordem em que aparecem. Para subverter
esta regra podem usar-se os parêntesis, de cujo uso as seguintes expressões apresentam resultados
diferentes.
6+4/2 cujo resultado é diferente de (6+4)/2;
5+4*2^2/4-7, cujo resultado é 2, ou ((5+4)*2^2)/(4-7), cujo resultado é - 12.

Os operadores lógicos permitem avaliar condições e tomar decisões consoante o resultado da sua
avaliação. Uma condição é uma expressão acerca da qual se pode dizer se é verdadeira ou falsa.
Por exemplo na avaliação da condição:
Carro vai ao posto se [(falta gasolina) OU (falta faróis E circula de noite)].
Vemos que basta que falte a gasolina para ir ao posto, mas é necessário que se verifique simultaneamente
faltar faróis e que circule de noite para que necessite de lá ir.
Podemos estabelecer a chamada tabela de verdade para cada um destes operadores lógicos:

OU 1º operando 2º operando Resultado


F F F
F V V
V F V
V V V

E 1º operando 2º operando Resultado


F F F
F V F
V F F
V V V

Micaela Esteves & Filipe Neves 14/61


Linguagem de programação C

A LINGUAGEM C

O que é uma linguagem de programação

Linguagem de Programação- Um conjunto de regras, símbolos e palavras especiais utilizado para


construir um programa.

Utilizamos programas para fazer com que o computador trabalhe para nós. Estes programas são escritos
numa das muitas linguagens que existem hoje em dia.

Uma linguagem de programação (como aliás qualquer linguagem) é composta por:


• uma terminologia ou um conjunto de termos, palavras e sinais, que assumem determinados
significados (semântica)
• um conjunto de regras que estipulam o uso correcto dos termos, para construir enunciações
válidas (sintaxe).

Introdução à linguagem de programação C

A linguagem C foi projectada em 1972 nos laboratórios da Bell, por Brian W. Kernighan e Dennis
Ritchie, deriva do ALGOL 68, e tinha por finalidade permitir a escrita de um sistema operativo (o UNIX),
desenvolvido em 1967 e rescrito em 1973 utilizando a linguagem C.

O nome da linguagem (e a própria linguagem) resulta da evolução de uma outra linguagem de


programação, desenvolvida por Ken Thompson também nos laboratórios Bell, que se chamava B. Dado
que era uma evolução da linguagem B nada mais natural que ser intitulada de C.

O C é uma linguagem extremamente potente e flexível, e caracteriza-se pelos seguintes aspectos:

Rapidez − consegue obter performances semelhantes às obtidas pelo Assembly, usando instruções de alto
nível, isto é, utilizando instruções semelhantes às utilizadas por linguagens como o PASCAL ou o
COBOL mesmo para aceder a mecanismos de mais baixo nível, como os endereços de memória ou a
manipulação de Bits.

Micaela Esteves & Filipe Neves 15/61


Linguagem de programação C

Simples − a sua sintaxe é extremamente simples e o número de palavras reservadas, tipos de dados
básicos e operadores é pequeno, reduzindo assim a quantidade de tempo e esforço necessários à
aprendizagem da linguagem.

Alto grau de portabilidade − que permite que os seus programas fonte sejam transportados entre
computadores sem maiores problemas.

É de uso geral − é eficiente tanto para programação de utilitários como para sistemas operativos,
processadores de texto, base de Dados e sistemas aplicativos em geral.

Gera um código executável (objecto) compacto e rápido em relação à maioria das outras linguagens
compiladas, tornando a sua aplicação eficiente para micro-computadores de memória reduzida.

Permite total interacção com o sistema operativo e inserção de código Assembly no programa fonte,
sendo assim , "ilimitada" por software.

Possui uma sintaxe e poucos comandos e um grande número de operadores aritméticos e lógicos
(incluindo operadores para manipulação de bits) que mantêm relação directa com operações básicas dos
processadores.

É uma linguagem estruturada e modular − permite a simplificação do uso das mais modernas técnicas
de programação.

Permite tratamento de estruturas de dados na forma de registos e campos.

Bibliotecas poderosas - O C é composto por um número muito pequeno de palavras chave, facto que
poderia limitar as suas capacidades caso não fossem as funcionalidades que as bibliotecas adicionais lhe
proporcionam.

Evolução − O C é uma linguagem estável. A evolução das linguagens fez com que o C também evoluísse
no sentidos das Linguagens Orientadas por Objectos, dando origem a uma nova linguagem, o C++, a
qual mantém a sintaxe da linguagem C e permite um conjunto adicional de características -
Hereditariedade, Polimorfismo, Encapsulamento, “Overloading”, etc..

Micaela Esteves & Filipe Neves 16/61


Linguagem de programação C

Compilação e Geração de código executável

Habitualmente são quatro as fases do desenvolvimento de um programa:

1. Edição do Código Fonte- a escrita do código pelo programador é guardada em ficheiros de texto
com extensão .C

2. Compilação do Programa- não é mais do que a verificação se o programa contém uma sintaxe
correcta. Esta operação é realizada pelo Compilador, e os erros interrompem o processo de
compilação tendo o programador que os corrigir.
Depois de efectuada a compilação, o compilador cria um ficheiro objecto, com o nome igual ao
nome do programa mas de extensão .OBJ (em DOS) ou .O (em UNIX).

3. “Linkagem” dos objectos- É o Linker que torna o ficheiro objecto, obtido através do processo
de compilação em executável e através das bobliotecas (extensões .LIB (em DOS) e .a (em
UNIX).

4. Execução do programa- logo que a “linkagem” termine com sucesso temos disponível um
ficheiro executável, o qual podemos testar para verificar se ele faz o que era suposto fazer. Caso
isso não venha a acontecer é porque o programador se enganou.

Micaela Esteves & Filipe Neves 17/61


Linguagem de programação C

Esquema do processo acima descrito

Edição

1.1.1.1.1.1.1
Outros programas-fonte
Pré-processamento
a serem incluídos e directivas de
pré-processamento
( # ...)
Prog.C
expandido

Compilação

asm – palavra-chave acrescentada pelo


Prog.ASM compilador de C que indica que se trata de
instruções em Assembly
Programa-fonte
Em assembly Montagem Prog. 0bj Bibliotecas
(P - . ASM) (junção)

1.1.1.1.1.1.2
Bibliotecas
Linkagem de funções (*. 0bj)

Programa
PROG. EXE executável

Micaela Esteves & Filipe Neves 18/61


Linguagem de programação C

A linguagem C não possui instruções de entrada e saída de dados, logo, estas operações só serão possíveis
com a chamada explícita de funções. Estas funções são fornecidas em cada implementação da linguagem
(compilador).

O desenvolvimento e execução de programas depende do sistema operativo em que se esteja a trabalhar,


bem como do compilador utilizado.

Micaela Esteves & Filipe Neves 19/61


Linguagem de programação C

Estrutura de um programa

A estrutura de um programa em C obedece a um determinado conjunto de regras denominadas Sintaxe.


A sintaxe da linguagem C, diferencia letras maiúsculas e minúsculas ( é Case Sensitive). Assim "main",
"Main" e "MAIN" são termos distintos, podendo-se no entanto usar qualquer uma delas.

O aspecto de um programa C é modular e funcional, sendo o próprio programa principal uma função
main().
Esta forma de apresentação da linguagem facilita o desenvolvimento de programas, pois permite o
emprego de formas estruturadas e modulares.

Os delimitadores /* e */ identificam o inicio e o fim de comentários.


Os delimitadores { e } delimitam um bloco.

Todo o programa em C consiste numa ou mais funções. A única função que necessita de estar presente é a
função main( ), pois ela é a primeira função a ser chamada quando a execução do programa começa, mas
pode conter muitas outras.
Esquematicamente temos:

[ < definições de pré-processamento >]


[ < declarações/Protótipos de funções > ]

[<tipo>] main([ argc,argv ])


{
/* corpo da função principal, com declarações de
variáveis, comandos e funções */
}

[
[ < tipo >] fun ([< lista de parâmetros >])
[ < declaração de parâmetros > ]
{

/* corpo da função fun() com declaração das suas


funções variáveis e comandos */
}
]

Micaela Esteves & Filipe Neves 20/61


Linguagem de programação C

Anotações:
[ e ] - significa que o que está no seu interior é facultativo.
< e > - qualquer coisa que pode ser substituído
{ e } - inicializa e termina um bloco de instruções (corresponde ao begin e end)
As chavetas podem conter blocos de instruções elementares (chamados de expressões) ou outros
blocos de instruções. Assim, podem existir blocos de instruções aninhados um dentro de outro.
/* e */ - limitadores de comentários ou observações (podem aparecer em qualquer parte do programa)
fun - Função

Entradas e Saídas

A existência de poucas palavras chave implica a necessidade de funções pré-definidas. (Todo o


compilador C vem com uma biblioteca C padrão de funções que realizam as tarefas necessárias mais
comuns).

Uma das ideias mais interessantes na filosofia da linguagem C é a inexistência de comandos específicos
para entrada e saída de dados, sendo este processamento efectuado por funções pré-definidas e
armazenadas na biblioteca padrão "stdio.h", esta filosofia difere das outras linguagens de programação:
BASIC possui os comandos INPUT e PRINT ; FORTRAN, PASCAL e COBOL utilizam os comandos
READ e WRITE.

As funções não dependem do hardware


Deste modo, pode-se assim fugir ao máximo de dependência impostas pelas características de hardware,
o que aumenta consideravelmente a portabilidade da linguagem.

As funções podem ter várias fontes de entrada ou destinos de saída


O utilizador pode definir igualmente as suas funções de entrada e saída.

Algumas das funções de entrada e saída da biblioteca padrão "stdio.h" são:


• getchar () - permite a leitura de um caracter de uma entrada standard (teclado)
• putchar () - escreve um caracter numa saída standard (monitor)
• gets () - leitura de uma cadeia de caracteres numa entrada standard
• puts () - escreve uma cadeia de caracteres numa saída standard
• scanf () - entrada formatada de dados (corresponde ao READ do Pascal)
• printf ()- saída formatada de dados (corresponde ao WRITE do Pascal)

Micaela Esteves & Filipe Neves 21/61


Linguagem de programação C

NOTA:
As funções já definidas estão sempre seguidas de parênteses.

EXEMPLO:

#include <stdio.h>
main ()
{
printf ("Primeiro programa em C");
puts ("Primeiro programa em C");
}

Deste exemplo importa reter:


• A linha #include <stdio.h> não é C, mas uma directiva de pré-processamento, pois indica ao
compilador (mais propriamente ao pré-processador) que deverá adicionar ao processo de
compilação um ficheiro existente algures no disco do computador, chamado stdio.h, de forma a
que o compilador tenha acesso a um conjunto de informações sobre as funções que virá a utilizar.
• Estes ficheiros têm sempre a extensão .h pois não têm código mas apenas os cabeçalhos (headers)
das funções que representam. Por isso são habitualmente designados de header files.
• Logo, a linha #include<stdio.h> significa “adiciona o ficheiro stdio.h ao meu programa”
exactamente neste sítio.
• Como não é uma instrução C não é seguida de ponto e vírgula.

A função printf()

A função printf() é uma das muitas que pertencem à biblioteca stdio.h. Esta função converte, formata e
imprime dados, mediante as especificações presentes nos seus parâmetros de entrada. Nos seus
parâmetros de entrada, geralmente a função tem duas partes interligadas entre si:
- a primeira contém texto a imprimir à mistura com caracteres que influenciam a segunda :
formatam-na; isto é, especificam
- a segunda é uma lista de variáveis cujo conteúdo se pretende seja afixado no monitor.
A separação entre a primeira e a segunda é feita por uma vírgula e a separação entre as variáveis também
é feita por um conjunto de vírgulas. Assim sendo, poderemos dizer que a separação entre a primeira parte
e a segunda é feita pela primeira vírgula.
Sendo uma função recebe um conjunto de parâmetros de entrada, para , mediante a sua interpretação
poder realizar a tarefa acometida.
Nos seus argumentos, a função printf() tem o seguinte formato:

Micaela Esteves & Filipe Neves 22/61


Linguagem de programação C

printf(“<string de controlo>”, <argumento(s)> );

Notemos duas partes dos parâmetros de entrada:


a string à esquerda da (primeira) vírgula e o conjunto de argumentos após a (primeira) vírgula. No caso de
haver mais que um argumento, os que existirem serão separados por uma vírgula, sendo que nesse caso a
divisão é feita pela primeira vírgula. Por exemplo:

printf(“Com %f litros faz %d quilometros a %d km por hora”, num, var, h);

A string de controlo contém:


- Caracteres comuns: texto normal que queiramos que apareça no monitor
- Especificadores de conversão: não aparecem no monitor. Começam com % e acabam com um
caracter de conversão. Entre o % e o caracter de conversão pode haver:
i) sinal menos (-). Significa: encostar à esquerda o argumento convertido
ii) conjunto de dígitos que especificam a largura do(s) argumento(s)
iii) ponto final: separa largura do(s) argumento(s) relativamente ao próximo conjunto de dígitos
iv) o próximo conjunto de dígitos (a precisão): -nº de máximo de caracteres, se for uma string
-nº de casas decimais, se for um float
v) ljdkhvls

Micaela Esteves & Filipe Neves 23/61


Linguagem de programação C

Identificadores de variáveis, constantes e funções

Identificadores são nomes dados aos vários elementos de um programa, como variáveis, constantes e
funções. Os identificadores consistem de letras e dígitos e devem obedecer às seguintes regras:
• caracteres permitidos: alfabéticos, numéricos e sublinha _ (“underscore”)
• não começar por algarismo
• maiúsculas ≠ minúsculas => var1 ≠ Var1
• não permitidos nomes reservados: auto, break, case, char, const, continue, default, do, double,
else, extern, ...
• desaconselhado uso de acentuação: ã, ú, ..., ç, ...
• sublinha para separar palavras do mesmo nome
• comprimentos até 32 carateres
• nomes sugestivos
• evitar tudo em maiúsculas (usa-se em constantes)

Existem certas palavras reservadas, chamadas de palavras–chave, que têm significados padrões
predefinidos em C. Essas palavras-chave podem ser usadas apenas para seu propósito predefinido.
Exemplo de algumas palavras-chave.
auto break case char
const continue default
do double else extern

Note-se que, os identificadores devem ter relação com as variáveis, constantes ou funções, isto é, estas
devem ter nomes significativos a fim de tornar a programação de mais fácil compreensão e reduzir
comentários supérfluos. Por exemplo, para uma variável contadora deve escolher-se como identificador
cont, contador ou cont_1, ou algo semelhante.

Micaela Esteves & Filipe Neves 24/61


Linguagem de programação C

Tipos de dados

Em C existem os seguintes tipos de dados básicos:


• char - caracter 1 ( 1 byte)
• int - inteiro ( 2 ou 4 bytes; depende do computador)
• float - número de vírgula flutuante ( normalmente 4 bytes)
• double - número de vírgula flutuante de precisão dupla ( normalmente 8 bytes)

O número de bytes ocupados por cada tipo depende do sistema operativo. Em caso de dúvida pode usar-
se a função sizeof().

EXEMPLO:
Sizeof(int) dará o tamanho do inteiro para o computador em questão.

Qualificadores

Em C existem determinados qualificadores que, aplicados a um certo tipo de dados, originam alterações
no número de bytes ocupados e consequentemente na gama de valores representáveis.
As tabelas seguintes apresentam os qualificadores e os respectivos tipos de dados que os podem utilizar:
O qualificador de tamanho altera o número de bytes utilizados para representar o número e por sua vez a
gama de valores.

Qualificadores de tamanho Tipos onde se pode aplicar Resultado

short int 2 bytes

long int 4 bytes

long double 10 bytes

O qualificador de sinal apenas desloca a gama de valores. Por omissão, isto é, se nada em contrário fôr
especificado, os tipos de dados int e char têm implícito o qualificador signed. Tal significa que os dados
representáveis podem ser positivos e negativos (têm sinal).

Qualificador de sinal Tipos onde se pode aplicar

unsigned char

unsigned int

signed char

1
A designação deste tipo como char, não significa que seja destinado unicamente ao armazenamento de carateres imprimíveis ou
não imprimíveis, mas sim pelo facto de na sua representação interna o computador usar 1 byte para esse armazenamento. (Por
razões históricas os carateres usam 1 byte para serem representados). Na verdade o que as variáveis contêm são códigos. O que
estes códigos representam não é aqui mencionado. Um char só será apresentado como um caracter se for especificado
explicitamente que seja traduzido esse número no seu carater ASCII correspondente. Voltaremos ao assunto da formatação
(forma de escrever um número) mais tarde.

Micaela Esteves & Filipe Neves 25/61


Linguagem de programação C

signed int
A tabela seguinte representa o tamanho dos tipos de dados após a aplicação dos qualificadores de
tamanho e a gama de valores consequente:

Tipo Tamanho Gama


char 1 byte 0 - 255

short (int) 2 bytes 0 - 65.535

int 2 ou 4 bytes depende


long(int) 4 bytes 0 - 4.294.967.295

float 4 bytes n. d.

double 8 bytes n. d.

long double 10 bytes n. d.

A interpretação de um tipo de dados qualificado varia conforme o compilador C, apesar de existirem


algumas relações de bom senso. Assim, um short int pode ocupar menos memória ou a mesma quantidade
de memória que um int comum, mas nunca ocupará mais memória que um int comum.

Micaela Esteves & Filipe Neves 26/61


Linguagem de programação C

Turbo C

Gamas de valores

Inteiros

Inteiros com sinal

Como se declaram Gama de valores


char -128 a 127

short (int) -32.768 a +32.767

int -32.768 a +32.767

long (int) -2.147.483.648 a 2.147.483.647

Inteiros sem sinal

Como se declaram Gama de valores


unsigned char 0 a 255

unsigned short (int) 0 a 65.535

unsigned int 0 a 65.535


unsigned long (int) 0 a 4.294.967.295

Reais
Como se declaram Gama de valores
float ±3,4E-38 a ±3,4E+38

double ±1,7E-308 a ±1,7E+308


long double ±3,4E-4932 a ±3,4E+4932

Declaração de variáveis

Uma variável não é mais do que um nome que nós damos a uma determinada posição de memória
(endereços) para guardar/conter um valor de um determinado tipo.
O tipo que lhe está associado indica o nº de bytes que irão ser utilizados para guardar um valor nessa
variável.

Micaela Esteves & Filipe Neves 27/61


Linguagem de programação C

Ao declarar-se uma variável estamos a solicitar ao compilador para reservar espaço em memória para a
armazenar e esse espaço passará a ser referenciado através do nome da variável.

Micaela Esteves & Filipe Neves 28/61


Linguagem de programação C

Identificadores de Conteúdos das Endereços de memória Conteúdo das células


variáveis variáveis

Nome Ana
10001
10002 Ana

10003
Morada Leiria
10004 Leiria

10005

10006
Telefone 656869
10007 656869

10008 25

Idade 25 10009

Representação de um fragmento de memória


Exemplos de quatro identificadores de variáveis (RAM) correspondente aos quatro
usados num programa identificadores usados no programa

Representação esquemática da conversão de endereços simbólicos (identificadores) em endereços reais de memória


RAM

NOTA:
É uma prática tradicional do C, usar letras minúsculas para nomes de variáveis e maiúsculas para nomes
de constantes. Isto facilita a leitura do código.
As variáveis no C devem ser declaradas antes de serem usadas1. A forma geral da declaração de variáveis
é:
<tipo_da_variável> < lista_de_variáveis_separadas_por_vírgula>;

Tipo Variável ;

As variáveis da lista de variáveis terão todas o mesmo tipo e deverão ser separadas por vírgula.

1
Era essa a prática aquando da análise dum problema.

Micaela Esteves & Filipe Neves 29/61


Linguagem de programação C

Como o tipo “default ” do C é o int, quando vamos declarar variáveis int com algum dos qualificadores de
sinal ou tamanho, basta colocar o nome do qualificador. Assim basta declarar long para declarar um
long int.
[<qualificador de sinal>] [<qualificador de tamanho<] <tipo_variável> < lista_de_variáveis>;

EXEMPLO:
unsigned long int a, b, c;
unsigned long a, b, c;

São instruções equivalentes.

Por exemplo, as declarações


char ch, letra;
long count;
float pi;
long float num;

declaram duas variáveis do tipo char (ch e letra), uma variavel long int (count), duas variáveis reais: uma
float (pi) e outra um long float (num).

Onde Declarar as Variáveis?

main( )
{
Declaração de variáveis ß aqui

Instrução1;
Instrução2;
}

O primeiro lugar no qual se pode declarar variáveis é no início de um bloco de código. Estas variáveis são
chamadas locais e só têm validade dentro do bloco no qual são declaradas, isto é, só a função à qual ela
pertence sabe da existência desta variável, dentro do bloco no qual foram declaradas.

Micaela Esteves & Filipe Neves 30/61


Linguagem de programação C

O segundo lugar onde se pode declarar variáveis é na lista de parâmetros de uma função. Mais uma vez,
apesar de receberem valores externos, estas variáveis são conhecidas apenas pela função onde são
declaradas. Veja o programa abaixo:

#include <stdio.h>
int func1(int );
void main()
{
char condicao;
int i;
/* aqui viria o código da função main*/

func1(i);
/* etc ... */
return;
}

int func1(int j){


/* aqui viria o código da funcao
*/
}

As variáveis condição e i, só existem dentro de main(), isto é são variáveis locais de main().
A variável inteira j é um exemplo de declaração na lista de parâmetros de uma função (a função func1).
As regras que regem onde uma variável é válida chamam-se regras de escopo da variável. Há mais dois
detalhes que devem ser salientados:
• duas variáveis locais não podem ter o mesmo nome.
• duas variáveis locais, de funções diferentes, podem ter o mesmo nome sem perigo algum de
conflito.

Inicialização de variáveis

Podemos inicializar variáveis no momento de sua declaração ou posteriormente. Se o fizermos no


momento da declaração podemos usar a forma geral:
tipo_da_variável nome_da_variável = constante;

Micaela Esteves & Filipe Neves 31/61


Linguagem de programação C

, ;
Tipo variável variável

, constante =

Isto é importante pois quando o C cria uma variável ele não a inicializa. Isto significa que até que um
primeiro valor seja atribuído à nova variável ela tem um valor indefinido e que não pode ser utilizado para
nada. Nunca presuma que uma variável declarada vale zero ou qualquer outro valor conhecido.

POR EXEMPLO:
char ch='D';
char ch1 = ‘3’;
int count=0;
float pi=3.141;

NOTA:
Em C o sinal de igual, =, é o operador de atribuição.

Constantes

Em C, constantes referem-se a valores fixos guardados em memória que o programa não pode alterar, ou
seja que não podem ser alterados durante a execução do programa.

Os quatro tipos de constantes possíveis são:


• Constantes do tipo caracter;
• Constantes do tipo inteiro;
• Constantes do tipo real;
• Constantes do tipo simbólicas.

Constantes do tipo caracter

a) Caracter entre plicas


‘a’, ‘4’, ‘+’

b) Solução sequência de escape(\)

Micaela Esteves & Filipe Neves 32/61


Linguagem de programação C

Sequência O que faz ou imprime de facto


‘\b’ Retrocesso ("back")

‘\n’ Nova linha ("new line")

‘\t’ Tabulação horizontal ("tab")

‘\"’ Aspas

‘\'’ Apóstrofo

‘\0’ Nulo (0 em decimal)

‘\\’ Barra invertida

\’v’ Tabulação vertical

‘\a’ Sinal sonoro ("beep")

Constantes dos tipos básicos

No quadro seguinte mostra-se as constantes relativas aos tipos básicos do C:

Tipo de Dado Exemplos de Constantes

char 'b' '\n' '\0'


int 2 32000 -130

long int 100000 -467

short int 100 -30

unsigned int 50000 35678


float 0.0 23.7 -12.3e-10

Double 12546354334.0 -0.0000034236556

Constantes simbólicas

Uma constante simbólica é um nome que substitui uma sequência de caracteres. Uma constante simbólica
permite que um nome apareça no lugar de uma constante numérica, constante caracter ou uma constante
“string”. Quando um programa é compilado, cada ocorrência de uma constante simbólica é substituída
pela sua sequência de caracteres correspondente.

Uma constante simbólica define-se da seguinte forma:

#define <Nome_simbólico> <valor>

onde <nome_simbólico> representa um valor constante, normalmente escrito em letras maiúsculas.

EXEMPLO:

Micaela Esteves & Filipe Neves 33/61


Linguagem de programação C

#define PI 3.1415926

Esta instrução permite que todo o programa possa utilizar a palavra PI em vez do valor definido.

Operadores Aritméticos e de Atribuição

Operadores de atribuição

O operador de atribuição do C é o =, como já referido várias vezes. O que ele faz é pegar o valor à direita
e atribuir à variável da esquerda. Além disto ele devolve o valor que ele atribuiu.

EXEMPLO:
int a;
float p;
a=2;
p=1.5;

A operação a=2 atribui o valor 2 à variável inteira a, devolvendo o valor 2.


A operação p=1.5 atribui à variável real p o valor 1.5, devolvendo o valor 1.5.

Atribuições Múltiplas

C permite que se atribua o mesmo valor a muitas variáveis usando atribuições múltiplas num único
comando.

EXEMPLO:
atribuir o valor oito a x, y e z.

x = y = z = 8;

Ordem da atribuição

NOTA:
Em C todos os operadores devolvem o valor da operação efectuada, podendo este ser ou não ser utilizado.

Micaela Esteves & Filipe Neves 34/61


Linguagem de programação C

Operadores aritméticos

OPERADOR ACÇÃO

- Subtração

+ Adição

* Multiplicação

/ Divisão

% Resto ou Módulo da divisão inteira (não pode ser


usado nos tipos de ponto flutuante)

Tabela dos operadores aritméticos de C

O operador / (divisão) quando aplicado a variáveis inteiras, fornece o resultado da divisão inteira; quando
aplicado a variáveis em ponto flutuante fornece o resultado da divisão "real". O operador % fornece o
resto da divisão de dois inteiros. Assim seja o seguinte trecho de código:
int a = 17, b = 3;
int x, y;
float z = 17.0, z1, z2;
x = a / b;
y = a % b;
z1 = z / b;
z2 = a/b;
a = b^5;

ao final da execução destas linhas, os valores calculados seriam a = 243, x = 5, y = 2, z1 = 5.666666 e


z2 = 5.0.

Note que, na linha correspondente a z2, primeiro é feita uma divisão inteira (pois os dois operandos são
inteiros). Somente após efectuada a divisão é que o resultado é atribuído a uma variável float.

O C possui operadores unários e binários. Os unários agem sobre uma variável apenas, modificando ou
não o seu valor, e devolvem o valor final da variável. Os binários usam duas variáveis e devolvem um
terceiro valor, sem alterar as variáveis originais.

A soma é um operador binário pois pega duas variáveis, soma os seus valores, sem alterar as variáveis, e
devolve esta soma. Outros operadores binários são os operadores - (subtração), *, / e %.

O operador - (subtração), como troca de sinal é um operador unário que não altera a variá vel sobre a qual
é aplicado, pois ele devolve o valor da variável multiplicado por -1.

Micaela Esteves & Filipe Neves 35/61


Linguagem de programação C

Operador de Atribuição Composta

Um caso muito comum em qualquer processamento é operar-se uma variável e armazenar nesta o
resultado obtido. Na linguagem C pode utilizar-se uma forma alternativa de realizar o processamento
anterior, substituindo a fórmula:

<variável> = <variável> <operador> <expressão>

pela fórmula equivalente (atribuição composta):

<variável> <operador> = <expressão>

A utilização da atribuição composta torna o programa mais eficiente.

EXEMPLO:
Vamos supor que queríamos adicionar 3 à variável x.

Normalmente escreveríamos: x = x + 3;

Usando uma atribuição composta basta escrever: x += 3;

NOTA:
Quando se utilizam atribuições compostas, é absolutamente necessário que o operador fique
imediatamente junto ao sinal da atribuição.

EXEMPLO SIGNIFICADO

x += 1 x=x+1

y *= 2+3 y = y * (2+3)

a - = b+1 a = a - (b+1)

k /= 12 k = k / 12

r %= 2 r=r%2

Operador de Incremento e Decremento

Operadores ++ e --

Micaela Esteves & Filipe Neves 36/61


Linguagem de programação C

Estes operadores podem ser pré-fixados ou pós-fixados. A diferença é que quando são pré-fixados eles
incrementam e devolvem o valor da variável já incrementada. Quando são pós- fixados eles devolvem o
valor da variável sem o incremento e depois incrementam a variável.

Operador significado Exemplo Equivalente Acção

++ Incrementa 1 X++ ou ++X X=X+1 Soma 1 ao seu operando

-- Decrement a 1 X-- ou --X X=X -1 Subtrai 1 ao seu operando

Diferenças entre ++x e x++

Equivalente a Equivalente a

y = x++ y = ++x
1º - y = x 1º - x++
2º - x++ 2º - y = x

Acontecem duas coisas por esta ordem: Acontecem duas coisas por esta ordem:

O valor de x é atribuído a y O valor de x é incrementado de uma unidade


O valor de x é incrementado de uma unidade O valor de x é atribuído a y

EXEMPLO:
int x, y = 5;
x = y++;

o resultado desta operação é x a valer 5 e o y a valer 6.

Se fosse
x = ++y;
teríamos x a valer 6 e y a valer também 6.

Operadores Relacionais e Lógicos

Os operadores relacionais realizam comparações entre variáveis. São eles:

Micaela Esteves & Filipe Neves 37/61


Linguagem de programação C

Operador Ação
> Maior do que

>= Maior ou igual a

< Menor do que

<= Menor ou igual a

== Igual a

!= Diferente de

Os operadores relacionais devolvem verdadeiro (!=0) ou fals o (0).

NOTA :
Em C não existe nenhum tipo específico de dados para armazenar valores lógicos, como em Pascal que
existe o tipo Boolean para receber os valores True e False.

Em C o valor lógico FALSO é representado por 0 (zero) e tudo aquilo que seja diferente de zero
representa o valor lógico VERDADEIRO.

Para verificar o funcionamento dos operadores relacionais, execute o seguinte programa :

/* Este programa ilustra o funcionamento dos operadores


relacionais. */
#include <stdio.h>
int main()
{
int i, j;
printf("\nEscreva dois numeros inteiros: ");
scanf("%d%d", &i, &j);
printf("\n%d == %d é %d\n", i, j, i==j);
printf("\n%d != %d é %d\n", i, j, i!=j);
printf("\n%d <= %d é %d\n", i, j, i<=j);
printf("\n%d >= %d é %d\n", i, j, i>=j);
printf("\n%d < %d é %d\n", i, j, i<j);
printf("\n%d > %d é %d\n", i, j, i>j);
return(0);
}
O resultado dos operadores relacionais é sempre igual a 0 (falso) ou 1 (verdadeiro).

Micaela Esteves & Filipe Neves 38/61


Linguagem de programação C

Operadores Lógicos

São designados por operadores lógicos, aqueles que efectuam operações de conjunção (E), disjunção(OU)
ou negação (NÃO) entre expressões de valor lógico.
Os operadores lógicos são:

OPERADOR Significado

&& AND ( E lógico)

|| OR ( OU lógico)

! NOT ( Negação lógica)

Usando os operadores relacionais e lógicos podemos realizar uma grande gama de testes. A tabela-
verdade destes operadores é dada a seguir:

p q p AND q p OR q

Falso Falso Falso Falso


Falso Verdadeiro Falso Verdadeiro

Verdadeiro Falso Falso Verdadeiro


Verdadeiro Verdadeiro Verdadeiro Verdadeiro

O programa a seguir ilustra o funcionamento dos operadores lógicos.

#include <stdio.h>
int main()
{
int i, j;
printf("informe dois números(cada um sendo 0 ou 1): ");
scanf("%d%d", &i, &j);
printf("%d AND %d é %d\n", i, j, i && j);
printf("%d OR %d é %d\n", i, j, i || j);
printf("NOT %d é %d\n", i, !i);
}

EXEMPLO:
No trecho de programa abaixo a operação j++ será executada, pois o resultado da expressão lógica é
verdadeiro:
int i = 5, j =7;
if ( (i > 3) && ( j <= 7) && ( i != j) ) j++;
V AND V AND V = V

Micaela Esteves & Filipe Neves 39/61


Linguagem de programação C

NOTA:
Os operadores relacionais && e || são operadores binários, enquanto o operador ! é um operador unário,
sendo aplicado apenas a uma única condição ou expressão.

Expressões

Expressões são combinações de variáveis, constantes e operadores. Quando se escreve uma expressão tem
de se ter em consideração a ordem pela qual os operadores são executados, conforme a tabela de
precedências da linguagem C.
Exemplos de expressões:
Anos=Dias/365.25;
i = i+3;
c= a*b + d/e;
c= a*(b+d)/e;

Conversão de tipos em expressões

Quando constantes e variáveis de tipos diferentes são misturadas numa expressão, elas são convertidas a
um mesmo tipo. O compilador C converte todos os operandos no tipo do maior operando ( o que é
chamado de promoção de tipo). Isso é feito operação por operação.
O C avalia uma expressões onde se tem variáveis de tipos diferentes o compilador verifica se as
conversões são possíveis. Se não são, ele não compilará o programa, dando uma mensagem de erro. Se as
conversões forem possíveis ele as faz, seguindo as seguintes regras:
Todos os chars e short ints são convertidos para ints. Todos os floats são convertidos para doubles.

1. Para pares de operandos de tipos diferentes: se um deles é long double o outro é convertido para
long double; se um deles é double o outro é convertido para double; se um é long o outro é
convertido para long; se um é unsigned o outro é convertido para unsigned.

Micaela Esteves & Filipe Neves 40/61


Linguagem de programação C

EXEMPLO:
char ch;
int i;
float f;
double d;

result = (ch / i) + (f * d) – (f + i);

int double float

int double float

double

Tabela de Precedências do C

Esta é a tabela de precedência dos operadores em C.

Maior precedência () [] ->


! ~ ++ -- . -(unário) (cast) *(unário) &(unário)
sizeof
*/%
+-

<< >>
<<= >>=
== !=

&
^
|
&&
||
?

= += -= *= /=
Menor precedência ,

Micaela Esteves & Filipe Neves 41/61


Linguagem de programação C

Modeladores (Casts)

Um modelador é aplicado a uma expressão. Ele força a mesma a ser de um tipo especificado. Sua forma
geral é:
(tipo)expressão

UM EXEMPLO:

#include <stdio.h>
int main ()
{
int num;
float f;
num=10;
f=(float)num/7;
printf ("%f",f);
return(0);
}

Se não tivéssemos usado o modelador no exemplo acima o C faria uma divisão inteira entre 10 e 7. O
resultado seria 1 (um) e este seria depois convertido para float mas continuaria a ser 1.0. Com o
modelador temos o resultado correcto.

Funções de entrada e Saída

O printf

Até aqui usámos a função printf de uma forma simplificada para imprimirmos caracteres no monitor.
Nesta secção faremos uma descrição mais completa das suas potencialidades, ainda que de forma não
exaustiva. Esta função converte, formata e imprime os seus argumentos no “standard output” (leia-se
monitor, para o efeito) sob controlo duma string de controlo. Podemos dizer que a função printf
obedece ao seguinte formato:

printf (“ ”, );

string de controlo variáveis a imprimir

Micaela Esteves & Filipe Neves 42/61


Linguagem de programação C

Por sua vez, a string de controlo pode conter caracteres comuns e especificadores de conversão.
Os caracteres comuns são os caracteres que queremos que sejam imprimidos no monitor, tal como os
escrevemos na string de controlo.
Os especificadores de conversão começam com o símbolo % e acabam com um dos seguintes caracteres,
chamados caracteres de conversão: d, o, x, u, c, s, e, f ou g. Entre o caracter % e o caracter de conversão
pode haver, por esta ordem:
1. o sinal menos (-): significa encostar à esquerda a variável a imprimir,
2. 0 (zero): preenche com zeros,
3. um conjunto de dígitos que especificam a largura do campo constituído pela variável. O número
convertido será impresso num campo com pelo menos esta largura espeificada ou maior se
necessário. Se o argumento convertido tiver menos caracteres que a largura especificada, será
encostado à direita (a menos que se tenha especificado para encostar à esquerda). O espeço
restante contém normalmente espaços em branco ou zeros, se a largura do campo foi especificada
com um zero no início.
4. um ponto (.): separa a largura do campo do próximo conjunto de algarismos,
5. o próximo conjunto de algarismos: especifica a precisão, isto é: o nº de casas decimais,
tratando-se de uma variável tipo float; ou o número máximo de caracteres, tratando-se de uma
string.
6. um modificador de comprimento (l-long; h-short)
7. o caracter de conversão, com o seguinte significado:
i. d: inteiro decimal
ii. o: inteiro octal
iii. x: inteiro hexadecimal
iv. u: unsigned decimal
v. c: caracter
vi. s: string
vii. f: float. o será considerado um float ou um double e convertido para a notação decimal da
forma [-] mmm.nnnnn. m é a parte inteira da variável. O número de ns é indicado pela
precisão. Por omissão é seis.
viii. e: o resultado será imprimido na notação científica: [-]m.nnnnnnE[+|-]xx. O que está
entre parêntesis rectos é opcional. m é a mantissa, n as casas decimais. Por omissão são
seis.
ix. g: usa %e ou %f (o que for mais curto). Os zeros não significativos não são impressos.

Se o caracter seguinte ao % não for um caracter de conversão, esse caracter será impresso, como caracter
comum.

Micaela Esteves & Filipe Neves 43/61


Linguagem de programação C

EXEMPLO:

printf(“% – 0 6 . 3 l d ”, a );

encosta à esquerda
preenche com zeros
largura do campo
nº de casas decimais
modificador de tamanho (long)
caracter de conversão (inteiro (decimal))
variável a imprimir, (declarada como inteiro)

EXEMPLO:
Supomos uma variável do tipo string com o conteúdo “ola”.
A tabela abaixo mostra o resultado no monitor em função da string de controlo.

String de controlo Resultado no monitor


“%6s:” _ _ _ola:
“%-6s:” ola_ _ _:
“%6.2s:” _ _ _ _ol:
“%-6.2s:” ol_ _ _ _:
“%.2s:” ol:

O scanf

A função scanf é análoga à printf, fornecendo muitas das mesmas facilidades de conversão, mas no
sentido oposto; isto é, recebe dados em vez de os imprimir. Antes de mais esta função faz parar o
programa, e este só prossegue na execução das restantes instruções após introduzidos os dados de entrada
pretendidos e premida a tecla Enter. Scanf lê dados do input standard, (leia-se teclado, para o efeito)
interpreta-os de acordo com o formato especificado pela string de controlo e guarda os resultados nas
variáveis mencionadas no respectivo local.

scanf (“ ”, );

string de controlo variáveis a imprimir

Micaela Esteves & Filipe Neves 44/61


Linguagem de programação C

O uso da string de controlo é análogo ao da string de controlo da função printf. Já o nome da(s)
variável(eis) deverá ser ser precedido pelo caracter &. Futuramente abordaremos o significado deste
símbolo no seu contexto.

EXEMPLO
int a;
scanf(“%d”, &a);

Esta última instrução pára a execução do programa ficando à espera da introdução dum dado pelo teclado,
interpreta-o como sendo um inteiro decimal e guarda-o na variável de nome a.

Poderemos usar a mesma instrução para receber do teclado mais que uma variável. Nesse caso,
deveremos especificar tantos caracteres de especificação quantas as variáveis e no teclado espaçar as
variáveis por espaços.

EXEMPLO
scanf(“%d %f”, &i, &y);

Esta última instrução pára a execução do programa ficando à espera da introdução de dados pelo teclado.
A cada espaço encontrado passa para a variável seguinte. Neste caso atribui o conteúdo antes dum espaço
à variável i formatando-a como um inteiro decimal e o conteúdo após o espaço à variável y formatado
como um float.

Micaela Esteves & Filipe Neves 45/61


Linguagem de programação C

ESTRUTURAS DE SELECÇÃO

if

O comando if representa uma tomada de decisão do tipo "SE isto ENTÃO aquilo". A sua forma geral é:
if (condição)
bloco de instruções;

A condição do comando if é uma expressão que será avaliada. Se o resultado for zero, o bloco de
instruções não será executado. Se o resultado for qualquer valor diferente de zero o bloco de instruções
será executado. O bloco de instruções pode ser um bloco de código ou apenas uma instrução.
O caso do bloco de instruções ser uma única instrução, não é necessário o uso de chavetas a delimitar
esssa instrução. No entanto se o bloco de código contiver mais que uma instrução é necessário o uso de
chavetas a delimitá-la.

EXEMPLO:
#include <stdio.h>
void main (void)
{
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\nAcertou!\n");
printf ("O numero e igual a 10.");
}
if (num<10)
printf ("\n\nO numero e menor que 10");

return;
}

Micaela Esteves & Filipe Neves 46/61


Linguagem de programação C

No programa acima a expressão num>10 é avaliada e devolve um valor diferente de zero, se verdadeira,
e zero, se falsa.
No exemplo, se num for maior que 10, será escrito no ecrã a frase:

O número e maior que 10


Repare-se que, quando queremos testar igualdades usamos o operador == e não =. Isto porque o operador
= representa uma atribuição. Pode parecer estranho à primeira vista, mas se escrevêssemos

if (num=10) /* Isto esta errado para aquilo que pretendemos */

o compilador iria atribuir o valor 10 à variável num e a expressão num=10 iria devolver o 10, fazendo
com que o valor de num fosse modificado e consequentemente a declaração seria sempre executada. Este
problema gera erros frequentes entre iniciantes e, portanto, muita atenção deve ser tomada.

O else

Podemos pensar no comando else como sendo um complemento do comando if. O comando if completo
tem assim a seguinte forma geral:

if (condição)
instrução_1;
else
instrução_2;

A expressão da condição será avaliada. Se ela for diferente de zero a instrução_1 será executada. Se for
zero a instrução_2 será executada. Mas é com base na avaliação da mesma condição que será executada
uma das duas declarações; ou a que está dentro do if, ou a que está dentro do else.
É importante nunca esquecer que, quando usamos a estrutura if - else, estamos a garantir que uma das
duas declarações será executada. Nunca serão executadas as duas e sempre se executará uma delas.
Note-se também que no pedaço de código apresentado não existem delimitadores de início e fim (as
chavetas { } ) para cada instrução. Neste caso não foram necessários pois foram usadas instruções
simples. Caso uma das instruções fosse substituída por duas ou mais, seria obrigatório o uso das chavetas
delimitadoras, como se verá a seguir.
O programa anterior pode ser alterado utilizando-se a estrutura if –else, o que resulta no seguinte.

Micaela Esteves & Filipe Neves 47/61


Linguagem de programação C

EXEMPLO:
#include <stdio.h>
void main (void)
{
int num;
printf ("Digite um numero: ");
scanf ("%d",&num);
if (num==10)
{
printf ("\n\nAcertou!\n");
printf ("O numero e’ igual a 10.\n");
}
else
{
printf ("\n\nErrou!\n");
printf ("O numero e diferente de 10.\n");
}
return;
}

O if-else-if

A estrutura if – else - if é apenas uma extensão da estrutura if-else. A sua forma geral pode ser escrita
assim:

if (condição_1)
instrução_1;
else
if (condição_2)
instrução_2;
else
if (condição_3)
instrução_3;
.
.
else
if (condição_n)
instrução_n;

Micaela Esteves & Filipe Neves 48/61


Linguagem de programação C

A estrutura acima funciona da seguinte maneira: o programa começa a testar as condições, começando
pela condição_1 e continua a testar até que encontre na condição uma expressão cujo resultado seja
diferente de zero. Nesse caso será executada a declaração correspondente 1 . Só uma declaração será
executada, ou seja; só executa a declaração equivalente à primeira condição que for diferente de zero.

EXEMPLO:

#include <stdio.h>
void 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\nAcertou!\n");
printf ("O numero e’ igual a 10.");
}
else
printf ("\n\nO numero e’ menor que 10");
return;
}

O Comando switch

O comando if - else e o comando switch são os dois comandos de tomada de decisão. Sem dúvida
alguma, o mais importante dos dois é o if, mas o comando switch tem aplicações valiosas.
Não esquecer que devemos usar o comando certo no local certo. Isto assegura um código limpo e de fácil
entendimento. Vejamos então as características do comando switch.

1
Por declaração, entenda-se aqui que poderá ser uma instrução simples ou um conjunto de instruções. Neste último caso, não
esquecer o uso das chavetas delimitadoras.

Micaela Esteves & Filipe Neves 49/61


Linguagem de programação C

O comando switch é próprio para comparar o valor de um inteiro em relação a conjunto de constantes
inteiras pré-estabelecidas e fazer a execução do programa saltar directamente para a única declaração que
executará, sem ter de testar todas as condições intermédias. A sua forma geral é:

switch (expressão inteira)


{
case constante_1:
instrução_1;
break;
case constante_2:
instrução _2;
break;
.
.
.
case constante_n:
instrução _n;
break;
default :
instrução_default;
break;
}

Podemos fazer uma analogia entre o switch e a estrutura if-else-if apresentada anteriormente. O switch
testa a variável e executa a declaração cujo case corresponda ao valor actual da variável. A declaração
default é opcional e será executada apenas se a variável, que está sendo 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. No entanto, se não for utilizado, as restantes cases, serão
todas executadas, o que nas maior parte das vezes não interessa.
Veremos agora um exemplo de uso do comando switch.

Micaela Esteves & Filipe Neves 50/61


Linguagem de programação C

EXEMPLO:

#include <stdio.h>
void main (void)
{
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;
}

Micaela Esteves & Filipe Neves 51/61


Linguagem de programação C

CICLOS

Inicialmente considerámos um programa como uma sequência linear de instruções a serem executadas.
No capítulo anterior analisámos situações em que certas instruções podem ou não serem executadas,
segundo se verifiquem ou não certas condições. O fluxo do programa deixou assim de ser linear. Vamos
neste capítulo abordar um conjunto de estruturas que alteram também a linearidade do fluxo do programa,
desta feita em situações em que existe carácter repetitivo dum certo conjunto de instruções bem definido.

while()

A estrutura while, também chamada ciclo while, faz executar um conjunto de instruções, chamado bloco
de instruções, enquanto uma determinada condição for verdadeira. A sua sintaxe é a seguinte:

while(condição)
{
instrução_1;
instrução_2;
instrução_3; bloco de instruções ou corpo da estrutura while
.......
instrução_n;
}

O seu funcionamento pode ser descrito da seguinte forma:


• o programa vem normalmente a ser executado instrução a instrução
• ao chegar à estrutura while a condição entre parêntesis é avaliada
• se o resultado for falso o ciclo termina, não sendo executada nenhuma das instruções do
bloco de instruções
• se o resultado for verdadeiro as instruções serão executadas uma a uma
• no fim da execução da última instrução do bloco, o fluxo do programa regressa ao topo
avaliando a condição entre parêntesis e o processo repete-se.

Dentro do bloco de instruções deverá haver, uma instrução que a certa altura altere o valor da condição;
caso contrário teríamos um ciclo infinito, pois a condição seria sempre verdadeira, caso o fosse na
primeira vez que o bloco fosse executado.
A cada execução do bloco chama-se iteração.

Micaela Esteves & Filipe Neves 52/61


Linguagem de programação C

Se o bloco de instruções for constituído por uma única instrução, não será necessário o uso de chavetas
como delimitadoras de início e fim de bloco.
Nota: o cabeçalho da estrutura while, não termina com ponto e vírgula, à semelhança das estruturas if() e
switch()

EXEMPLO:
Escrever um programa que coloque no écran os primeiros dez números inteiros, mudando de linha entre
cada número:

#include <stdio.h>
void main(void)
{ int i;
i=1;
while(i<=10)
{
printf(“%d\n”, i);
i=i+1;
}
}

Que aconteceria se não se tivessem usado parêntesis no ciclo while?


Teríamos um ciclo infinito! Porquê?

EXEMPLO:
Escrever um programa que ponha no monitor a tabuada do 5, alinhada como em baixo à direita.

5* 1= 5
#include <stdio.h>
5* 2=10
void main(void) 5* 3=15
{ int n=1; 5* 4=20
while(n<=10) 5* 5=25
{ 5* 6=30
printf(“5*%2d=%2d\n”, n, 5*n); 5* 7=35
5* 8=40
n++;
5* 9=45
}
5*10=50
}

Micaela Esteves & Filipe Neves 53/61


Linguagem de programação C

for()

Esta estrutura tem a seguinte sintaxe:

1 4
for (inicialização(ões); condição; pós-instrução(ões))
{ 2
instrução_1;
3
instrução_2;
instrução_3; bloco de instruções ou corpo da estrutura for
.......
instrução_n;
}

O seu funcionamento pode ser descrito da seguinte forma:


• o programa vem normalmente a ser executado instrução a instrução
• ao chegar ao for:
• são executadas uma única vez as instruções correspondentes a inicializações
• é avaliada a condição
• se o resultado for falso o ciclo termina, não sendo executada nenhuma das instruções do
bloco de instruções
• se o resultado for verdadeiro as instruções serão executadas uma a uma
• no fim da execução da última instrução do bloco, são executadas as instruções
correspondentes às pós-instruções
• é avaliada a condição e o processo repete-se.

EXEMPLO:
O anterior programa de escrever na vertical os dez primeiros números inteiros, feito com um ciclo while,
pode assim escrever-se usando o for.
...
int i;
for(i=1; i<=10; i=i+1)
{
printf(“%d\n”,i);
}
Neste caso o ciclo for só tem uma instrição no seu bloco de instruções; as chavetas seriam dispensadas,
por esse motivo.

Micaela Esteves & Filipe Neves 54/61


Linguagem de programação C

EXEMPLO:
Escrever um programa que calcule a soma e o produto dos dez primeiros números inteiros.
...
int soma;
int produto;
for(soma=0, n=1, produto=1; n<=10; n=n+1)
{
soma=soma+n;
produto=produto*n
}
printf(“adicoes: %d; multiplicacoes: %d”, soma, produto);

Equivalência entre o ciclo for e o ciclo while

Se observarmos com atenção as diferenças entre um ciclo for e um ciclo while, podemos verificar que um
pode ser substituído pelo outro de acordo com as equivalências a seguir ilustradas.

for(inicializações; condição; pós-instrução) inicializações;


{ while(condição)
instrucao_1; {
instrucao_2: instrucao_1;
equivalentes
... instrucao_2:
instrucao_n; ...
} instrucao_n;
pós-instrução
}

do ... while

O ciclo do ... while é muito semelhante aos anteriores, excepto que neste a condição é verificada no fim
do bloco de instruções, o que significa que qualquer que seja o valor da condição, é sempre executado o
conjunto de instruções que o constituem.
Este ciclo tem a seguinte sintaxe:
do
{
instruções;
}
while(condição)};

Micaela Esteves & Filipe Neves 55/61


Linguagem de programação C

Uma vez que executa sempre pelo menos uma vez o bloco de instruções, é uma estrutura muito
apropriada à protecção de dados de entrada. O seguinte exemplo mostra uma aplicação deste ciclo em tal
situação.

EXEMPLO:

Programa que apresenta um menu com as opções Clientes, Fornecedores , Encomendas e Sair, permitindo
ao utilizador escolher uma delas. Só sai do ciclo quando escolher Sair.
#include <stdio.h>
#include <conio.h>
void main(void)
{ char opcao;
do
{ clrscr();
printf("\t MENU PRINCIPAL\n");
printf("\n\n\t\tClientes");
printf("\n\n\t\tFornecedores");
printf("\n\n\t\tEncomendas");
printf("\n\n\t\tSair");
printf("\n\n\nA sua opcao e': ");
scanf("%c",&opcao);
fflush(stdin);
switch(opcao)
{ case 'c':
case 'C':
printf("A sua opcao foi CLIENTES\n");
break;
case 'f':
case 'F':
printf("A sua opcao foi FORNECEDORES\n");
break;
case 'e':
case 'E':
printf("A sua opcao foi ENCOMENDAS\n");
break;
case 's':
case 'S':
break;
default:
printf("opcao INVALIDA!!!\n");
} /* fecha switch */
getch();
} /* fecha ciclo */
while(opcao != 's' && opcao != 'S');
} /* fecha main() */

Micaela Esteves & Filipe Neves 56/61


Linguagem de programação C

Neste programa aparece pela primeira vez a função fflush(), utilizando como parâmetro de entrada
stdin. É uma função que limpa os caracteres que existam no buffer do teclado. Doravante utulizá-la-emos
sempre que utilizemos a função scanf().

break

à semelhança do que já conhecemos da instrução break utilizada na estrutura switch(), também quando
utilizada numa estrutura cíclica, o que faz é terminar a execução completa de toda a estrutura, isto é, não
será executada mais nenhuma instrução do ciclo, passando a ser executada a primeira instrução a seguir à
chaveta de fecar o ciclo.

continue

A instrução cotinue usada dentro dum ciclo é semelhante à break, excepto que em vez de terminar todo o
ciclo só termina a iteração em que se encontra. Isto é; não executa mais nenhuma instrução do bloco de
instruções, mas vai de novo testar a condição e se ela for verdadeira, continuará a executar o bloco de
instruções.

Ciclos encadeados

Chama-se ciclo encadeado à situação de se ter um ciclo dentro de outro ciclo.


Comecemos com o problema de querer fazer um programa que escreva o seguinte no monitor:

1
1 2
1 2 3
1 2 3 4
...
1 2 3 4 5 6 7 8 9 10

Como se constata existem dois padrões de repetição. Por um lado há dez linhas a imprimir, mas por outro
em cada linha há também um padrão a repetir, embora dependendo de linha para linha, pois enquanto na
primeira só um número é escrito, na última são dez.
Um programa solução seria:

Micaela Esteves & Filipe Neves 57/61


Linguagem de programação C

int i, j; /* i conta as linhas, j conta os números em cada linha*/


for(i=1; i<=10; i++ )
{
for(j=1; j<=i; j++)
printf(“%d”, j);
printf(“\n”);
}

No caso do uso de ciclos encadeados, há a notar que um ciclo não se pode estender para além do ciclo a
que pertence, isto é, se está dentro doutro, terá de estar completamente dentro do outro.
Um ciclo interno pode alterar as variáveis do externo e vice-versa.

Exemplos de ciclos infinitos

while(1) for( ; ; ) do{ instrução}


instrução; instrução; while(1)}

Quando no ciclo for não é colocada qualquer condição, tudo se passa como se lá estivesse uma condição
verdadeira.
Como se termina então um ciclo infinito? Em programação termina-se colocando no seu bloco de
instruções a avaliação de uma condição seguida duma instrução break.

Micaela Esteves & Filipe Neves 58/61


Linguagem de programação C

FUNÇÕES
ADENDA

Quanto à passagem de parâmetros, as funções podem ter quatro configurações, conforme passem ou não
parâmetros de entrada ou de saída. Assim, poderíamos agrupá-las em quatro “configurações”:

Devolve parâmetro? Recebe parâmetros? Cabeçalho da definição da função com nome nome_funcao, viria:
Não Não void nome_funcao (void)

Não Sim void nome_função (<declaração de variáveis>)

Sim Não <tipo_devolvido> nome_funcao (void)


Sim Sim <tipo_devolvido> nome_funcao (<declaração de variáveis>)

<declaração de variaveis>

Neste campo, usam-se (declaram-se!) variáveis quando esta função recebe valores da função que chama
esta.
Se porventura, esta função receber valores unicamente pelo teclado, ou não receber qualquer valor (nem
por teclado, nem da função que a chama), usa-se void.
A função que chama esta poderá ser a função main(), ou outra qualquer, já que qualquer função pode
chamar qualquer função.

<tipo devolvido>

Menciona-se aqui um tipo de dados quando esta função devolve um valor à função que chama esta.
Se porventura esta função “devolver” valores unicamente para o monitor (o que não costuma chamar-se
“devolver”), ou se não devolver qualquer valor para a função que a chamou, usa-se “void”.

Nota: Quando se diz devolver valores para a função que chama esta, estamos sempre a ter em mente a
instrução return.
Resumindo… O uso da instrução return requer que neste campo se mencione um tipo de dados.

EXEMPLOS PARA AS QUATRO SITUAÇÕES POSSÍVEIS

Situação 1
Definição duma função que recebe do teclado dois valores, os soma e imprime o resultado.
void funcao(void)
{ float a, b, c;
scanf(“%d%d”, &a, &b);
c=a+b;
printf(“%f”, c);
}

Micaela Esteves & Filipe Neves 59/61


Linguagem de programação C

Poderia ser incluída no seguinte programa (com declaração e chamada a esta função acabada de definir).

#include <stdio.h>
void funcao(void); //declaracao
void main (void)
{
funcao(); //chamada
}

Situação 2

Definição duma função que recebe da função chamadora dois valores, os soma e imprime o
resultado.

void funcao(float a, int b)


{ float c;
c=a+b;
printf(“%f”, c);
}

Poderia ser incluída no seguinte programa (com declaração e chamada a esta função acabada de definir).
#include <stdio.h>
void funcao(float, int); //declaracao
void main (void)
{ float a, b;
scanf(“%d%d”, &a, &b); //chamada
funcao(a, b);
}

Situação 3
Definição duma função que recebe do teclado dois valores, os soma e devolve o resultado.

float funcao(void)
{ float a, b, c;
scanf(“%d%d”, &a, &b);
c=a+b;
return c;
}

Poderia ser incluída no seguinte programa (com declaração e chamada a esta função acabada de definir).
#include <stdio.h>
float funcao(void); //declaracao
void main (void)

Micaela Esteves & Filipe Neves 60/61


Linguagem de programação C

{ float z;
z=funcao(); //chamada
printf(“%f”, z);
}

Situação 4

Definição duma função que recebe dois valores, os soma e devolve o resultado.

float funcao(float a, int b)


{ float c;
c=a+b;
return c;
}

Poderia ser incluída no seguinte programa (com declaração e chamada a esta função acabada de definir).
#include <stdio.h>
float funcao(float a, int b); //declaracao
void main (void)
{ float x, y, z;
scanf(“%d%d”, &x, &y);
z=funcao(); //chamada
printf(“%f”, z);
}

Micaela Esteves & Filipe Neves 61/61