You are on page 1of 179

Informtica

Linguagem de Programao I

Ricardo Reis Pereira

3a edio
Fortaleza
2013

Qumica

Cincias
Biologia
Biolgicas

Artes
Artes
Plsticas

Informtica

Fsica

Matemtica

Pedagogia

Copyright 2013. Todos os direitos reservados desta edio UAB/UECE. Nenhuma


parte deste material poder ser reproduzida, transmitida e gravada, por qualquer meio
eletrnico, por fotocpia e outros, sem a prvia autorizao, por escrito, dos autores.

Presidenta da Repblica
Dilma Vana Rousseff
Ministro da Educao
Aloizio Mercadante
Presidente da CAPES
Jorge Almeida Guimares
Diretor de Educao a Distncia da CAPES
Joo Carlos Teatini de Souza Climaco
Governador do Estado do Cear
Cid Ferreira Gomes

Designer Instrucional
Laurisa Nutting
Coordenadora Editorial
Rocylnia Isidio
Projeto Grfico e Capa
Roberto Santos
Ilustrador
Mikael Baima
Diagramador
Francisco Jos da Silva Saraiva

Reitor da Universidade Estadual do Cear


Jos Jackson Coelho Sampaio
Pr-Reitora de Graduao
Marclia Chagas Barreto
Coordenador da SATE e UAB/UECE
Francisco Fbio Castelo Branco
Coordenadora Adjunta UAB/UECE
Elosa Maia Vidal
Diretor do CCT/UECE
Luciano Moura Cavalcante
Coordenadora da Licenciatura
em Informtica
Francisco Assis Amaral Bastos
Coordenadora de Tutoria e Docncia
em Informtica
Maria Wilda Fernandes

Secretaria de Apoio s Tecnologias Educacionais


Av. Paranjana, 1700 - Campus do Itaperi - Fortaleza - Cear
(85) 3101-9962

Sumrio
Apresentao.................................................................................................5
Parte 1 - Introduo Programao de Computadores...............7
Captulo 1 - Fundamentos........................................................................9
1. Introduo Programao de Computadores.......................................9
2. A Linguagem Pascal.............................................................................11
3. Utilizando um Compilador Pascal........................................................12
4. Elementos Essenciais da Linguagem Pascal......................................16
4.1. Palavras Reservadas e Identificadores.........................................16
4.2. Estrutura Bsica de um Programa Pascal....................................17
4.3. Variveis........................................................................................19
4.4. Constantes....................................................................................22
4.5. Operadores e Expresses............................................................24
4.6. Comandos de Entrada e Sada.....................................................28
4.7. Tomando Decises........................................................................31
4.8. Utilizando Laos............................................................................36
4.9. Funes e Procedimentos............................................................44
5. Estudos de Caso..................................................................................51
5.1. Converso Celsius em Fahrenheit................................................51
5.2. Anlise do IMC..............................................................................52
5.3. Maior de Trs Valores...................................................................53
5.4. Ordenao de Trs Nmeros........................................................54
5.5. Somando Quadrados....................................................................55
5.6. Somatrio Condicional..................................................................56
5.7. Nmeros Primos...........................................................................57

Captulo 2- Strings e Arrays...................................................................61


1. Caracteres e Strings............................................................................61
1.1. Caracteres....................................................................................61
1.2. Strings Curtas e Longas...............................................................64
1.3. Operaes com Strings................................................................65
2. Arrays...................................................................................................73
2.1. Arrays Unidimensionais.................................................................74
2.2. Arrays Multidimensionais..............................................................76
2.3. Arrays Dinmicas..........................................................................78
3. Estudos de Caso..................................................................................81
3.1. Palndromos Numricos................................................................81
3.2. Ordenao por Seleo................................................................83
3.3. Hiper Fatorial.................................................................................84

Parte 2 - Tipos de Dados Personalizados........................................91


Captulo 3 - Tipos de Dados Personalizados..................................93
1. Definindo Novos Tipos.........................................................................93
2. Enumeraes.......................................................................................96
3. Estruturas Heterogneas.....................................................................99
4. Conjuntos...........................................................................................105

Captulo 4 - Ponteiros.............................................................................109
1. Fundamentos.....................................................................................109
2. Declarao e Inicializao de Ponteiros............................................ 111
3. Ponteiros e Arrays..............................................................................115
4. Ponteiros em Mdulos........................................................................117
5. Alocao Dinmica............................................................................121
5.1. Alocao Dinmica Escalar........................................................122
5.2. Alocao Dinmica Vetorial........................................................123
5.3. Usando Ponteiros No Tipados..................................................126
6. Problemas com Ponteiros..................................................................128
7. Estudo de Caso: Lista Escadeada Elementar....................................129

Parte 3 - Modularizao.........................................................................135
Captulo 5 - Modularizao...................................................................137
1. Noes de Controle e Processo........................................................137
2. Parmetros Formais e Reais..............................................................139
3. Modos de Passagem de Argumentos................................................140
4. Recursividade ...................................................................................145
5. Aninhamento Modular........................................................................148
6. Unidades............................................................................................150

Captulo 6 - Arquivos..............................................................................157
1. Memria Secundria..........................................................................157
2. Fluxos.................................................................................................159
3. Modos de Acesso...............................................................................161
4. Utilizando Arquivos Binrios...............................................................165
5. Utilizando Arquivos de Texto..............................................................172

Sobre o autor.............................................................................................179

Apresentao
Sejam bem vindos ao mundo da programao de computadores! Tratase de um mundo fascinante e sofisticado que evolui constantemente no intuito
de agilizar o trabalho das pessoas envolvidas com tecnologia da informao.
No existe apenas uma forma de programar um computador. Na realidade
cada rea de conhecimento abrangida pela computao est ligada a alguma
categoria de programao que se caracterizam por suas prprias ferramentas
e linguagens.
Assim, por exemplo, um programador de sistemas operacionais trabalha no desenvolvimento de ferramentas que permitam melhor acessibilidade
do hardware, um programador de jogos almeja usar ao mximo o potencial
grfico disponvel para desenvolver aplicativos para entretenimento, um programador de sistemas informativos cria softwares que permitam s pessoas
interagirem atravs de uma rede particular ou da internet, um programador
de interfaces objetiva maximizar o aproveitamento de aplicaes locais ou
remotas utilizando todo aparato visual moderno e assim por diante. Cada uma
destas reas requer especializao.
Entretanto em todos os casos os programadores precisam de conhecimentos essenciais adquiridos em disciplinas bsicas sobre programao
de computadores. Estes conhecimentos passam pela estudo das chamadas
linguagens de programao que, de forma geral, consistem de poderosos artifcios para a expresso de instrues a serem executadas por computadores.
Este livro tem por objetivo apresentar e explorar conceitos essenciais
da linguagem de programao Pascal. Esta linguagem foi desenvolvida para
ser fcil de compreender e utilizar. De fato ela foi criada para ser ensinada e
por essa razo tem boa aceitao entre iniciantes em programao. Alm do
mais uma vez compreendida a linguagem Pascal torna-se consideravelmente
mais simples tanto migrar para outras linguagens como ingressar numa rea
de especializao como aquelas citadas ante- riormente.
A estrutura bsica do livro consiste de seis captulos divididos em trs
unidades. A primeira unidade trata de toda parte fundamental da linguagem de
forma que possvel ao final dela j construir aplicaes que funcionem. As
duas unidades finais so adendos para sofisticao e potencializao do que
foi aprendido na primeira unidade. Em termos gerais o objetivo do livro permitir que o leitor programe o mais prematu- ramente possvel de forma prtica,
desafiadora e estimulante.
O autor

Parte
Introduo Programao de
Computadores

Captulo

Fundamentos
Objetivos:
Esta unidade tem por objetivo introduzir o estudante no aprendizado da
linguagem de programao Pascal. No Captulo 1 so apresentadas a
sintaxe bsica bem como as estruturas fundamentais para implementao de pequenos programas funcionais. No Captulo 2 a linguagem
expandida atravs do estudo de estruturas sequenciais que permitem a
representao e manipulao de listagens de dados auxiliando o estudante a lidar com a resoluo de problemas mais complexos.

1. Introduo Programao de
Computadores
No princpio no havia a distino entre hardware e software e os primeiros
computadores eram programados diretamente em seus circuitos. Consistia de
uma tarefa ardua e exigia profundo conhecimento da arquitetura e do funcionamento do equipamento. Tarefas elementares exigiam considervel tempo
de trabalho e erros eram frequentes. A evoluo do hardware e a concepo
do conceito de software deram uma guinada na histria dos computadores.
O software passou a representar a alma de um computador e sua inoculao
nos circuitos dos equipamentos passou a ser referenciada como instalao
de software.
Softwares so instalados em camadas, ou seja, um software, para
funcionar, utiliza outros softwares. A exceo naturalmente a camada de
software instalada diretamente sobre o hardware: o sistema operacional. As
demais camadas se instalam sobre este ou sobre uma ou mais camadas existentes. considerado um programa um software de aplicao especfica. H
programas para edio de imagens, reproduo de arquivos de som, navegao na internet, edio de texto e etc.
Um programa um arquivo que contm uma listagem de instrues de
mquina. Estas instrues devem ser executadas por uma CPU na ordem
que se apresentam no arquivo. Este processo denominado execuo do

Sistema Operacional:
O sistema operacional
um conjunto de
softwares que trabalham
cooperativamente para
proporcionar ao usurio
acesso a recursos
do computador. Ele
esconde detalhes,
muitas vezes complexos,
de funcionamento do
hardware atravs de
abstraes simples.
Exemplos so Linux,
Windows, OS2, Unix e etc

10

Ricardo Reis Pereira

programa. Para executar um programa ele primeiramente deve ser copiado


da memria secundria (do arquivo) para a primria (tempo de carregamento)
onde finalmente a CPU vai buscar, uma a uma, as instrues do programa at
sua finalizao (tempo de execuo). Muitos programas podem estar em execuo ao mesmo tempo em sistemas operacionais modernos e concorrerem
entre si pela mesma CPU (ou mesmas CPUs). Um programa em execuo
comumente chamado processo.
Para um ser humano, gerar um arquivo de programa codificando instrues de mquina, uma tarefa rdua, tediosa e dispendiosa haja vista que
para se produzir programas extremamente simples o tempo necessrio seria
consideravelmente grande. A soluo para esse problema foi a concepo
de linguagens com maior nvel que a linguagem de mquina necessria para
expressar instrues de mquina.
Os termos linguagem e nvel de linguagem so discutidos a seguir. Uma
linguagem , de forma geral, um conjunto de regras utilizados para expressar ou
registrar algum tipo de informao. Uma linguagem de programao (de computadores) naturalmente aquela utilizada para projetar e construir programas.
Quanto mais elaborada for uma linguagem, no sentido de propiciar melhor compreenso a um ser humano, maior ser o seu nvel. Ao longo da histria das
linguagens de programao o projeto e implementao de novas linguagens
com nvel cada vez mais alto se mostrou uma realidade. O leitor pode encontrar
em Sebesta o histrico completo das principais linguagens de programao.
A sofisticao da modernas linguagens de programao tem como principal origem a produtividade de software pelas pessoas. Para os computadores, entretanto, a melhor e mais compreensvel forma ainda a em cdigo de
mquina. Na prtica um programa, escrito numa dada linguagem de programao, precisa primeiramente ser traduzido em linguagem de mquina para
que enfim possa ser executado. Essa traduo pode ser abordada genericamente de duas formas.
Na primeira forma um cdigo em alto nvel completamente convertido em cdigo de mquina. Esse processo conhecido como compilao. Na
compilao um arquivo de cdigo (cdigo-fonte) expresso em uma linguagem
de alto nvel submetido a um programa denominado compilador e um novo arquivo em cdigo de mquina (executvel) gerado como sada. O arquivo executvel de fato um novo programa cuja execuo independe do cdigo-fonte.
A segunda estratgia de traduo conhecida como interpretao.
Nessa estratgia no existe a criao de um novo arquivo em cdigo de mquina. Ao invs disso a execuo realizada diretamente sobre o cdigo-fonte
por um programa denominado interpretador. proporo que o interpretador
avalia as linhas de cdigo em linguagem de alto nvel, ele as converte em

Linguagem de Programao I

cdigo de mquina e s ento as executa. Na interpretao a execuo s


vivel se um interpretador est instalado no sistema.
Um cdigo de mquina, oriundo de um processo de compilao, tem dependncia direta com o hardware e o sistema operacional sobre o qual foi criado. Assim se um dado cdigo-fonte F escrito numa linguagem de alto nvel X,
compilado num hardware H utilizando um sistema operacional S, s executar
em em mquinas com a mesma arquitetura de H e com o sistema S. Como o
executvel obtido atravs de uma traduo em cdigo de mquina, ento a
linguagem X no impe, no contexto avaliado, restries ao programa obtido
pela traduo de F. Se o hardware H mantido e o sistema mudado, digamos
para S2, ento F poder ser recompilado para S2 gerando um novo executvel.
Um compilador, que traduz cdigo escrito numa linguagem de alto nvel
X, precisa de uma verso para cada sistema operacional em que se deseja
escrever (utilizando X) programas que executem neste sistema. Assim, um
cdigo-fonte escrito numa linguagem X, que precisa ser traduzido em cdigo
de mquina para os sistemas S1 e S2, precisar de duas verses de compiladores C1 e C2, ambos da mesma linguagem X, para os respectivos sistemas.
Similar ao que acontece com compiladores, tradutores tambm requerem uma verso por sistema operacional. Entretanto, como no existe compilao prvia, o cdigo-fonte pode ser executado diretamente em sistemas
distintos desde que possuam instalado o interpretador apropriado.

2. A Linguagem Pascal
A linguagem de programao Pascal foi originalmente projetada por Niklaus
Wirth na dcada de 1970. A linguagem tem absorvido desde essa poca muitas contribuies que convergiram para a criao de diversos compiladores
importantes. Atualmente possvel encontrar na Internet mais de 300 compiladores ou interpretadores da linguagem (alguns pagos, outros gratuitos
e muitos descontinuados, ou seja, no possuem mais suporte). Veja www.
Pascaland.org para uma lista completa de compiladores Pascal. As mais
notveis contribuies para o desenvolvimento do Pascal foram feitas pela
Borland (empresa americana de desenvolvimento de software) com a criao
do Turbo Pascal e posteriormente do Delphi Pascal.
A linguagem Pascal originalmente estruturada, ou seja, os programas
so construdos como um conjunto de pequenos subprogramas que se conectavam por chamadas (uma chamada de um determinado subprograma
a solicitao de execuo de outros subprogramas a partir dele). A linguagem
absorveu com o passar do tempo o paradigma da orientao a objetos (que
se baseia nos conceitos de classes e objetos) dando origem ao Object Pascal.

11

12

Ricardo Reis Pereira

Arquitetura do
Processador:
Define o leiaute e
a capacidade de
armazenamento ou
processamento dos
componentes de uma
unidade central de
processamento (CPU).
As arquiteturas mais
populares hoje em dia
possuem de um a dois
ncleos (em ingls,
single core e dual core) e
tamanhos de registradores
(memria interna da CPU)
de 32 ou 64 bits.
Janela de Terminal:
Uma janela de terminal
a forma mais primitiva que
um sistema operacional
oferece ao usurio
para requisies de
tarefas. Todas as aes
so repassadas como
instrues escritas
denominadas de linhas de
comandos. Para indicar
que novas instrues
podem ser digitadas,
um terminal dispe um
indicador de entrada
denominado prompt
seguido de um cursor
piscante. Para confirmar
entradas o usurio
pressiona ENTER aps
cada linha de comandos e
aguarda o processamento
que normalmente se
encerra com a reexibio
do prompt aguardando
novas instrues.

O Turbo Pascal e o Delphi Pascal constituem a base de desenvolvimento do compilador Free Pascal abordado neste livro e recomendado aos
leitores (veja www.freePascal.org). Trata-se de um compilador livre, de crescente popularidade e que reconhece cdigos em Pascal puramente estruturado (como acontecia no Turbo Pascal), cdigos em Object Pascal (como
acontece com o Delphi) ou associao de cdigo (parte estruturada e parte
orientada a objetos)
Abordaremos neste livro apenas os elementos estruturados do Free
Pascal (que incluem os fundamentos da linguagem, variveis e constantes,
operadores, expresses, controle de fluxo, strings e arrays, tipos de dados
personalizados, ponteiros, modularizao e arquivos) que permitiro ao leitor
posterior extenso ao Object Pascal (que inclui ainda uso de classes e objetos, uso de interfaces, programao genrica, sobrecarga de operadores e
manipulao de excees).

3. Utilizando um Compilador Pascal


O primeiro passo para se iniciar em programao naturalmente instalar o
compilador (ou o interpretador se for o caso). Para baixar o compilador Free
Pascal visite www.freePascal.org/download.var. O site dispe vrias verses
do compilador listados por arquitetura do processador e por sistema operacional. Na sesso binaries (binrios) ficam os instaladores propriamente ditos.
Na sesso sources (fontes) o cdigo fonte do compilador (voltado para quem
deseja contribuir com melhorias no Free Pascal). Por fim a sesso documentation (documentao) permite baixar a documentao oficial completa do
compilador em vrios formatos (PDF, HTML, PS, DVI e TXT).
Para testar se o compilador instalado est devidamente configurado,
abra um terminal (no Windows isso pode ser feito indo em Iniciar|Executar,
digite cmd, depois OK. Em sistemas Unix e relacionados, como Linux, caso o
sistema j no esteja em modo terminal, h diversos aplicativos de simulao
de terminal em modo X). Quando o prompt do terminal estiver visvel simplesmente digite,
fpc

Se o compilador estiver devidamente instalado ser impressa uma listagem das opes bsicas de uso. A seguir mostramos um fragmento que
antecede a listagem propriamente dita e que trs informaes do compilador.
Free Pascal Compiler version 2.2.4-3 [2009/06/04] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
/usr/lib/fpc/2.2.4/ppc386 [options] <inputfile> [options]

Linguagem de Programao I

13

Para compilar um programa escrito em Pascal, via linha de comando


(terminal), utilizando o Free Pascal, deve-se primeiramente mudar para a pasta que contm o arquivo com o cdigo-fonte. Em seguida digite,
fpc teste.pas

neste caso teste.pas o arquivo de cdigo-fonte na pasta corrente. A sada


em terminal da compilao anterior algo semelhante a,
Free Pascal Compiler version 2.2.4-3 [2009/06/04] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Linux for i386
Compiling teste.pas
Linking teste
3 lines compiled, 0.1 sec

Quando a compilao encerra, dois novos arquivos tero surgido:


teste.o e teste (ou teste.exe, no Windows). O arquivo teste.o chamado arquivo objeto e representa o programa sem ligaes com o sistema operacional. Na ltima fase da compilao todos os arquivos objetos (h projetos com
mais de um arquivo de cdigo-fonte cada qual gerando um arquivo objeto) so
submetidos a um processo denominado linkagem (vinculao) proporcionado
por um programa chamado linker (vinculador). Este programa resolve as pendencias de conexo dos arquivos objeto com o sistema operacional e gera
como sada o programa executvel, neste caso teste. Para executar o novo
programa no Windows simplesmente digite na linha de comando,
teste.exe

e no Unix e Linux:
./teste

Quando erros esto presentes no cdigo-fonte o compilador reportar


uma lista de todos eles (neste caso, no prprio terminal) indicando a linha onde
cada um ocorre. Alguns erros so facilmente corrigveis como erros de sintaxe
(algo foi escrito erroneamente). J outros requerem uma anlise mais apurada
do programador para serem corretamente diagnosticados e corrigidos.
Alm de erros, um compilador pode gerar tambm advertncias. Uma
advertncia (Warning) um alerta que o compilador envia para indicar que
algum recurso no est sendo apropriadamente utilizado. Erros impedem que
o compilador crie o executvel do programa ao contrrio das advertncias.
Um programa compilado que gera somente advertncias produz um binrio.
Na prtica os efeitos de uma advertncia para o programa que ser executado pode ser imperceptvel em alguns casos e prejudicial em outros. Consulte

Um compilador no
pode corrigir os erros
que lista porque, em sua
abrangente viso, h
muitas possibilidades de
correo de um mesmo
erro. Para ajudar ento no
trabalho do programador
o compilador gera o
mximo de documentao
de erro que permite mais
facilmente a soluo do
problema. O processo de
resoluo de erros num
programa conhecido
como depurao (em
ingls, debug).

14

Ricardo Reis Pereira

o guia do programador, na documentao oficial do Free Pascal, para mais


detalhes sobre erros e advertncias de compilao.
Uma IDE (Integrated development environment ou ambiente de desenvolvimento integrado) um programa utilizado para melhorar a produtividade
de software. Eles constituem em geral de um editor de cdigo-fonte com destacamentos de sintaxe, auto completao e uma srie de ferramentas dispostas
em menus e botes. Muitas IDEs so pagas e outras de uso livre. As IDEs mais
populares para o desenvolvimento em linguagem Pascal e Object Pascal so
Delphi e Lazarus. Entretanto diversos editores de texto elementares funcionam
como IDEs sendo suficientes para escrever cdigos fonte em Pascal.
Delphi ou Borland Delphi na realidade a associao de um compilador
(cuja linguagem uma extenso do Object Pascal) e uma IDE orientada a
desenvolvimento RAD (Rapid Application Development ou Desenvolvimento
Rpido de Aplicao). Delphi era mantido inicialmente pela Borland Software
Corporation (www.borland.com), mas atualmente a detentora a Embarcadero
(www.embarcadero.com). Delphi direcionado a plataforma Windows e inclui
atualmente verso para o framework .NET. Chegou a ser usado para desenvolvimento de aplicaes nativas para Linux e Mac OS, atravs do Kylix. O
desenvolvimento do Kylix foi descontinuado.
Lazarus (www.lazarus.freePascal.org) uma IDE cuja interface semelhante ao Delphi e que utiliza como compilador o Free Pascal. Trata-se
de uma ferramente multiplataforma com verses para os sistemas Linux,
Windows, OS/2, Mac OS, ARM, BSD, BeOS, DOS entre outros.
A explorao destas IDEs est fora do escopo deste livro. Ao invs disso apresentaremos brevemente a IDE que acompanha o prprio Free Pascal
(Free Pascal IDE) e que pode ser executada via linha de comando digitando,
fp

Trata-se de uma IDE de interface modesta (sem recursos grficos), mas


de uso fcil e sem restries de desenvolvimento, compilao ou execuo
de programas. O aspecto desta IDE mostrado na Figura-1.1.

Linguagem de Programao I

Figura 1 - IDE que acompanha o Free Pascal

Para criar, abrir ou salvar arquivos de cdigo-fonte no Free Pascal IDE


usa-se as opes new (novo), open (abrir), Save/Save as... (salvar/salvar
como...) do menu File (arquivo) conforme Figura 2.

Figura 3 - menu compile

Figura 4 - Menu run

Figura 2 - menu File

Para compilar o arquivo de cdigo-fonte em edio use o menu Compile.


Para compilao pura use Compile|Compile e para criar o executvel use
Compile|Build. A Figura 3 ilustra este menu. Para executar o programa na
prpria IDE utiliza o menu Run indo em Run|Run (Figura 4).

Figura 5 - Caixa de notificaes do Free Pascal IDE

15

16

Ricardo Reis Pereira

Quando erros e/ou advertncias ocorrem durante a compilao, a IDE


faz a listagem na caixa de notificao Compiler Messages (mensagens do
compilador) que surge na parte inferior da IDE (Figura 5). Se erros no ocorrerem a IDE indica que a compilao obteve sucesso e exibe uma caixa como
a mostrada na Figura 6.

Para mais detalhes sobre a Free Pascal IDE consulte o guia do usurio
(users guide) na documentao do compilador.

4. Elementos Essenciais da Linguagem Pascal


Esta sesso tem por objetivo apresentar todos os elementos bsicos construtivos da linguagem Pascal. Isso inclui regras elementares de sintaxe, variveis,
constantes, operadores, entrada e sada, controle de fluxo e uso bsico da
modularizao. Este contedo suficiente para a construo de diversos programas funcionais. Os captulos retantes do livro tem por objetivo refinar ou
potencializar os tpicos abordados nessa sesso.

4.1. Palavras Reservadas e Identificadores


Um cdigo-fonte em Pascal escrito pela associao dos chamados tokens.
Tokens, por definio, so blocos lxicos bsicos de cdigo-fonte que representam as palavras da linguagem. Eles so formados pela combinao de
caracteres de acordo com regras definidas na linguagem.
Palavras Reservadas so tokens com significado fixo numa linguagem
de programao e desta forma no podem ser modificadas ou redefinidas.
As palavras reservadas do Free Pascal somam aquelas provenientes da
linguagem original (idealizada por Niklaus Wirth) mais aquelas oriundas das
contribuies do Turbo Pascal e do Delphi Pascal. Ao invs de uma lista completa dessas palavras, apresentamos na Tabela-1.1 as palavras reservadas

Linguagem de Programao I

17

utilizadas neste livro as quais so suficientes programao estruturada aqui


abordada.
and

for

not

string

array

function

of

then

asm

goto

on

to

begin

if

or

true

case

implementation

packed

type

const

in

procedure

unit

dispose

inline

program

until

div

interface

record

uses

do

label

repeat

var

exit

mod

set

while

false

new

shl

with

file

nil

shr

xor

Tabela 1 - Palavras reservadas da Linguagem Pascal

Identificadores so tokens definidos pelo programador que podem ser


modificados e reutilizados. Identificadores so sujeitos s regras de escopo
da linguagem.
Para escrever um identificador em Pascal deve-se seguir as premissas:
O primeiro caractere (obrigatrio) deve ser uma letra (intervalos a..z ou
A..Z) ou um underline (_).
Os demais caracteres (opcionais) podem ser letras, nmeros (0..9) ou
undelines.
No existe sensibilidade de caixa, ou seja, no h distino entre maisculas e minsculas. Assim, por exemplo, os identificadores Casa, CASA e
cASA so idnticos.
So todos exemplos de identificadores vlidos em linguagem Pascal:
x
a789 teste_56

dia_de_sol

__1987q
_223 AxZ9 CARRO

4.2. Estrutura Bsica de um Programa Pascal


O compilador Pascal precisa como entrada um ou mais arquivos de cdigo
para gerar um arquivo de cdigo de mquina (executvel). Estes arquivos de
entrada so de fato arquivos texto podendo inclusive ser editados em editores de textos elementares. Como usual em muitas IDEs a extenso destes
arquivos modificada para .PAS ou .PP sem comprometimento de tipo
(ainda so de contedo texto). O menor cdigo fonte compilvel em Pascal :

Regras de Escopo:
So regras que definem
restries de acessos
entre partes distintas de
um mesmo programa. Elas
permitem, por exemplo,
a implementao de
programas grandes atravs
de fragmentos menores
fceis de gerenciar.

18

Ricardo Reis Pereira

program teste; // linha de ttulo


{ declaraes }
begin
{ bloco principal }
end. {* fim do programa *}

Todo programa em linguagem Pascal deve iniciar com a palavra reservada program seguida de um identificador (nome do programa; neste caso,
teste) seguido de ponto-e-vrgula. Logo abaixo devem ser colocadas, quando
necessrias, as declaraes globais do programa (global significa disponvel
para todo programa). Uma declarao um cdigo que viabiliza a utilizao
de um recurso do computador. As declaraes em linguagem Pascal so dispostas em sesses (unidades, tipos, constantes, variveis e mdulos) que so
estudadas ao decorrer do livro.
As respectivas palavras reservadas begin e end, representam os delimitadores do bloco ou corpo principal do programa: todo contedo entre begin
(que significa incio) e end (que significa fim) representa o programa propriamente dito a ser executado. A construo de um programa Pascal enfim a
implementao do cdigo no bloco principal que eventualmente requer por
recursos adicionais via declaraes. O ponto (.) marcado aps o end na ltima
linha faz parte da sintaxe da linguagem e formaliza o trmino do programa.

Sub-rotina:
So trechos de cdigofonte que funcionam como
programas independentes.
Programas e unidades
em Pascal so de fato
aglomeraes de subrotinas. As sub-rotinas so
tambm conhecidas como
subprogramas. Adiante
veremos que sub-rotinas
em Pascal podem ser
procedimentos ou funes
e que por essa razo
utilizamos o termo mdulo
para nos referirmos a
ambos.

Comentrios so fragmentos de textos no compilveis escritos conjuntamente ao cdigo-fonte e cuja funo documentar o programa. Pode-se
comentar contedo em Pascal colocando uma ou mais linhas entre chaves ou
entre /* e */ ou prefixando cada linha com // (veja exemplos no cdigo anterior).
Uma sesso de unidades declara bibliotecas conhecidas como unidades em Pascal. Unidades contm sub-rotinas desenvolvidas por outros programadores que se tornam disponveis nos programas onde so declaradas
tais unidades (Vrias unidades so distribudas com o compilador Pascal e
esto disponveis aps sua instalao).
Listagem 1
01

program primeiro_exemplo;

02

uses crt, sysutils, nova_unidade;

03

begin

04

modulo1;

05

modulo2(34);

06

modulo3(12, teste);

07

end.

Linguagem de Programao I

A Listagem 1 ilustra o uso de unidades em linguagem Pascal. A palavra


reservada que abre uma sesso de declarao de unidades uses. Todo contedo aps uses e antes de outra sesso, ou do begin do programa principal,
dever ser de unidades devidamente separadas por vrgulas (quando h mais
de uma). O final das declaraes sempre marcado com ponto-e-vrgula (;).
Na Linha-02 v-se a declarao de trs unidades.
Cada mdulo de uma unidade pode ser uma funo ou um procedimento (veja Captulo-5) o qual contm um nome (um identificador) que usado
para fazer uma chamada do mdulo. Uma chamada de mdulo representa
sua invocao no programa principal atravs de uma linha que contm seu
nome. Nas Linhas 04, 05 e 06, Listagem 1, v-se trs exemplos de chamadas
a mdulos. Na Linha 05 o mdulo requer informao adicional que repassada entre parnteses. Quando mais de uma informao requerida pelo
mdulo, como na Linha-06, deve-se separ-las por vrgulas. Cada uma das
informaes fornecidas a um mdulo denominada de argumento ou parmetro do mdulo. As trs chamadas de mdulos na Listagem 1 possuem respectivamente zero, um e dois argumentos.

4.3. Variveis
Uma varivel um artifcio das linguagens de programao que permite o
programador utilizar de forma iterativa a memria do computador. O programador define que variveis o programa dever utilizar e elas sero criadas na
memria quando o programa for executado. Cada varivel se vincula a uma
clula de memria real de forma que as operaes programadas em cdigo
afetaro a memria quando o programa estiver rodando.
Basicamente uma varivel pode verificar ou modificar a clula de memria a qual est ligada. As operaes de mudana e verificao de valor, por
uma varivel so chamadas respectivamente de operaes de escrita e leitura.
A leitura no afeta o contedo da varvel ao passo que a escrita sobrescreve o
valor que a varivel contm com um novo valor (o valor sobrescrito perdido).
A sesso de declarao de variveis a sesso do programa destinada
a identificao (definio) de todas as variveis que sero utilizadas. Tentar
usar uma varivel no declarada faz o compilador emitir um erro de sintaxe.
Cada nova varivel precisa de um nome (que um identificador) e um
tipo (que uma palavra reservada). O tipo dir ao compilador que valores e
operaes sero suportados por aquela varivel. Tipos podem ser primitivos e
derivados. Os tipos primitivos so aqueles definidos nativamente pelo Pascal
ao passo que os derivados so construdos pelo programador a partir de tipos
primitivos (veja os Captulos 2, 3 e 4 para mais detalhes).

19

20

Ricardo Reis Pereira

A palavra reservada var marca o incio de uma sesso de declarao de


variveis em Pascal. Um grupo, em uma declarao de variveis, um conjunto de nomes de variveis que compartilham o mesmo tipo e que so sintaticamente separados por vrgulas. Cada lista de nomes de um grupo encerra em
dois-pontos (:) seguida da palavra reservado ao tipo das variveis deste grupo.
Como a maioria das formaes em Pascal, um grupo encerra com ponto e
vrgula (;). Uma sesso pode possuir um ou mais grupos. Esquematicamente,
var
<a_1>, <a_2>, ... ,<a_n> : <tipo_1>; // grupo de variveis de tipo tipo_1
<b_1>, <b_2>, ... ,<b_m> : <tipo_2>; // grupo de variveis de tipo tipo_2
...

Os tipos primitivos da linguagem Pascal so subdivididos em cinco categorias,


inteiros
reais
lgicos
caracteres
strings
Os tipos inteiros permitem a criao de variveis para o armazenamento
de nmeros inteiros. Os tipos inteiros da linguagem Pascal distinguem-se basicamente pelo nmero de bytes e (consequentemente) pela faixa de valores que
podem ser representados (quanto mais bytes, mais nmeros podem ser representados por um tipo). A Tabela-1.2 apresenta as palavras reservadas para os
dez tipos inteiros na Linguagem Pascal, bem como a faixa numrica dos valores
cujas as variveis podem representar e ainda o total de bytes que tais variveis
ocupam em memria quando o programa estiver em execuo.
Tipo
Faixa
Byte
0 .. 255
Shortint
-128 .. 127
Smallint
-32768 .. 32767
Word
0 .. 65535
Integer
smallint ou longint
Cardinal
longword
Longint
-2147483648 .. 2147483647
Longword
0 .. 4294967295
Int64
-9223372036854775808 .. 9223372036854775807
QWord
0 .. 18446744073709551615
Tabela 2 - Tipos inteiros da Linguagem Pascal

Tamanho (bytes)
1
1
2
2
2 ou 4
4
4
4
8
8

Linguagem de Programao I

21

A sesso a seguir declara algumas variveis inteiras,


var
a,b,c: integer; // grupo de varveis integer de nomes a, b e c
teste: word; // grupo de uma varivel word de nome teste
x: cardinal; // grupo de uma varivel cardinal de nome x

Variveis de tipo real armazenam nmeros com possibilidade de casas


decimais. Os tipos reais, similar aos inteiros, so to representativos quanto
maior for a quantidade de bytes associada. A diferena entre diferentes tipos
reais reside na quantidade de bits dedicada a poro fracionria. A Tabela-1.3
lista as palavras reservadas aos seis tipos reais da linguagem Pascal bem
como a faixa representativa e a quantidade de bytes (Conforme tabela, o tipo
real depende da plataforma, ou seja, pode ter 4 ou 8 bytes conforme arquitetura de CPU utilizada).
Tipo
Real
Single
Double
Extended
Comp
Currency

Faixa
depende da plataforma
1.5E-45 .. 3.4E38
5.0E-324 .. 1.7E308
1.9E-4932 .. 1.1E4932
-2E64+1 .. 2E63-1
-922337203685477.5808 ..
922337203685477.5807

Tamanho (bytes)
4 ou 8
4
8
10
8
8

Tabela 3 - Tipos reais da Linguagem Pascal

A sesso a seguir declara algumas variveis reais,


var
angulo: real; // grupo de uma varivel real de nome angulo
pop, uni: extended; // grupo de duas variveis extended de nomes pop e uni

Tipos lgicos ou booleanos so utilizados para definir variveis que assumam apenas os valores verdadeiro e falso. Estes valores so representados em Pascal respectivamente pelas palavras reservadas True e False.
Uma varivel lgica teoricamente representada por um nico bit, mas na
prtica existem quatro tipos booleanos em Pascal com pelo menos 1-byte,
como mostrado na Tabela-1.4 (palavra reservada versus tamanho em bytes).
O tipo boolean o mais difundido sendo suficiente na maioria das aplicaes
que precisam de variveis booleanas.

Os tipos integer e real


variam com a plataforma
utilizada, ou seja,
dependendo da arquitetura
da CPU suas variveis
podem ser mais ou
menos representativas.
Recomenda-se que no
caso do desenvolvimento
de programas que devam
rodar em mais de uma
plataforma, esses tipos
sejam evitados.

22

Ricardo Reis Pereira

Tipo
Tamanho (bytes)
Boolean
1
ByteBool
1
WordBool
2
LongBool
4
Tabela 4 - Tipos lgicos da Linguagem Pascal

A sesso seguinte ilustra a declarao de variveis booleanas,


var
b, m, q: boolean; // grupo de trs variveis booleanas de nomes a, m e q

O tipo caractere, cuja a palavra reservada em Pascal char, uma


variao do tipo inteiro byte. A faixa numrica 0..255 substituda por 256
caracteres mapeados pelo equivalente byte. O tipo string, cuja palavra reservada em Pascal string, refere-se a variveis que devem armazenar um
fragmento de texto. As strings constituem-se de sequncias de caracteres
e contam com um conjunto prprio de operaes que as diferenciam dos
demais tipos primitivos. Para saber mais sobre variveis caracteres e strings, veja Captulo 2.
Para determinar em Pascal o tamanho em bytes utilizado por uma varivel utiliza-se o comando nativo de linguagem sizeof. Este comando pode
receber tanto o nome da varivel, como em,
sizeof(x);

como o nome de tipo,


sizeof(Integer);

No caso de tipos primitivos, sizeof possui aplicao importante na determinao dos tamanhos de integer e real haja vista dependerem da plataforma
utilizada (hardware).

4.4. Constantes
Uma constante um artifcio das linguagens de programao que permite a
manuteno de valores invariantes durante toda execuo do programa. Uma
constante pode aparecer num cdigo como parte integrante de uma expresso (veja prxima sesso) ou vinculada a uma clula de memria independente (como nas variveis), mas com suporte apenas a verificao (nunca a
escrita). Nas expresses,

Linguagem de Programao I

x*25
3.45-y
a + ch
hoje foi + st
b/100

x, ch, st e b so variveis e 25, 3.45, a, hoje foi e 100 so constantes.


As variveis podem mudar de valor em diferentes execues ao passo que as
constantes mantm os mesmos valores. Constantes tambm possuem tipos.
Nos exemplos anteriores, 25 e 100 so constantes de tipo inteiro, 3.45 de tipo
real, a de tipo caractere e hoje foi de tipo string (constantes strings e caracteres so, em Pascal, sempre colocadas entre aspas simples. Para saber mais
sobre caracteres e strings, veja Captulo 2).
Para construir uma constante com clula prpria de memria, deve-se
construir uma sesso de declarao de constantes. A palavra reservada para
incio deste tipo de sesso const. Cada nova constante possui a sintaxe fixa,
const
<nome_da_constante> = <valor>;

A sesso a seguir ilustra a definio de cinco novas constantes em


Pascal,
const
cx = 25;
max = 6.76;

// constante de tipo inteiro

// constante de tipo real

msg = 'ola mundo'; // constante de tipo string


meu_ch = 'a';

// constante de tipo caractere

my_bool = True;

// constante de tipo booleano

O compilador reconhece o tipo das constantes pelo valor na definio.


No possvel, em Pascal, definir constantes sem fornecer um valor.
O programador pode tambm forar que uma constante seja de um tipo
especfico. So as chamadas constantes tipadas. Elas seguem a sintaxe fixa,
const
<constante>: <tipo> = <valor>;

A sesso seguinte traz apenas constantes tipadas,


const
q: integer = 11;
ex: real = 3;
st: string = x;

23

24

Ricardo Reis Pereira

Observe que a tipagem de q no necessrio pois o compilador detectaria 11 como inteiro. Nos casos de ex e st a tipagem necessria pois, sem
elas, ex seria inteiro e st caractere.

4.5. Operadores e Expresses


O mecanismo utilizado para modificar o contedo de uma varivel denominado atribuio explicita ou simplesmente atribuio. Em linguagem Pascal uma
atribuio construda com o operador de atribuio (:=) seguindo a sintaxe,
<varivel> := <expresso>;

Semanticamente a expresso do lado direito do operador resolvida


e o valor resultante gravado na varivel do lado esquerdo. Deve existir em
Pascal apenas uma varivel do lado esquerdo de uma atribuio.
Listagem 2
01

program atribuicoes;

02

var

03

i: integer;

04

x, info_2: real;

05

db: double;

06

b: boolean;

07

begin

08

i := 35;

09

x := 4.87;

10

info_2 := x * i;

11

db := x*x + 6.0*i + 45;

12

b := True;

13

end.

A Listagem 2 demonstra a construo de cinco atribuies com expresses diversificadas. O operador de atribuio apenas um exemplo de operador.
A linguagem Pascal disponibiliza diversos operadores divididos nas categorias,
Operador de atribuio
Operadores aritmticos
Operadores relacionais
Operadores lgicos
Operadores de ponteiros
Operadores bit-a-bit

Linguagem de Programao I

Os operadores aritmticos da linguagem Pascal so listados na Tabela 5.


Estes operadores so binrios (possuem dois operandos) e infixos (colocados
entre os operandos). Os operandos devem ser necessariamente valores numricos e o resultado da operao tambm um valor numrico. As operaes de
soma, subtrao e produto, quando realizadas entre dois operandos inteiros,
resultar num valor inteiro.
Entretanto, se qualquer um dos operandos for real (ou ambos), o valor
final ser real. O operador de diviso, /, sempre retornar um valor real, mesmo
que os operandos sejam inteiros (ocorrer um erro de execuo se o divisor for
zero). Os operador div (quociente de diviso) e mod (resto de diviso) s operam valores inteiros e o resultado da operao tambm um inteiro. Usar estes
operadores com variveis reais ou qualquer outro tipo de varivel, representa
um erro de sintaxe (que o compilador acusar).
Operador
Funo
+
Soma
Subtrao
*
Produto
/
Diviso
div
Quociente de diviso
mod
Resto de diviso
Tabela 5 - Operadores Aritmticos em Pascal

Uma expresso aritmtica pode ser um valor constante, uma varivel


ou ainda uma associao entre constantes, variveis e operadores aritmticos (o uso de parnteses tambm permitido). Numa atribuio o resultado
final da expresso no lado direito deve ser compatvel com o tipo da varivel
que aguarda do lado esquerdo. Na Listagem-1.2, o resultado de expresses
aritmticas so atribudos s variveis i, x, info_2 e db. So outros exemplos
legais de expresses aritmticas em Pascal,
12+x*(a-b*3.0) (x div 10)*10 beta mod 2 + 1 a+b*c div 2

Denomina-se precedncia de operaes a ordem que o compilador resolve as sub operaes que constituem uma expresso. Numa expresso aritmtica a sequencia de resolues a mesma definida pela matemtica, ou seja,
primeiro as multiplicaes (*) e divises (/, div ou mod), depois adies (+) e
subtraes (-). Assim em, x+3*y, feita primeira a multiplicao depois a soma.
Se operadores de mesma precedncia aparecem adjacentes numa mesma expresso, o compilador far a avaliao seguindo a sequencia em que esto,
da esquerda para a direita. Assim por exemplo a expresso, 20 mod 11 div 2,
resulta em 4 porque mod resolvido antes de div. De forma similar a expresso,
100 div 3 div 2 div 5, reduzida pelo compilador na sequencia,

25

26

Ricardo Reis Pereira

100 div 3 div 2 div 5


33 div 2 div 5
16 div 5
3

Para quebrar a ordem de precedncia seguida nas avaliaes de expresses, pode-se utilizar parnteses como em, (3+x)*y. Neste exemplo a
soma realizada primeiro.
Operadores relacionais so aqueles que comparam dois valores (que
podem ser ou no numricos) e resultam num valor booleano, ou seja, verdadeiro ou falso. Por exemplo a expresso,
x > 10

utiliza o operador relacional maior que (>) e retorna verdadeiro (se o valor em
x maior que 10) ou falso (se o valor em x menor ou igual a 10). A tabela
seguinte lista os operadores relacionais da linguagem Pascal e seus respectivos significados:
Operador Relacional

Significado

>

Maior que

<

Menor que

>=

Maior ou igual a

<=

Menor ou igual a

<>

Diferente de

Igual a

Tabela 6 - Operadores relacionais em Pascal

Operadores relacionais em Pascal so no associativos, ou seja, dois


operadores relacionais no devem aparecer adjacentes na mesma expresso.
Assim, por exemplo, a expresso, x>y>10, ilegal em Pascal. Expresses formadas com operadores relacionais so denominadas expresses booleanas.
De fato qualquer expresso que retorne um booleano como valor final uma
expresso booleana.
Operadores lgicos so operadores que modificam ou conectam entre
si expresses booleanas. Por exemplo, na expresso,
(x>y) and (y>10)

o operador lgico and conecta duas expresses relacionais. Veja Tabela 7


com os operadores lgicos do Pascal.
O operador de conjuno, and, binrio, infixo e retorna verdadeiro
apenas quando as duas expresses (que so seus operandos) so ambas
verdadeiras. Os operadores de disjuno, or, e disjuno exclusiva, xor so

Linguagem de Programao I

tambm binrios e infixos. Na disjuno basta que um dos operandos seja


verdadeiro para que a resultante tambm o seja. Na disjuno exclusiva a
resultante verdadeira quando apenas uma das expresses for verdadeira.
O operador de negao, not, unrio (apenas um operando) e prefixo (disposto esquerda do operando). A negao resulta no inverso do valor da
expresso booleana.
Operador Lgico

Significado

and

Conjuno

or

Disjuno

xor

Disjuno exclusiva

not

Negao

Tabela 7 - Operadores lgicos em Pascal

Operadores lgicos possuem precedncia de operaes. O operador


lgico de maior precedncia o not seguido por and, depois or e por fim, o de
menor precedncia, xor. Por exemplo, a expresso, not true or false and true,
avaliada na sequencia,
not true or false and true
false or false and true
false or false
false

Se operadores lgicos de mesma precedncia aparecem adjacentes


na mesma expresso o compilador efetuar a avaliao da esquerda para
a direita.
A Tabela 8 ilustra a tabela verdade dos operadores lgicos em Pascal (A
e B representam expresses booleanas)
A
TRUE
TRUE
FALSE
FALSE

B
TRUE
FALSE
TRUE
FALSE

A and B
TRUE
FALSE
FALSE
FALSE

A or B
TRUE
TRUE
TRUE
FALSE

A xor B
FALSE
TRUE
TRUE
FALSE

not A
FALSE
FALSE
TRUE
TRUE

Tabela 8 - Tabela verdade dos operadores lgicos em Pascal

Em Pascal, expresses booleanas conectadas com operadores lgicos, precisam estar entre parnteses. Isso acontece porque os operadores
lgicos tm precedncia sobre os operadores relacionais de forma que uma
expresso do tipo, x>0 and x<100, sem parnteses, tem primeiramente avaliado o and, que neste caso significa operar a sub expresso, 0 and x. Mesmo
que isso tivesse algum sentido para o programador ainda restariam por se re-

27

28

Ricardo Reis Pereira

solver dois operadores relacionais adjacentes, o que invivel. As expresses


booleanas a seguir so todas legais em linguagem Pascal.
Expresso

Verdadeira se o Valor em ...

x>10

x maior que dez

y<=7

(x>11) and (x<=100)


zeta <> mega

(a<100) or (b>500)

y menor ou igual a sete


x maior que onze e ao mesmo tempo menor
ou igual a cem
zeta diferente do em mega
a menor que cem ou o em b maior que
quinhentos.

(dia=seg) xor (dia=qua) dia no segunda nem quarta


not((x=y) and (a=b))

x diferente do em y ou o em a diferente
do em b

Operadores de ponteiros sero estudados no Captulo 4. Operadores


bit a bit no sero explorados neste livro.

4.6. Comandos de Entrada e Sada


A entrada de um programa usualmente realizada atravs de um mouse e
um teclado ao passo que a sada atravs da tela ou de uma impressora. Para
facilitar o trabalho dos usurios comum distribuir o programa com uma interface grfica (uma janela com botes, menus, caixas de rolagem e etc). O
desenvolvimento de interfaces grficas (GUIs) requer mais que a programao estruturada apresentada neste livro. Para este nvel de programao o
leitor dever estender seus estudos ao Object Pascal (www.freePascal.org) e
depois explorar o uso de IDEs voltadas a criao de GUIs, como o caso do
Delphi (www.borland.com/br/products/delphi) que comercial ou do Lazarus
(www.lazarus.freePascal.org) que livre.
Os detalhes de implementao de uma GUI so substitudos aqui por
uma janela de terminal completamente orientada a contedo textual e onde
so visualizadas todas as operaes de entrada e sada (no Captulo-6 estenderemos os mesmos conceitos a arquivos). Um programa executado num
terminal via linha de comando (use o command no Windows ou um interpretador de linha de comando como o bash no Linux) imprime no prprio terminal
tanto o contedo de entrada que digitado em teclado quanto a sada gerada
pelo programa.
A unidade em Pascal que contm mdulos responsveis por operaes de entrada e sada a unidade system. Seu uso to frequente que
ela dispensa declarao, ou seja, um programa sem qualquer declarao de
unidades ainda utiliza a unidade system. Outras categorias de mdulos desta

Linguagem de Programao I

unidade sero vistas ao decorrer do livro. Os mdulos de entrada e sada em


Pascal (comumente chamados comandos de entrada e sada) so,
write

Escreve na sada padro o contedo de sua lista de argumentos.


Podem haver um ou mais argumentos neste comando.

writeln

Funciona de forma similar a write acrescentando uma nova linha


depois de escrever seus argumentos. Pode ser utilizado sem
argumentos para deixar uma linha em branco.

read

L da entrada padro (normalmente o teclado) um ou mais


valores e os dispe em seus argumentos obedecendo a
sequencia de leitura. Os argumentos deste comando devem ser
necessariamente variveis.

readln

Funciona como read mas ainda pode ser utilizado sem


argumentos simplesmente para aguardar o pressionar de tecla
ENTER (quando o teclado a entrada padro).

Listagem 3
01

program entrada_e_saida;

02

var

03
04

x: integer;
begin

05

write('Fornecer valor de x: ');

06

read(x);

07

writeln('o dobro de x vale ', x*2);

08

readln;

09

end.

O programa da Listagem 3 ilustra a utilizao dos comandos de entrada


e sada em Pascal. Na Linha-05 o comando write utilizado para escrever
uma string, Uma string em Pascal uma sequencia de caracteres entre aspas
simples ( ) representando um trecho de texto. A impresso de uma string por
write apenas reproduz seus caracteres na sada padro. Veja Captulo-2 para
mais detalhes sobre strings em Pascal.
Na Linha-06 ocorre uma leitura de valor via teclado e o valor final digitado armazenado na varivel x. importante observar que o comando read
suspende momentaneamente a execuo e aguarda que o usurio digite alguma coisa. Somente quando confirmada a entrada (normalmente com um
ENTER) que o programa prossegue suas execuo. Na Linha-07 writeln
recebe dois argumentos e os imprime na sequencia que aparecem (atente
que a vrgula de separao de parmetros no impressa!).

29

30

Ricardo Reis Pereira

O primeiro argumento uma string e impressa da mesma forma que


aparece no cdigo. O segundo argumento uma expresso que deve ser
resolvida pelo programa e o resultado (dobro do valor em x) impresso por
writeln. Na Linha-08 o programa aguarda por um ENTER adicional antes de
encerrar. A sequencia em terminal mostrada a seguir exemplifica a execuo
do programa da Listagem 3 (o underline, _, representa o cursor e o contedo
entre < e > apenas informativo e no consta na sada do programa),
1. Incio da execuo. Aguarda x:
Fornecer valor de x: _

2. Valor de x fornecido:
Fornecer valor de x: 32_ <enter>

3. Impresso da resposta:
Fornecer valor de x: 32

4. Encerramento:
Fornecer valor de x: 32

o dobro de x vale 64

o dobro de x vale 64

_
_

possvel modificar a formatao de valores numricos impressos por


write (ou writeln). Isso inclui alterar tanto o comprimento global do nmero
(medido em caracteres) quanto o nmero de casas decimais utilizadas (no
caso de valores reais). O modificador dois-pontos (:) formata a impresso de
variveis inteiras e reais pelas respectivas sintaxes,
<varivel_inteira> : <comp>
<varivel_real> : <comp> : <num_decs>

O valor de uma varivel impresso com o total de caracteres dado em


comp, dos quais so reservados, para os decimais, o total de num_decs (caso
a varivel seja real). Se o comprimento comp insuficiente, ento usado um
valor de comprimento mnimo que inclua completamente a parte inteira do nmero. Se a representao requer menos que comp caracteres, ento a sada
ser preenchida com espaos em banco esquerda (alinhamento direita).
Se nenhuma formao especificada, ento o nmero escrito usando seu
comprimento natural, sem prefixao, caso seja positivo, e com um sinal de
menos, caso seja negativo. Nmeros reais no formatados so escritos em
notao cientfica. A seguir alguns exemplos de formatao,

Linguagem de Programao I

Var.
a
b
x
y

Tipo
integer
real
integer
real

Valor
81
37.92
35
6.7541

Exemplo
writeln(tenho,a,anos);
write(b);
write(Carros: , x:6)
Writeln(>,y:7:2, gramas);

Sada
tenho81anos
3.79200000000000E+001
Carros: 35
> 6.75 gramas

4.7. Tomando Decises


Dependendo do estado de uma varivel ou do resultado de uma expresso
um programa poder tomar uma deciso relativa a um caminho ou outro que
deva seguir. Na prtica isso significa desviar-se de ou ir direto para um trecho de cdigo especfico. Em termos de implementao uma deciso requer
que o programador codifique duas ou mais possibilidades de direes que um
programa pode seguir num dado instante de sua execuo. A direo escolhida s conhecida em tempo de execuo e pode mudar entre execues
distintas.
A linguagem Pascal suporta trs formas de estruturao de decises:
Deciso Unidirecional, Deciso Bidirecional e Decises Mltiplas.
4.7.1. Decises Unidirecional e Bidirecional
Uma deciso unidirecional aquela que deve decidir entre executar um bloco
de cdigo ou no fazer nada. Sua estrutura fundamental em Pascal dada por,
if <teste> then
<bloco>;

As palavras reservadas if (que significa se) e then (que significa ento) marcam o incio de um processo de deciso. Elas reservam entre si uma
expresso booleana, representada aqui por <teste>. Quando o resultado
verdadeiro o contedo de <bloco> executado. Do contrrio o processo se
encerra e o programa continua sua execuo. O ponto-e-vrgula (;) marca o
fim sinttico da gramtica de deciso de forma que se <teste> falso ento o
programa desvia sua execuo para logo aps esta marcao.
Uma deciso bidirecional aquela que deve decidir entre executar um
de dois blocos sem possibilidade de execuo de ambos. Sua estrutura fundamental em Pascal dada por,

31

32

Ricardo Reis Pereira

if <teste> then
<bloco_1>
else
<bloco_2>;

Quando <teste>, na deciso bidirecional, verdadeiro ento o cdigo


em <bloco_1> executado. Do contrrio o cdigo em <bloco_2> o ser. A
nova palavra reservada else (que significa seno) que provoca o desvio para
<bloco_2> quando o teste falha. A marcao de ponto-e-vrgula (;) aps <bloco_2> obrigatria pois indica o final sinttico da gramtica de deciso, mas
no ocorre aps <bloco_1> devido a estrutura no ter se concludo ainda.
Os blocos ilustrados nas estruturas de deciso anteriores podem possuir uma ou mais linhas de comando. Define-se linha de comando como uma
instruo de programa cuja sintaxe localmente independente. Cada linha de
comando em Pascal encerra num ponto-e-vrgula (;).
Quando existe apenas uma linha de comando numa deciso, ela deve
ser escrita logo aps o if..then. Para o compilador indiferente se isso for feito
na mesma linha de texto, como em,
if x>10 then writeln(x);

valor em x impresso somente se for maior


que 10.

ou em linhas de texto adjacentes, como em,


if (angulo<3.14) then
write(Ola Mundo!);

a string Ola Mundo s impressa se o


valor em angulo for inferior a 3.14.

Expresses booleanas completas podem fazer parte de uma estrutura


de deciso como em,
if (y<=80) and (x>76) then
readln(beta);

Se o valor em y for menor ou igual a 80 e ao


mesmo tempo o valor em x superior a 76,
ento o programa suspende provisoriamente
para ler um valor e armazen-lo em beta.

O compilador, entretanto, no reconhece, como pertencente deciso,


mais de uma linha de comando adjacente como em,

Linguagem de Programao I

if x<>100 or y<>67 then


write(x+y)
write(Oi);

Caso o valor em y seja diferente de 100 ou o


em y diferente de 67 ento a soma deles ser
impressa. A impresso da mensagem Oi,
apesar do alinhamento enganoso, independe
do teste pois no faz parte do bloco de
deciso.

No exemplo a seguir um else est presente (deciso bidirecional) e


cada bloco possui apenas uma linha de comando.
If p div 2 <> 0 then
writeln(p)
else

Se o valor em p for mpar ele ser impresso


integralmente, do contrrio ser impresso
metade de seu valor.

writeln(p/2);

Se uma sequncia formada por mais de uma linha de comando precisa de execuo condicional, ento a formao do bloco dever incluir as
palavras chaves begin e end. Estas so respectivamente dispostas antes e
depois das linhas de comando formando o novo bloco da estrutura if..then. As
estruturas finais, nas decises unidirecional e bidirecional, envolvendo blocos
de linhas de comando, so respectivamente:
if <teste> then

if <teste> then

begin

begin

<linhas de comando>

<linhas de comando>

end;

end else begin


<Linhas de comando>
end;

Decises podem ocorrer uma dentro da outra, ou seja, dentro de um


bloco de deciso pode haver uma outra deciso. Este mecanismo conhecido como aninhamento de decises e teoricamente no possui restries.
Para ilustrar o aninhamento de decises observe o esquema a seguir,

33

34

Ricardo Reis Pereira

if <teste1> then

if <teste2> then
<bloco1>

else
<bloco2>

else

if <teste3> then
<bloco3>

O if..then..else marcado com 1 bidirecional e aninha, no primeiro bloco, o if..then..else bidirecional marcado com 2 e no segundo bloco o if..then
unidirecional marcado com 3. Dessa forma bloco1 s executa se teste1 e teste2
forem verdadeiros; bloco2 s executa se teste1 for verdadeiro e teste2 for falso;
e por fim bloco3 s executa se teste1 falso e teste3 verdadeiro.
4.7.2. Decises Mltiplas
Uma deciso mltipla em Pascal aquela que lida com diversas possibilidades de caminhos a se seguir. Cada possibilidade representada por um bloco
de cdigo e apenas um destes blocos ter o contedo executado. Como as
expresses booleanas s encaminham para no mximo duas rotas, elas no
so a base de construo de uma deciso mltipla em Pascal. Ao invs disso
utilizam-se expresses aritmticas que resultem em valores inteiros. Desta forma cada bloco de deciso fica atrelado a um valor inteiro distinto. A estrutura
de deciso mltipla em Pascal tem sintaxe,
case <expressao_aritmetica_inteira> of
<rotulo_1>: <bloco_1>;
<rotulo_2>: <bloco_2>;

<rotulo_n>: <bloco_n>;
else <bloco_alternativo>;
end;

As palavras reservadas case..of (que significam caso..seja) formam a coroa da estrutura de deciso mltipla que necessariamente deve ser encerrada
em end mais ponto e vrgula. A expresso aritmtica entre case e of deve resultar num dos valores inteiros rotulados no cdigo do corpo da estrutura. Cada
rtulo deve ser seguido de dois pontos (:) e do bloco de deciso (encerrado em

Linguagem de Programao I

ponto e vrgula). Um bloco pode ser uma linha de comando ou um conjunto


delas encapsuladas por begin/end. Se o valor da expresso avaliada no se
igualar a nenhum dos rtulos, ser executado o bloco alternativo que marcado
por um else. O compilador no exige a presena de um bloco alternativo em
decises mltiplas. Alm de case..of..end; e da expresso aritmtica, a estrutura
exige no mnimo um rtulo e seu bloco.
A Listagem 4 ilustra o uso de decises mltiplas. Dependendo do valor
de op fornecido pelo usurio, um de cinco blocos ser executado. Atenue ao
bloco de rtulo 4 que encapsula uma deciso unidirecional demonstrando a
flexibilidade de associao de estruturas em Pascal.
Listagem 4
01 program operacoes_basicas;
02 var op: integer;
03

a, b: real;

04 begin
05

writeln('Menu');

06

writeln('1-- somar');

07

writeln('2 - subtrair');

08

writeln('3 - multiplicar');

09

writeln('3 - dividir');

10

readln(op);

11

writeln('valores:');

12

readln(a, b);

13

case op of

14

1: writeln('soma: ', a+b:0:3);

15

2: writeln('subtracao: ', a-b:0:3);

16

3: writeln('multiplicacao: ', a*b:0:3);

17

4: if abs(b)>1.0e-5 then

18
19

writeln('divisao: ', a/b:0:3);

20

else writeln('opcao invalida');


end;

21 end.

Se mais de uma valor resultante da expresso de entrada na estrutura


case..of precisar acionar o mesmo bloco, poder se usar a listagem de rtulos
como ilustrada a seguir,

35

36

Ricardo Reis Pereira

case x of
1,2,3: write('ok');
4: write('tchau!');
else write('invalido!');
end;

O primeiro bloco deste exemplo poder ser executado quando a varivel x conter 1, 2 ou 3. Uma listagem de rtulos usa vrgulas para separar os
rtulos que devem conduzir a um mesmo bloco.

4.8. Utilizando Laos


Laos, ou loops, so estruturas que permitem a repetio da execuo de um
mesmo trecho de cdigo. Eles possibilitam a automatizao de tarefas que
necessitam ser processadas diversas vezes. Denomina-se iterao cada uma
das repeties de um lao. A entrada de uma iterao o estado das variveis
que participam do cdigo do lao. A entrada de uma dada iterao pode, ou
no, afetar a entrada da iterao posterior. Uma ou mais linhas de comando
podem ser repetidos por um lao.
H trs estruturas de construo de laos em Pascal: laos com contador, laos de pr-teste e laos de ps-teste.

4.8.1. Laos com Contador


Um lao com contador aquele que utiliza uma varivel auxiliar denominada
contador, dois valores limites denominados limite inferior e limite superior e
um valor de passo. O lao inicia configurando o contador com o limite inferior.
Em cada iterao o contador adicionado do passo. O lao encerra quando
o contador se iguala ou extrapola o limite superior. Cada iterao se destaca
por ser processada com seu prprio valor do contador.
Em Pascal o contador necessariamente uma varivel de tipo inteiro.
Os limites devem possuir tambm valores inteiros e o passo vale sempre 1
(lao crescente) ou -1 (lao decrescente). Em laos crescentes o limite inferior
deve ser menor ou igual ao superior ou ento nenhuma iterao se proceder.
Em laos decrescentes ocorre exatamente o inverso. A estrutura de um lao
de contagem crescente em Pascal a seguinte:
for <contador> := <limite_inferior> to <limite_superior> do
<bloco_de_repetio>

Linguagem de Programao I

Esta estrutura utiliza as palavras reservadas for (que significa para), to


(que, neste contexto, significa at) e do (que significa faa). O operador de
atribuio (:=) parte integrante tambm da estrutura indicando que o contador sofre uma nova atribuio em cada iterao que se inicia. A estrutura de
um lao decrescente se distingue do crescente apenas pela substituio de to
pela palavra reservada downto, ou seja:
for <contador> := <limite_inferior> downto <limite_superior> do
<bloco_de_repetio>

O trecho a seguir ilustra o uso de laos de contagem crescentes,


for i := 1 to 100 do
write(i, );

Os valores de 1 a 100 so impressor


separados por espaos em branco. A varivel
i inteira.

Para gerar a mesma sada em ordem decrescente faz-se:


for i := 100 downto 1 do
write(i, ' ');

Os valores de 1 a 100 so impressor


separados por espaos em branco e em
ordem decrescente.

Quando mais de uma linha de comando est presente no mesmo lao,


deve-se utilizar um bloco begin/end similar quele utilizado em estruturas de
deciso. Esquematicamente tem-se,
for <contador> := <limite_inferior> to/
downto <limite_superior> do
begin
<linhas_de_comando>
end;

O trecho a seguir ilustra o uso de laos de contagem com mais de uma


linha de comando para repetio,
for i := 1 to 100 do
begin
k := 101 - i;
write(k, ' ');
end;

Os valores de 1 a 100 so impressos


separados por espaos em branco e em
ordem decrescente. Como o lao crescente
utilizou-se a varivel k, inteira, para calcular o
valor de impresso.

37

38

Ricardo Reis Pereira

possvel acoplar decises a laos fazendo toda estrutura de deciso se tornar o bloco da estrutura de repetio. Este mecanismo bastante flexvel e permite a implementao de algoritmos mais sofisticados. O
exemplo a seguir ilustra o acoplamento entre um lao de contagem e uma
deciso unidirecional,
for i := 1 to 1000 do
if (i mod 7 = 0) and
(i mod 3 <> 0) then
write(i, ' ');

Imprime inteiros entre 1 e 1000 que so


divisveis por 7 (o resto da diviso por 7
zero, ou i mod 7 = 0) e no divisveis por 3
(o resto da diviso por 3 no nulo, ou seja,
i mod 3 <> 0)

Laos podem ser aninhados em Pascal. Aninhar significa construir laos dentro de outros. No h restries da quantidade de aninhamentos numa
mesma construo. Cada lao em um aninhamento representa um nvel deste aninhamento. No exemplo,
for i:= 1 to 10 do
for j := 1 to 10 do
write(i*j);

h dois nveis de aninhamento. Diz-se que o segundo lao for est aninhado no primeiro. Semanticamente cada iterao do primeiro lao for provoca a execuo das dez iteraes do segundo lao for. Assim a instruo write
executada um total de 100 vezes. No exemplo,
for i:= 1 to 10 do begin
for j := 1 to 10 do write(i+j);
for j := 1 to 10 do write(i+j);
end;

o primeiro lao aninha outros dois laos que por sua vez no se aninham. Assim existem apenas dois nveis de aninhamento neste exemplo. O
comando write executado 200 vezes.

4.8.2. Laos com Pr-teste


Expresses booleanas podem ser utilizadas para montar laos. A mais usual
o lao com pr-teste no qual uma expresso testada no incio de cada
iterao. Enquanto o valor da expresso resultar em verdadeiro o lao deve

Linguagem de Programao I

prosseguir. Do contrrio ele se encerra. A sintaxe bsica de um lao pr-teste


em Pascal dada por,
while <expressao> do
<bloco>

As palavras reservadas while (que significa enquanto) e do (que significa faa) encapsulam a expresso booleana, <expressao>. Enquanto o valor
desta expresso for verdadeiro o cdigo em <bloco> repetido. Este bloco
pode ser formado por uma linha de comando ou por um conjunto delas desde
que encapsuladas pelas palavras reservadas begin/end;.
importante observar que o estado das variveis que formam a expresso devem ser modificadas dentro do bloco (ou por um agente externo ao programa), ou do contrrio o lao se tornar infinito (ou nunca ser executado).
No exemplo,
j := 1;
while j < 100 do
begin

os inteiros de 1 a 99 so impressos em
sada padro.

write(j, ' ');


j := j+1;
end;

a varivel j age como contador que iniciado fora do lao. A atribuio, j := j+1,
permite que a expresso booleana de entrada do lao, j<=100, diferencie sua
avaliao de uma iterao para outra. Na primeira iterao do lao, j contm 1
e este o valor impresso por write. Nas demais iteraes a incrementao de
j geram novas impresses. Quando 99 impresso o valor em j incrementado
para 100 na linha seguinte. Quando o teste de entrada executar na prxima
vez (e ele ainda o ser), o avaliador encontrar a instruo 100<100 que resulta falso: neste ponto o lao encerrado. Assim 99 o ltimo valor impresso.
O lao anterior pode ser facilmente substitudo por um lao de contagem. H situaes entretanto que os laos de contagem no podem resolver, como em,
x := 145;
while x > 0 do begin
write(x mod 2);
x := x div 2;
end;

Imprime a representao bin[aria de 145, de trs


para frente, ou seja, 10001001.

39

40

Ricardo Reis Pereira

4.8.3. Laos com Ps-Teste


Laos de ps teste tambm so baseados em expresses booleanas para
controle de fluxo. Neste caso entretanto o teste fica sada da estrutura. Em
Pascal a semntica de um lao ps-teste a seguinte: repetir um bloco de
cdigo at que determinada condio seja satisfeita. A sintaxe bsica de um
lao ps-teste em Pascal dado por,
repeat
<bloco>
until <expressao>;

As palavras reservadas repeat (que significa repita) e until (que significa


at) encapsulam o bloco de cdigo que deve ser repetido. Esta sintaxe, ao
contrrio das apresentadas at ento, dispensa o uso das palavras reservadas begin/end mesmo quando vrias linhas de comando constituem <bloco>.
O valor da avaliao de <expressao> precisa ser falso para garantir a prxima
iterao. No momento em que essa expresso avaliada como verdadeira,
o lao se encerra (repita at que isso seja verdade). Num lao ps-teste a primeira iterao sempre acontece (o que no verdade para laos pr-teste).
No exemplo,
j := 1;
repeat
write(j, ' ');
j := j+1;
until j>100;

os valores de 1 a 100 so impressos na sada padro. O teste de parada


aquele onde j vale 101 e por essa razo o 100 tambm impresso (lembre que
no exemplo anlogo apresentado com lao pr-teste, o 100 no era impresso).
A obrigatoriedade de execuo da primeira iterao num lao ps-teste pode ser interessante em algumas situaes como a mostrada na
Listagem 5. Este programa l uma quantidade indefinita de inteiros e exibe a mdia ao final. Para executar esta tarefa, um readln utilizado dentro
de um lao ps-teste (Linha-08) que recebe atravs de x cada um dos
valores fornecidos pelo usurio. Quando um valor zero for fornecido o
lao encerrado (o zero no entra na mdia). O teste da Linha-09, que
tambm est dentro do lao, faz com que o valor lido atravs de x, numa
dada iterao, seja acumulado em s (Linha-11). Esta varivel (previamen-

Linguagem de Programao I

te anulada fora do lao, Linha-04) conter, no final das iteraes, a somatria dos valores fornecidos pelo usurio (excluindo o zero). A varivel
auxiliar n permite a contagem de valores lidos. Ela anulada antes do
lao (Linha-05) e incrementada em uma unidade (Linha-12) cada vez que
um novo valor (no nulo) lido atravs de x. A mdia final naturalmente
s/n e impressa na Linha-16 desde que o valor em n no seja nulo (verificao feita pelo teste da Linha-15). Se n contm zero, a mensagem da
Linha-18 impressa ao invs da mdia.
Listagem 5
01

program media;

02

var s, x, n: integer;

03

begin

04

s := 0;

05

n := 0;

06

repeat

07

write('Valor: ');

08

readln(x);

09

if x <> 0 then

10

begin

11

s := s+x;

12

n := n+1;

13

end;

14

until x=0;

15

if n>0 then

16
17

write('media: ', s/n :0:2)


else

18
19

write('nenhum valor fornecido!');


end.

4.8.4. Break e Continue


Quebrar um lao significa suspender seu fluxo de execuo e continuar a execuo do programa a partir da primeira instruo que sucede o corpo estrutural do lao quebrado. Para quebrar um lao (seja com contador, de pr-teste
ou de ps-teste) a linguagem Pascal conta com uma instruo especfica cuja
palavra reservada break. Utilizando break possvel, por exemplo, reescrever o lao da Listagem-1.5 utilizando while..do conforme segue,

41

42

Ricardo Reis Pereira

while True do begin


write('Valor: ');
readln(x);
if x = 0 then break;
s := s+x;
n := n+1;
end;

Este lao teoricamente infinito porque a expresso booleana de teste simplesmente True. Entretanto, quando zero fornecido, o teste do if
se torna verdadeiro e break acionado, quebrando o lao. Observe que os
incrementos de s e n no so mais protegidos por um corpo de deciso simplesmente porque no sero mais executados aps a quebra do lao. O efeito
deste lao o mesmo daquele na Listagem-1.5.
Break tem efeito apenas sobre o lao em que est embutido. Numa
situao onde laos esto aninhados, break afeta o lao que o executa. Por
exemplo em,
while <expressao_1> do begin
...
while <expressao_2> do begin
...
if <expressao_3> then break;
end;
end;

break quebra o segundo while (se <expressao_3> verdadeira). Podem haver vrias quebras, dependendo do total de iteraes do primeiro while. J no
caso seguinte,
while <expressao_1> do begin
...
while <expressao_2> do begin
...
end;
if <expressao_3> then break;
end;

Linguagem de Programao I

a execuo de break quebra o primeiro while e impede novas iteraes do


segundo while.
H situaes em que necessrio executar parcialmente o cdigo de um
bloco de um lao e passar para a iterao seguinte (sem quebra). Pascal possui
uma instruo para isso de palavra reservada continue. Neste exemplo,
for i := 1 to 100 do begin
if (i mod 2 = 0) continue;
write(i, ' ');
end;

apenas os nmeros mpares, entre 1 e 100, so impressos. Isso acontece


porque quando o teste i mod 2 = 0 verdadeiro, continue executado obrigando o lao a ignorar as instrues restantes do bloco (neste caso apenas
o write) e passar para a iterao seguinte. A expresso i mod 2, que o resto
de diviso por 2 do valor em i, s retorna zero quando i contm um valor par o
que justifica a impresso apenas de valores mpares.

4.8.5. Desvio Incondicional


O desvio incondicional um artifcio que permite ao programador desviar o fluxo
de execuo para outras partes do programa. Este artifcio no tem uso recomendado sequer existindo em outras linguagens. Pascal constri desvio incondicional com uma instruo de palavra reservada goto. A sintaxe de goto ,
goto <rotulo>:

onde <rotulo> um identificador declarado pelo programador numa sesso


de rtulos e repetido no ponto do programa para onde o fluxo de execuo
dever ser desviado. Esquematicamente,
label <rotulo>; // sesso de rtulos
begin
<rotulo>:

// destino do desvio

...
goto <rotulo>;
end.

A palavra reservada label inicia uma sesso de rtulos em Pascal.


Declarar um rtulo significa simplesmente definir para ele um identificador
nesta sesso. Se mais de rtulo existir, eles devero ser separados por vrgulas. O local do programa para onde o desvio deve conduzir deve conter o
rtulo ps-fixado de dois pontos (:).

43

44

Ricardo Reis Pereira

Listagem 6
01

program desvio;

02

var

03
04
05
06

n: integer;
label
rot;
begin

07

n := 1;

08

rot:

09

write(n, ' ');

10

n := n+1;

11

if n<100 then goto rot;

12

end.

Na Listagem 6 o rtulo para desvio incondicional, rot, declarado na


Linha-05 e utilizado na Linha-08. O goto na Linha-11 provoca o desvio que,
neste caso, est condicionado pelo if na mesma linha. O efeito da associao destes elementos um lao: a varivel n funciona como contador sendo
configurada como 1 antes do rtulo (Linha-07) e incrementada da unidade
(Linha-10) depois dele; alm disso if provoca desvio para rot enquanto o valor
em n for menor que 100. o resultado final a impresso dos valores entre 1 e
99 (pelas sucessivas chamadas a write na Linha-09).

4.9. Funes e Procedimentos


Mdulos so normalmente distribudos em colees chamadas unidades.
Mdulos de uma unidade tm sintaxe e funcionalidade de um programa e por
essa razo so tambm denominados de subprogramas. Subprogramas podem ser implementados em arquivos de unidades (veja Captulo-5 para mais
detalhes sobre construo de unidades) ou no prprio arquivo principal do
programa. Mdulos codificados no arquivo principal do programa so disponveis apenas para este programa. Cada mdulo Pascal possui seu prprio
nome e corpo de cdigo que deve ser disposto antes do bloco principal e logo
aps as sesses de declarao (apenas aquelas que os mdulos precisam).
Existem dois tipos de mdulos em Pascal: procedimentos e funes.
Tanto um quanto o outro podem requerer por informao adicional no momento
em que so requisitados, mas apenas as funes devolvem (obrigatoriamente)
um resultado tangvel (ou seja, que pode ser armazenado numa varivel). Toda
informao adicional requerida por um mdulo recebida atravs de variveis
auxiliares denominadas de argumentos ou parmetros do mdulo.

Linguagem de Programao I

Um mdulo (procedimento ou funo) pode contar com zero ou mais


argumentos. A requisio de um mdulo denominada de chamada do mdulo e o resultado de uma funo de retorno da funo. A chamada de um
mdulo construda utilizando o nome do mdulo ps-fixando os argumentos
(quando existentes) entre parnteses e separados por vrgulas. Se no h
argumentos, apenas o nome do mdulo efetua sua chamada. Se uma funo
chamada ela deve estar no lado direito de uma atribuio ou fazer parte de
uma expresso.
O exemplo,
teste(23, x);

constri uma chamada ao mdulo teste que requer dois argumentos de entrada. J em,
teste;

a chamada no requer argumentos e assim parnteses no so necessrios.


O mdulo teste nesses exemplos pode ser tanto um procedimento quanto
uma funo. Caso seja funo, o retorno perdido por ausncia de um agente
que resgate o retorno. Um exemplo de resgate de retorno de uma funo pode
ser escrito assim,
y := teste(23, x);

ou integrada numa expresso como,


y := 23*teste*(23, x) + h*4.2;

onde y atua como resgatador direto no primeiro caso e indireto no segundo. Caso teste seja um procedimento nestes ltimos exemplos, o compilador
acusar erro de sintaxe. Vale enfatizar que todas essas construes devem
encerrar em ponto-e-vrgula.
Para construir um procedimento sem argumentos em Pascal deve-se
utilizar a seguinte sintaxe,
procedure <identificador_do_nome>;
{ declaraes }
begin
{ corpo do procedimento }
end;

Procedimentos em Pascal devem iniciar com a palavra chave procedure seguida de um identificador (nome do mdulo). A linha contendo a palavra
reservada procedure chamada de prottipo ou interface do procedimento.
Sesses de declarao so suportadas, mas os recursos declarados so de
uso nico do procedimento. O bloco begin/end, restringe o corpo de cdigo
do procedimento e deve ser encerrado em ponto-e-vrgula. O programa da
Listagem 7 ilustra o uso de procedimentos Pascal sem argumentos.

45

46

Ricardo Reis Pereira

Listagem 7
01 program usando_procedimento;
02

procedure meu_teste;

03

begin

04
05

writeln('chamada feita com sucesso');


end;

06 begin
07

meu_teste;

08 end;

Na Listagem 7 o procedimento meu_teste compreende as Linhas 02 a


05 e sua chamada implica a impresso de uma mensagem fixa (Linha-04).
O corpo principal do programa constitudo unicamente por uma chamada
ao procedimento meu_teste (Linha-07) e dessa forma a sada do programa
dever ser,
chamada feita com sucesso

Quando o procedimento possui argumentos a sintaxe possui aspecto,


procedure <identificador_do_nome>(<grupo_1>;
<grupo_2>;...;<grupo_n>);
{ declaraes }
begin
{ corpo do procedimento }
end;

Similar a uma sesso de declarao de variveis, o par de parnteses


ps-fixo ao nome do procedimento encapsula grupos de variveis (argumentos ou parmetros) separados por ponto-e-vrgula. Um grupo de argumentos
uma listagem de variveis, de mesmo tipo separadas por vrgulas (quando
mais de uma est presente) e encerrada com :<tipo_do_grupo>.

Linguagem de Programao I

Listagem 8
01 program teste_de_procedimentos;
02 var
03

n: integer;

04 { mdulos }
05 procedure print(n: integer);
06 begin
07

writeln('O quadrado de ', n, ' vale ', n*n);

08 end;
09
10 procedure listar(m, n: integer);
11 var i: integer;
12 begin
13

for i := m to n do

14

print(i);

15 end;
16 { programa principal }
17 begin
18

readln(n);

19

listar(0, n);

20

listar(2*n, 3*n);

21 end.

O programa da Listagem 8 trs dois procedimentos, print e listar, cujos


prottipos esto respectivamente nas Linhas 05 e 10. O procedimento print
imprime uma mensagem formatada baseada no valor do argumento n. O procedimento listar usa um lao para imprimir vrias linhas de texto formatadas
impressas por chamadas a print.
A chamada de um mdulo a partir de outro legal em Pascal desde que
o mdulo chamado seja definido antes do mdulo chamador. O procedimento
listar possui dois argumentos que recebem os valores dos limites inferior e
superior do lao de impresso (Linhas 13 e 14). Por fim o programa principal faz duas chamadas independentes a listar (Linhas 19 e 20) cujos valores
de repasse aos argumentos so calculados com base do valor de n lido na
Linha-18. Um exemplo de sada deste programa ,

47

48

Ricardo Reis Pereira

3
O quadrado de 0 vale 0
O quadrado de 1 vale 1
O quadrado de 2 vale 4
O quadrado de 3 vale 9
O quadrado de 6 vale 36
O quadrado de 7 vale 49
O quadrado de 8 vale 64
O quadrado de 9 vale 81

O mecanismo de passagem de argumentos funciona da seguinte forma:


quando um mdulo chamado ele deve receber um total de entradas (separadas por vrgulas) igual ao nmero de argumentos presentes em seu prottipo.
Essas entradas podem ser valores constantes, variveis, expresses ou mesmo chamadas de outros mdulos. Cada entrada resolvida antes da execuo do mdulo e gera um valor que atribudo ao argumento correspondente
no mdulo. Esse tipo de atribuio denominada implcita por no utilizar o
operador de atribuio (:=). Assim, no programa da Listagem-1.8, Linha-20, as
expresses 2*n e 3*n so avaliadas e seus valores atribudos respectivamente
aos parmetros m e n do procedimento listar.
Para construir uma funo em Pascal deve-se utilizar a seguinte sintaxe,
function <ident_do_nome> (<grupo_1>,<grupo_2>,,
<grupo_n>): <tipo_de_retorno>;
{ declaraes }
begin
{ corpo da funo }
end;

Funes em Pascal devem iniciar com a palavra chave function seguida de um identificador (nome do mdulo). O prottipo de uma funo inclui
ainda o tipo da informao que a funo retorna (tipo de retorno) marcado
com dois-pontos seguido da palavra reservada do tipo. A estrutura de sesses
de declarao e de cdigo do corpo de uma funo so idnticos aos dos procedimentos. As funes ainda contam com uma varivel interna, cujo nome
o mesmo da funo e o tipo o de retorno, e cujo valor armazenado antes do
trmino da funo justamente o valor de retorno desta funo.

Linguagem de Programao I

O programa da Listagem 9 possui prottipos de uma funo (fat) na


Linha-05 e de um procedimento (listar) na Linha-13. A funo fat calcula o fatorial do valor recebido pelo argumento n. A terminao :integer no prottipo indica
que a funo retorna um valor inteiro. Para calcular o fatorial, a varivel interna
fat recebe inicialmente, na Linha-08, 1 (elemento neutro da multiplicao). O
lao da Linha-09 evolui o valor em fat por sucessivas multiplicaes at que esta
varivel contenha o valor do fatorial do valor em n.
Quando a funo encerra, o ltimo valor em fat o do fatorial procurado
e justamente esse o valor retornado. O procedimento listar faz diversas chamadas funo fat (atravs do lao na Linha-16) para imprimir uma lista dos
fatoriais entre zero e o valor no argumento de entrada max. A chamada funo
fat realizada diretamente dentro do writeln que recebe e imprime o valor do fatorial. Apesar de no ser necessrio neste contexto, uma varivel intermediria
poderia receber o valor da chamada deixando explicito que algum est de fato
manipulado a sada da funo. Neste caso a funo listar se reescreveria assim,
procedure listar(max: integer);
var i, res: integer;
begin
for i := 0 to max do begin
res := fat(i);
writeln('Fatorial de ', i, ' = ', res);
end;
end;

onde res a varivel intermediria. Um exemplo de sada do programa ,


5
Fatorial de 0 = 1
Fatorial de 1 = 1
Fatorial de 2 = 2
Fatorial de 3 = 6
Fatorial de 4 = 24
Fatorial de 5 = 120

49

50

Ricardo Reis Pereira

Listagem 9
01

program teste_de_funcoes;

13

procedure listar(max: integer);

02

var

14

var i: integer;

15

begin

03

n: integer;

04

16

05

function fat(n: integer): integer;

17

06

var i: integer;

18

07

begin

19

for i := 0 to max do
writeln('Fatorial de ', i, ' = ', fat(i));
end;

08

fat := 1;

20

09

for i := 1 to n do

21

readln(n);

10

fat := fat*i;

22

listar(n);

11

end;

23

begin

end.

12

Funes sem argumento, assim como procedimentos, so possveis


em Pascal. O prottipo,
function teste: integer;

pertence a uma funo que no recebe parmetros e retorna um valor inteiro.


Esse tipo de funo, devido a ausncia de argumentos, aparentemente retorna sempre o mesmo valor. Entretanto elas podem usar outras informaes do
prprio programa ou mesmo do sistema para gerar diferentes sadas.
Variveis declaradas em mdulos, sejam eles procedimentos ou funes,
so denominadas de variveis locais. So variveis locais tanto os argumentos de entrada quanto aquelas declaradas na sesso interna de declarao do
mdulo. Na Listagem 9 o procedimento listar possui duas variveis locais, max
e i, ao passo que a funo fat possui trs, n, i e fat. Variveis locais so de uso
exclusivo do mdulo que as declara e por essa razo o mesmo nome pode ser
utilizado para batizar variveis que esto em mdulos diferentes.
Variveis declaradas na sesso de declaraes do programa so denominadas de variveis globais. Elas podem ser utilizadas por todo o programa
incluindo os mdulos e o programa principal. A restrio a essa globalidade
a posio da sesso de declarao do programa que pode inclusive ficar
entre dois mdulos, como em,

Linguagem de Programao I

function teste_1(x: integer): real;


begin
teste_1 := x*x;
end;

var
y: real;

procedure teste_2;
begin
writeln('ol');
end;

Em casos como esse a varivel global (neste exemplo, y) s visvel


nos mdulos que sucedem a declarao e no programa principal. Assim teste_1 no visualiza y, apenas teste_2.
Quando uma varivel local possui o mesmo nome de uma varivel global (como n na Listagem 9), o mdulo ignora a varivel global e qualquer operao afeta apenas a varivel local.
As regras que definem o acesso das variveis num programa, brevemente discutidas nesta sesso, so denominadas de regras de escopo. Para
entender mais sobre procedimentos, funes em Pascal, veja Captulo 5.

5. Estudos de Caso
Os estudos de casos a seguir aplicam a sintaxe bsica da linguagem Pascal
estudada neste captulo.

5.1. Converso Celsius em Fahrenheit


A expresso que relaciona temperaturas em Celsius (C) e Fahrenheit (F)
a dada por:

C (F 32)
=
5
9

51

52

Ricardo Reis Pereira

onde C a temperatura em Celsius e F em Fahrenheit. Isolando F fcil


construir um programa de converso de Celsius para Fahrenheit como se v
na Listagem 10.
Listagem 10
01

program Celsius_para_Fahrenheit;

02

var

03
04

C, F: real;
begin

05

write('Valor de temperatura em Celsius: ');

06

read(C);

07

F := C*9/5 + 32;

08

writeln(C:0:1, 'oC = ', F:0:1, 'oF');

09

end.

Na Linha-07, v-se F isolado do lado esquerdo da atribuio e uma expresso sem parnteses do lado direito. O primeiro e o terceiro argumento do
writeln, Linha-08, fazem as temperaturas serem escritas com uma casa decimal e o mnimo de caracteres (o zero em :0:1 causa este efeito). A sada final
do programa aps o usurio fornecer uma temperatura de 27C a seguinte:
Valor de temperatura em Celsius: 27
27.0oC = 80.6oF

5.2. Anlise do IMC


O IMC, ou ndice de massa corprea, de uma pessoa, determinado
pela equao:

IMC =

p
2
h

onde p o peso (em quilogramas) e h a altura (em metros). Quando o IMC


menor que 25, diz-se que o indivduo est magro; se o valor maior que 25,
diz-se que est gordo; por fim um IMC no intervalo fechado de 20 a 25 acusa
peso ideal. O programa da Listagem-1.11 resolve o problema do clculo e
anlise do IMC.

Linguagem de Programao I

Listagem 11
01

program Calculo_IMC;

10

02

var

11

03
04

peso, altura, imc: real;

if (imc<20) then

12

begin

writeln('Magro!')

13

05

write('Fornecer altura em metros: ');

14

06

readln(altura);

15

07

write('Fornecer peso em kg: ');

16

08

readln(peso);

17

09

write('IMC = ', imc:0:1, '. ');

imc := peso/(altura*altura);

18

else
if (imc>25) then
writeln('Gordo!')
else
writeln('Normal!');
end.

No programa da Listagem 11 a deciso na Linha-11 divide o processo


entre as pessoas que so magras (imc menor que 20) e as que no so
(imc maior ou igual a 20). Quando a entrada no de uma pessoa magra, o
bloco do else (Linha-13) entra em atividade e dispara a deciso bidirecional
na Linha-14. Este novo processo se divide entre os gordos (sucesso do teste
da Linha-14) e os no gordos. Como a primeira condio imposta foi a de no
magros, ento a impresso da Linha-17 ocorre quando simultaneamente nem
imc menor que 20 e nem maior que 25.
Um exemplo de sada do programa da Listagem 11 mostrado a seguir:
Fornecer altura em metros: 1.85
Fornecer peso em kg: 90
IMC = 26.3. Gordo!

5.3. Maior de Trs Valores


Listagem 12
01

program Maior_De_Tres;

10

writeln(a)

02

var

11

else

03
04

a,b,c: integer;
begin

12
13

05

write('Fornecer numeros: ');

14

06

readln(a,b,c);

15

07

write('Max(',a,',',b,',',c,') = ');

16

08

if a>b then

17

09

if (a>c) then

18

writeln(c)
else
if b>c then
writeln(b)
else
writeln(c);
end.

53

54

Ricardo Reis Pereira

A Listagem 12 resolve o problema de determinao do maior de trs


nmeros inteiros fornecidos. Este programa possui trs processos bidirecionais de deciso estando os dois ltimos aninhados no primeiro. O if..then..
else do primeiro processo est nas Linha 08 e 13 dividindo o processo de deciso entre a situao em que o valor em a maior que o em b e a situao
em que o valor em a menor ou igual ao em b. Quando a primeira situao
ocorre o segundo processo de deciso (entre as Linhas 09 e 12) acionado.
Do contrrio o terceiro processo de deciso (Linhas 14 a 17) tomar lugar. Apenas
uma entre quatro chamadas de impresso (Linhas 10, 12, 15 ou 17) ocorrer de
fato. Um exemplo de sada do programa da Listagem-1.12 o seguinte:
Fornecer numeros: 5 11 3
Max(5,11,3) = 11

5.4. Ordenao de Trs Nmeros


Seja o problema de escrever em ordem crescente trs valores inteiros dados. Uma soluo utilizar variveis para armazenar os valores dados e
depois efetuar trocas convenientes de forma que os valores nelas fiquem
em ordem crescente (na ordem de apresentao das variveis). Uma troca de valores entre duas variveis envolve necessariamente uma terceira varivel (auxiliar) e ocorre em trs fases: (i) a varivel auxiliar copia o
contedo da primeira varivel; (ii) a primeira varivel copia o contedo da
segunda varivel; (iii) a segunda varivel copia o contedo da varivel auxiliar. Sem varivel auxiliar perder-se-ia o valor de uma das variveis de
entrada. O programa da Listagem 13 resolve o problema da ordenao de
trs valores inteiros.
Listagem 13
01

program Ordenacao_Tres_Numeros;

13

t := a;

02

var

14

a := c;

03
04

a, b, c, t: integer;
begin

15

c := t;

16

end;
if b>c then begin

05

write('Fornecer numeros: ');

17

06

readln(a,b,c);

18

t := b;

07

if a>b then begin

19

b := c;

08

t := a;

20

c := t;

09

a := b;

21

end;

10

b := t;

22

writeln('Ordenacao: ',a,', ',b, ', ',c);

11
12

end;
if a>c then begin

23

end.

Linguagem de Programao I

No programa da Listagem 13 possui trs decises no aninhadas. Cada


uma delas representa uma possvel troca entre duas variveis. Por exemplo,
a deciso na Linha-07, quando obtm xito, troca o contedo das variveis a
e b. A varivel auxiliar t e o bloco com begin-end necessrio porque trs
linhas de comando esto presentes. O algoritmo por trs das trocas explicado a seguir.
Para ordenar a sequencia deve-se primeiramente fazer a conter o menor
dos trs valores. Para isso esta varivel deve ser comparada com b (Linha-07)
e c (Linha -12) e, possivelmente, trocada com elas (trocas das Linhas 08 a 10
e Linhas 13 a 15). Uma vez que o menor valor agora est em a, o valor intermedirio estar em b ou c, impasse facilmente resolvido por um nico teste,
neste caso, o da Linha-16. Finalizado os trs testes, e feitas as devidas trocas
(nenhuma troca pode ocorrer!), a, b e c contero nesta ordem os valores de
entrada em ordem crescente. Abaixo ilustra-se um exemplo de sada do programa da Listagem 13,
Fornecer numeros: 32 11 9
Ordenacao: 9, 11, 32

5.5. Somando Quadrados


Seja o problema de somar o quadrado dos inteiros entre 0 e um limite superior
dado. O programa da Listagem 14 sugere uma soluo.
Listagem 14
01
02
03
04
05
06
07
08
09
10
11

program Somatorio_Quadratico;
var

i, max, S: integer;

begin

S := 0;

write('Fornecer limite superior: ');


readln(max);

for i := 0 to max do
S := S + i*i;

writeln('Soma de quadrados entre 0 e ', max, ' = ', S);

end.

Na Linha-05 a varivel S, que conter ao final do processamento o somatrio desejado, recebe zero marcando o incio do somatrio. O lao da
Linha-08 tem como limite superior a prpria varivel max indicando que o somatrio vai de fato at o valor lido na Linha-07. A expresso do lado direito da
atribuio na Linha-09 contm a prpria varivel que sofrer a atribuio (S).

55

56

Ricardo Reis Pereira

Como um processo de atribuio processa da direita para a esquerda


ento o valor da expresso resolvido antes da atribuio propriamente dita
desassociando os papis que S desempenha em cada lado. A rigor o valor
em S atualizado com um novo valor calculado a partir de seu anterior. Como
se trata de um lao, ento S ser atualizada vrias vezes. Em cada iterao
o quadrado do valor em i (i*i) adicionado ao valor corrente de S e este novo
valor atribudo a S causando um efeito de acmulo. No final o valor impresso
na Linha-10 ser a somatria quadrtica entre zero e o valor em max. Um
exemplo de sada do programa mostrado a seguir,
Fornecer limite superior: 100
Soma de quadrados entre 0 e 100 = 10670

5.6. Somatrio Condicional


Seja o problema de somar todos os nmeros inteiros positivos menores
do que 500 que sejam divisveis por 7 mas que no sejam divisveis por 3. O
programa da Listagem 15 sugere uma soluo.
Listagem 15
01

program Somatorio_Condicional;

06

02

var

07

03
04
05

n, S: integer;
begin

if (n mod 7 = 0) and (n mod 3 <> 0) then

08
09

S := 0;

for n := 0 to 500 do

10

S := S + n;
writeln('Soma = ', S);
end.

A varivel S utilizada para armazenar a soma de inteiros pretendidos.


Por essa razo ela previamente configurada como zero (Linha-05) indicando que nada ainda foi somado a ela. O lao na Linha-06, associado a deciso
na Linha-07, condiciona a atribuio na Linha-08. A expresso S := S + n representa dois estgios de S, um antes (lado direito da atribuio) que soma
seu valor na iterao anterior ao valor em n; e um depois (lado esquerdo da
atribuio) que sobrepe em S o novo valor obtido da expresso.
O efeito destes acoplamentos um contnuo acmulo em S dos valores
em n que suprem o teste na Linha-07. Este teste condiciona que o resto da
diviso por 7 deve ser nula (ou seja, divisvel por sete) e simultaneamente que
o resto da diviso por 3 no deve ser nula (ou seja, no divisvel por 3). A sada
do programa da Listagem 15 ,
Soma = 12096

Linguagem de Programao I

5.7. Nmeros Primos


Nmeros primos so nmeros naturais que so divisveis apenas por
um e por si mesmos (o menor nmero primo 2). Para testar se um natural n primo, deve-se dividi-lo pelos naturais no intervalo |2;|, onde
2<n. Se todas as divises forem inexatas (no divisibilidade), n ser primo. Se entretanto, neste processo de divises, uma delas for exata, o restante do intervalo (se ainda houver) dever ser ignorado e n considerado
no primo.
Listagem 16
01

program primos;

16

02

17

03

function e_primo(n: integer): boolean; 18

04

var d: integer;

05
06

res: boolean;
begin

e_primo := res;
end;

19

var i, cnt: integer;

20

begin

21

i := 2;

07

d := 2;

22

cnt := 0;

08

res := true;

23

while

09

while d*d <= n do begin

24

10

if (n mod d) = 0 then begin

cnt < 20 do begin

if e_primo(i) then begin

25

write(i, ' ');


cnt := cnt+1;

11

res := false;

26

12

break;

27

end;

end;

28

i := i+1;

d := d + 1;

29

13
14
15

end;

30

end;
end.

A funo e_primo na Listagem 16 recebe um inteiro e determina se ele


ou no primo. Para tanto o retorno da funo um booleano (true indica que n
contm um primo e false um no primo). A funo e_primo funciona conforme
explicado a seguir. O lao da Linha-09 faz o valor em n ser dividido por todos
os valores do intervalo de teste (veja pargrafo anterior).
O controle deste intervalo feito com a varivel d: o limite inferior (menor
primo) definido na Linha-07 e o superior testado pela expresso booleana
do lao (a incrementao feita na Linha-14). A varivel res controla o estado
(primo ou no primo) do valor em n e dessa forma, como primeira hiptese,
recebe true (um nmero primo at que prove o contrrio).
O teste na Linha-10 verifica a divisibilidade do valor em n pelo valor
corrente em d (numa dada iterao de while). Quando o valor em n primo,
todos estes testes falham, o lao principal se desenvolve normalmente e o
valor retornado (Linha-16) true (como esperado). Se um destes testes ob-

57

58

Ricardo Reis Pereira

tm sucesso, significa que o valor em n no primo e desta forma o lao no


precisa mais continuar. Por essa razo res redefinido para false (Linha-11) e
o lao quebrado (Linha-12).
O programa principal na Listagem 16 utiliza a funo e_primo para imprimir na sada padro os primeiros 20 nmeros primos. A varivel i inicia com
valor 2 (linha-21) e incrementado continuamente na Linha-28 por ao do
lao while (Linha-23). Cada vez que o valor em i primo (teste da Linha-24)
seu valor impresso (Linha-25) e o contador de primos, cnt (previamente anulado na Linha-22), incrementado de uma unidade (Linha-26). Como o teste de
while baseado em cnt, o efeito final ser a impresso de uma quantidade fixa
de primos (20, neste exemplo). A sada do programa ,
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71

Atividades de avaliao
1. Faa um programa para o computador calcular o quadrado de um nmero.
2. Faa um programa para o computador determinar o valor mximo entre
dois nmeros inteiros A e B.
3. Faa o programa para calcular a mdia das notas de uma turma de 20
alunos.
4. Faa um programa que receba as dimenses de uma caixa dgua e
calcule o seu volume.
5. Modifique o programa da questo 04 de forma que a sada seja a quantidade em metros quadrados de material necessrio a construo da caixa. Considere a presena de tampa.
6. Dois alunos fizeram trs provas cada um cujas notas so conhecidas
Faa um programa que diga qual deles tem a maior mdia.
7. Construa um programa que receba dois valores inteiros a e b e retorne
como sada ab.
8. Construa um programa que receba os lados de um tringulo e indique se
ele existe ou no. Em caso afirmativo imprimir tambm: a) se ele retngulo, acutngulo ou obtusngulo; b) valor de sua rea.
9. Faa um programa para calcular o fatorial de um nmero N inteiro dado.

Linguagem de Programao I

10. Faa um programa que determine se um nmero divisvel ou no por outro.


11. Faa um programa para calcular a soma de todos os nmeros inteiros
menores que 500 e que no sejam divisveis por 3 e terminem no dgito 2.
12. Considere o problema do polinmio de segundo grau. Construa programa que receba como entrada os trs coeficientes destes polinmios,
exiba suas razes se existirem, seno informe isso como sada.
13. Considere uma moeda que contenha cdulas de 50,00, 10,00, 5,00 e
1,00. Considere ainda que caixas eletrnicos de um banco operem com
todos os tipos de notas disponveis, mantendo um estoque de cdulas
para cada valor. Os clientes deste banco utilizam os caixas eletrnicos
para efetuar retiradas de uma certa quantia. Escreva um programa que,
dado o valor da retirada desejada pelo cliente, determine o nmero de
cada uma das notas necessrias para totalizar esse valor, de modo a
minimizar a quantidade de cdulas entregues.
14. Construir programa que receba os valores naturais a e M e tenha como
sada o valor da seguinte somatria:

59

Captulo

Strings e Arrays

1. Caracteres e Strings
A maior parte de toda informao gravada em mdias digitais, incluindo aquela
disponvel via internet, est em formato texto. Textos, em computadores, so
representados por strings que por sua vez so representadas pela unio sequencial (concatenao) de unidades grficas de informao denominadas
caracteres. A presena de recursos de manipulao de strings numa linguagem de programao essencial. Tais recursos so normalmente disponibilizados atravs de bibliotecas ou de comandos nativos (previstos no projeto
original da linguagem e implementados juntamente com ela). Pascal conta
com recursos nativos para a manipulao de texto.

1.1. Caracteres
Pascal possui o tipo de dados primitivo char para representar caracteres independentes (que no fazem parte de uma string). Assim,
var
ch: char;

declara um caractere em Pascal. Em Pascal os caracteres utilizam


1-byte e seguem a codificao ASCII. Em ASCII os caracteres so representados por sete bits e so baseados no alfabeto ingls (o oitavo bit no
representativo). O total de caracteres 128 sendo 33 no imprimveis (como
o caso dos caracteres de controle utilizados nos bastidores de softwares processadores de texto).

ASCII:
abreviao de American
Standard Code for
Information Interchange
que significa Cdigo
Padro Americano para o
Intercmbio de Informao.

62

Ricardo Reis Pereira

cod

ASCII

32

cod

ASCII

cod

ASCII

cod

ASCII

cod

ASCII

42

52

62

>

72

33

43

53

63

73

34

44

54

64

74

35

45

55

65

75

36

46

56

66

76

37

47

57

67

77

38

&

48

58

68

78

39

49

59

69

79

40

50

60

<

70

80

41

51

61

71

81

cod

ASCII

cod

ASCII

cod

ASCII

cod

ASCII

cod

ASCII

82

92

102

112

122

83

93

103

113

123

84

94

104

114

124

85

95

105

115

125

86

96

106

116

126

87

97

107

117

88

98

108

118

89

99

109

119

90

100

110

120

91

101

111

121

Tabela 9 - Tabela de cdigo ASCII

Uma constante caractere deve ser especificada em Pascal entre aspas


simples, como nos exemplos,
'a'

'A'

'$'

'7'

'_'

' '

Conforme padro ASCII, h distino entre caracteres maisculos e


minsculos, no caso de letras, e no h correspondncia entre caracteres
numricos e constantes numricas (assim, por exemplo, 7 diferente de 7).
Cada caractere ASCII possui um cdigo (valor inteiro) exclusivo denominado cdigo ASCII do respectivo caractere. A Tabela 9 Ilustra os cdigos
ASCII dos caracteres imprimveis cuja faixa 32 a 126 (128 possveis com
7-bits menos os 33 no imprimveis).
Um caractere Pascal pode ser representado em cdigo tambm pela
prefixao do smbolo # ao cdigo ASCII. Assim a expresso #65 equivalente
a A. Quando o caractere no imprimvel, essa notao torna-se uma opo
representao em cdigo do caractere. Alguns importantes caracteres no

Linguagem de Programao I

imprimveis possuem larga aplicao em programao possuindo inclusive


teclas de acionamento prprias (no teclado do computador). So exemplos,
#10

ENTER

// concatenado a #13 em alguns sistemas

#27 ESC
#9 TAB
#8 BACKSPACE

Para permutar entre representao numrica e grfica, os caracteres


em Pascal contam com os comandos nativos ord e chr. O comando ord recebe
um caractere e retorna seu cdigo ASCII ao passo que chr recebe um cdigo
ASCII e retorna o caractere equivalente. Assim, por exemplo, ord(A) retorna 65
e chr(65) retorna A.
Caracteres podem ser impressos por write/writeln desde que sejam imprimveis. Caracteres no imprimveis causam outros efeitos (no necessariamente na sada padro) que dependero da plataforma utilizada. So exemplos de impresso de caracteres imprimveis,
write('A');

// A

writeln('B', '%');

// B%

write(#65, ord('X'), chr(35));

// A98#

O resultado de impresso de um caractere imprimvel, seja fornecido


com a notao de aspas simples, seja com a notao de # (ou do comando
chr), sempre simblica. A impresso da sada de uma chamada a ord sempre um valor inteiro (valor do cdigo ASCII).
Caracteres so dados ordinais dispostos na sequncia de seus respectivos cdigos ASCII. Dessa forma podem ser comparados com operadores
relacionais ou utilizados como contadores em laos for. Para construir, por
exemplo, uma tabela de letras minsculas e seus respectivos cdigos ASCII,
implementa-se,
var
ch: char;
begin
for ch := 'a' to 'z' do
writeln(ch, ':

', ord(ch));

end.

Aritmtica envolvendo caracteres pode ser executada indiretamente


pelo uso de seus respectivos cdigos ASCII. Um exemplo interessante a
converso de um caractere letra minscula para maiscula. A ideia subtrair
o cdigo de um dado caractere letra minuscula pelo cdigo do caractere a

63

64

Ricardo Reis Pereira

(107) e somar resultado ao do cdigo do caractere A (75). Como as letras, tanto maisculas como minsculas, so sequencias contnuas (veja Tabela-2.1),
este procedimento deve fazer retornar um cdigo ASCII conveniente para a
verso maiscula. A funo maiuscula na Listagem 17 recebe um caractere,
verifica se uma letra minuscula (Linha-03) e, caso seja, retorna sua verso
maiscula (calculada pela expresso na Linha-04), do contrrio retorna o prprio caractere de entrada (Linha-06).
Listagem 17
01

function maiuscula(ch: char): char;

02

begin

03

if (ch>='a') and (ch<='z') then

04

maiuscula := chr( ord(ch) 32 );

05

eles

06
07

// -32 75-107

maiuscula := ch;
end.

1.2. Strings Curtas e Longas


Uma string uma concatenao de caracteres. Em Pascal a palavra reservada string denota o tipo para declarao de strings. Strings possuem especificao opcional de tamanho, ou seja, no obrigatrio informar quantos caracteres a string dever conter. No exemplo a seguir uma string sem especificao
de tamanho declarada,
var
st1: string;

Neste outro exemplo a declarao feita com especificao de tamanho,


var
st2: string[120];

O tamanho, quando especificado, definido entre colchetes, [ ], e ps-fixado palavra reservada string. Strings de tamanho definido em Pascal s
suportam at 255 caracteres. Especificar um valor maior que esse causa um
erro de compilao. A restrio de tamanho imposta por este tipo de construo classifica as strings declaradas como strings curtas. Tais strings podem
ser alternativamente declaradas pela palavra reservada shortstring (sem especificao de tamanho). Exemplo,
var sst: shortstring;

Linguagem de Programao I

As strings longas em Pascal correspondem s strings sem restries de


tamanho. Elas permitem a concatenao de qualquer quantidade de caracteres. So declaradas utilizando-se o tipo ansistring. Exemplo,
var lst: ansistring;

Uma string longa processada mais lentamente que as curtas devido


a natureza de sua implementao. Por uma questo de performance, sempre
que possvel, aconselhvel utilizar strings curtas.
O compilador Pascal poder interpretar uma declarao de string sem
especificao de tamanho como sendo uma string curta ou longa dependendo do acionamento da diretiva {$H}. A diretiva {$H-} instrui o compilador a considerar uma declarao de string sem definio de tamanho como uma string
curta de tamanho 255 ao passo que {$H+} instrui tratar-se de uma string longa.
Se nenhuma destas duas diretivas estiver presente o padro {$H-} ser aplicado. Logo existe equivalncia tanto entre os quatro cdigos,

Diretivas de Prprocessamento ou
simplesmente Diretivas:
tratam-se de cdigos
escritos entre chaves, { },
pr-fixados pelo smbolo $
e que servem normalmente
para ligar, desligar ou
modificar recursos do
compilador. Exemplo, {$I+}.

program teste;

program teste;

program teste;

program teste;

var

{$H-}

var

var

var

x:
string[255];

x:
shortstring;

{}

{}

x: string;
{}

x: string;
{}

quanto nos dois que seguem,


program teste;

program teste;

{$H+}

var

var

x: ansistring;
x: string;

{}

{}

1.3. Operaes com Strings


Em Pascal, atribuies podem ser diretamente realizadas em strings longas e
curtas pelo operador de atribuio, :=. As atribuies a seguir so vlidas,
var
a: string;
b: ansistring;
begin
a := 'este e um teste';
b := 'este e um novo teste';
end.

65

66

Ricardo Reis Pereira

Constantes de tipo string so dispostas entre aspas simples, . No


exemplo anterior o contedo de duas strings constantes so copiados para as
variveis string a e b. A primeira atribuio feita a uma varivel string conhecida como inicializao da string.

O tamanho de uma string


equivale ao mximo de
caracteres que ela pode
suportar. O comprimento
de uma string representa
o total de caracteres que
ela utiliza em determinado
momento. O comprimento
sempre menor ou igual
ao tamanho.

Variveis de tipo string podem ser atribudas diretamente a outras mesmo quando seus comprimentos so distintos. Quando uma string recebe o
contedo de outra string, seu contedo primeiramente eliminado da memria
e em seguida sua referncia (o ponto da memria ao qual a string se refere)
mudado para o mesmo da string atribuda. Por exemplo em,
A := minha casa;
B := meu trabalho;
B := A;

faz a string meu trabalho ser eliminada da memria e a string minha casa passar
a ser referenciada tanto por A quanto por B. A priori acredita-se que qualquer
mudana em A afetar B (e vice-versa) numa nova atribuio. Mas isso no
acontece. Se algum cdigo mais adiante tentar modificar A ou B (no apenas
ler, mas modificar!), uma cpia da string ser feita antes da modificao e atribuda a quem solicitou a mudana (A ou B). Novamente as strings possuiro
referncias distintas (uma mantida e outra modificada). Exemplo,
A := 'minha casa';
// A no endereo 1
B := 'meu trabalho';
// B no endereo 2
B := A;
// A e B no endereo 1 e nada mais em 2
A := 'minha vida';

// B no endereo 1 e A no endereo 3

Os comandos write e writeln podem conter strings nas suas respectivas


listas de impresso sendo possvel tanto imprimir constantes strings quanto o
contedo de variveis strings. Exemplo,
fulano := beltrano;
writeln(Meu nome e , fulano);

Os comandos read e readln podem ser usados para ler strings curtas e
longas sem adicional de sintaxe como em,
read(fulano);

onde fulano uma string (curta ou longa). Os argumentos string de read/readln


precisam ser variveis. Caso a string repassada no caiba na varivel, ocorrer um erro em tempo de execuo.
A concatenao ou fuso de strings em Pascal construda com o operador de concatenao, +, cujo smbolo o mesmo da soma aritmtica mas a
semntica (comportamento) diferente. Podem ser concatenadas constantes
strings, strings em variveis ou associaes. Exemplos,

Linguagem de Programao I

x := 'ola' + ' !';


y := x + 'mundo';

// ola!
// ola!mundo

z := x + y;

// ola!ola!mundo

onde x, y e z so variveis e podem ser tanto strings longas como curtas.


Concatenaes geram novas strings. Por exemplo em,
x := x + fim;

onde x uma string. Uma nova string criada do lado direito da atribuio pela
concatenao do contedo de x e fim. Com a atribuio, a antiga string inicial
em x eliminada da memria e x passa a se referenciar nova string oriunda
da concatenao.
Strings podem ser tambm concatenadas com caracteres, como em,
x := Caractere de ASCII 38 e: + #38; // Caractere de ASCII 38 e: &

Strings no podem ser concatenadas a tipos numricos diretamente.


Para inserir numa string valores que esto armazenados em inteiros ou reais
deve-se primeiramente converter os valores numricos em strings e por fim
efetuar a concatenao. A unidade system possui o comando str para a converso de inteiros ou reais em strings. A sintaxe bsica deste comando ,
str(V, S);

onde V denota o valor (inteiro ou real) para ser convertido e armazenado na string
S (curta ou longa). A Listagem 18 ilustra o uso de str. As converses nas Linhas
09 e 10 colocam respectivamente nas variveis si e sp as verses string do inteiro
em idade e do real em peso. Observe que possvel converter a parte do valor real
que realmente interessa utilizando a notao de dois-pontos (:0:2 denota todas as
casas antes da vrgula e apenas duas depois). A string final gerada pela concatenao da Linha-11, armazenada na varivel s e impressa na Linha-12.
Listagem 18
01
02
03

program usando_str;
var

04

s, si, sp: string;

05
06
07

idade: integer;
peso: real;

begin

idade := 25;

08

peso := 60.5;

09
10
11
12
13

str(idade, si);

str(peso:0:2, sp);

s := 'Ela tem '+si+' anos de idade e pesa '+sp+'


quilos';
writeln(s);

end.

67

68

Ricardo Reis Pereira

Nmeros tambm podem ser convertidos em strings. O comando em


system para essa tarefa val cuja sintaxe bsica ,
val(S, V, P)

onde S representa a string a ser convertida em nmero e V a varivel numrica


(inteira ou real) que receber o resultado da converso. A converso de valor
numrico em string susceptvel a erro e por essa razo existe um terceiro
argumento de controle denotado pela varivel inteira P. Se a converso ocorre
normalmente, o valor final de P ser zero, do contrrio conter um valor maior
que zero (posio na string S onde ocorreu o erro de converso).
A Listagem 19 Ilustra o uso do comando val. O programa l um valor da
entrada padro e imprime seu quadrado. Para assegurar que o valor digitado
realmente um inteiro criou-se a funo inteiro_valido que possui um lao infinito (Linhas 08 a 16) quebrado na Linha-14 somente quando um inteiro valido
dado via entrada padro. Em cada iterao deste lao a string entrada usada
para receber uma informao aleatria do teclado (Linha-10).
Na Linha-11, val tenta executar a converso da string em entrada utilizando a varivel interna inteiro_valido como receptculo e err como controle de
converso. O teste da Linha-12 decide entre a impresso de uma mensagem
de erro (err tem um valor diferente de zero) ou pela quebra do lao (err contm
zero). Neste ltimo caso o ultimo valor da varivel interna inteiro_valido, antes da
quebra do lao, coerente. Como a funo termina logo aps o fim do lao e
o ltimo valor da varivel interna inteiro_valido o retorno da funo, ento x, no
programa principal, recebe necessariamente um inteiro vlido. Um exemplo
de sada deste programa ,
Valor inteiro> 90u
inteiro invalido!
Valor inteiro> 7.8
inteiro invalido!
Valor inteiro> /
inteiro invalido!
Valor inteiro> 7
O quadrado vale 49

Linguagem de Programao I

Listagem 19
01

program valor_seguro;

02
03

function inteiro_valido: integer;

04

var

05

entrada: string;

06

err: integer;

07
08

begin
repeat

09

write('Valor inteiro> ');

10

readln(entrada);

11

val(entrada, inteiro_valido, err);

12

if err<>0 then

13

writeln('inteiro invalido!')

14

else

15
16
17

break;
until False;

// Lao infinito

end;

18
19

var x: integer;

20

begin

21

x := inteiro_valido;

22

writeln('O quadrado vale ', x*x);

23

end.

Os caracteres de uma string podem ser acessados de forma individual


utilizando o operador de indexao, [ ]. Este operador ps-fixado varivel
string e deve conter um inteiro (ndice) com valor entre 1 e o comprimento da
string. No exemplo,
s := 'abcdefg';
write(s[3], s[2]);

// cb

ch := s[7];

// g

onde s e ch so respectivamente uma string e um caractere, write imprime o


terceiro e o segundo caracteres de s ao passo que ch copia o stimo.
O comando length da unidade system recebe uma string como entrada e
retorna seu comprimento. No caso de strings curtas com tamanho predefinido
o comprimento consiste apenas dos caracteres gravados e no do valor definido na declarao. Exemplo,

69

70

Ricardo Reis Pereira

var
s: string[100];

// string curta de tamanho predefinido

begin
s := 'abcdefg';
writeln( length(s) );

// 7

end.

Apesar de s ter comprimento predefinido 100, o valor impresso por writeln


7. O comprimento predefinido representa a quantidade mxima de caracteres que a string pode suportar. denominado comprimento teto. J o valor
retornado por length denominado comprimento utilizado. O comando length
funciona normalmente com cadeias longas e curtas com ou sem comprimento predefinido.
O programa da Listagem 20 ilustra o uso de length. Neste programa uma
string, lida via entrada padro, reescrita de trs para a frente. O lao de contagem decrescente na Linha-09 varre todos os ndices da string s de trs para
frente (inicia em length(s) e vai at 1) e faz write na Linha-10 imprimir o caractere
correspondente a posio visitada. O efeito a impresso da string de entrada
em ordem reversa. Um exemplo de sada do programa ,
Entrada> abcdefg
Inverso> gfedcba

Listagem 20
01

program de_tras_pra_frente;

07

02

var

08

write('Inverso> ');
for i := length(s) downto 1 do

03

s: string[100];

09

04

i: integer;

10

05
06

begin

readln(s);

write( s[i] );

11

write('Entrada> ');

12

writeln;
end.

O acesso individual a caracteres proporcionado pelo operador de indexao leitura/escrita, ou seja, pode ser usado tanto para ler os caracteres
quanto para modific-los. Um exemplo interessante a converso de uma
string em sua verso maiscula. Utilizando a funo maiuscula da Listagem 17,
pode-se escrever,
read(s);
for i := 1 to length(s) do
s[i] := maiuscula( s[i] );
writeln(s);

// ver Listagem-2.1

Linguagem de Programao I

71

onde s pode ser uma string curta ou longa. O lao de contagem crescente varre a cadeia completa e modifica cada caractere para a sada
da chamada da funo maiuscula (que por sua vez recebe o caractere da
cadeia de entrada).
Strings podem ser comparadas com operadores relacionais. O critrio
de comparao adotado pelo compilador Pascal denominado critrio lexicogrfico. exatamente o mesmo critrio utilizado para fazer comparaes
e ento ordenar uma lista, por exemplo, de nomes de pessoas. Dadas duas
strings, a comparao lexicogrfica executa comparaes entre caracteres
de uma e de outra na mesma posio.
As comparaes partem do incio de cada string e se mantm enquanto
os caracteres forem idnticos ou uma das cadeias no extrapolar seu ndice
mximo. Quando surge no processo dois caracteres distintos, a comparao
termina e ser lexicograficamente maior a string cujo caractere comparado
tiver maior cdigo ASCII. Exemplos,
'casar' > 'casado'

// TRUE pois ASCII de 'r' maior que o de 'd'

'MEDALHA' > 'MEDICO'

// FALSE pois ASCII de 'A' menor que o de 'I'

'mata' <= 'pata'

// TRUE pois ASCII de 'm' menor que o de 'p'

'cantar' <> 'cantora'

// TRUE pois encontrou 'a' diferente de 'o'

Quando a menor string prefixo da maior ento no existe caractere de


desempate. Neste caso a de maior comprimento considerada lexicograficamente maior. Exemplos,
'casa' > 'casado'

// FALSE pois a primeira prefixo da segunda

'folhagem' > 'folha'

// TRUE pois a segunda prefixo da primeira

'cantor' <= 'cantora'

// TRUE pois a primeira prefixo da segunda

Duas strings so idnticas em Pascal deste que tenham mesmo comprimento e mesma sequencia de caracteres.
Para obter uma substring de uma dada string, utiliza-se o comando
copy, unidade system, cuja sintaxe bsica ,
copy(S, I, cont);

onde S denota uma string, curta ou longa, da qual se deseja obter a


substring, I denota a posio dentro da string onde deve iniciar a substring e
cont a quantidade de caracteres que devem ser extrados. A nova string gerada
por copy dve ser atribuda a uma varivel string, fazer parte de uma expresso
ou ser repassada a como argumento de um mdulo. Exemplos,

Substring:
String formada por uma
subsequencia contnua
dos caracteres de uma
outra string. Na string
abcdefghij so exemplos
de substrings abc, cdefg
e ij.

72

Ricardo Reis Pereira

s := 'ABCDEFG';

Quebrar uma string


significa subdividi-la
em substrings cuja
concatenao origina
a string original. Por
exemplo, a string abcxyzw
pode ser quebrada no
conjunto {abc, xyzw} ou
em {ab, cxy, yz, w}.

t := copy(s, 3, 4);

// CDEF

writeln( copy(t, 2, 2)

// DE

);

s := s + copy(s,4,4);

// ABCDEFGDEFG

onde s e t so variveis strings. A primeira extrao atribuda a t, a segunda repassada como parmetro de writeln e a terceira componente
de uma expresso.
Strings podem ser inseridas em outras, ou seja, possvel, utilizando
um nico comando, quebrar uma string W em W1 e W2 e depois fazer W se
tornar W1 + X + W2 onde X a string inserida. Para inserir uma string em outra,
utiliza-se o comando insert, unidade system, seguindo a sintaxe bsica,
insert(S1, S2, p);

onde S1 representa a string que ser inserida e S2 a string que sofrer a insero. A posio de insero em S2 dada pelo inteiro p. No exemplo,
s := '123';
tex := 'abcdef';
insert(s, tex, 4);

// abc123def

a string s inserida na string tex. A insero quebra tex em abc e def e depois
atribui a tex o resultado da concatenao abc + 123 + def. Insert no possui retorno (procedimento) mas modifica a string passada como segundo argumento.
Para remover caracteres de uma string utiliza-se o comando delete, unidade system, de sintaxe bsica,
delete(S, p, cont);

onde S denota a string que sofrer retrao, p a posio onde deve principiar a deleo e cont a quantidade de caracteres que devero ser eliminados.
Internamente delete efetua a quebra da string e concatena as partes que devem ser mantidas. Exemplo,
s := 'abcdefgh';
delete(s, 3, 4);
writeln(s);

//

abgh

onde s uma string. A deleo ocorre a partir da posio 3 e elimina 4 caracteres. Delete quebra S nas substrings {ab. cdef. gh }, concatena a primeira com
a terceira e atribui o resultado a S. O comando delete, assim como insert, no
possui valor de retorno mas modifica a string que recebe como argumento.

Linguagem de Programao I

2. Arrays
Uma array uma estrutura de dados que permite o armazenamento sequencial de dados de mesmo tipo. Cada unidade constituinte de uma array denominada clula e o tipo de dados comum a todas as clulas denominado
tipo base. Uma array referenciada em cdigo por uma nica varivel e suas
clulas por uma associao desta varivel, do operador de indexao, [ ], e de
um ou mais valores de ndices.
Strings so exemplos de arrays cujo tipo base char mas comumente
no recebem o ttulo (de array) por possurem propriedades prprias no presentes em arrays de outros tipos base. Manteremos a conveno distinguindo
strings de arrays. Arrays no podem ser diretamente concatenadas, comparadas, impressas por write/writeln ou lidas por read/readln. Veremos alguns cdigos
que permitiro gerar comportamentos equivalentes em arrays.
O comprimento de uma array igual ao total de clulas que a constitui e
pode tambm ser determinado pelo comando length que receber, neste caso,
a varivel array como argumento. Arrays no fazem distino entre comprimento teto e comprimento utilizado como nas strings. Dessa forma length retorna sempre o total de clulas alocadas em memria para a array, independente
do contedo.
Arrays em Pascal podem ser estticas e dinmicas. Uma array esttica aquela cujo comprimento predefinido na declarao e no pode ser
mais modificado em tempo de execuo. Arrays dinmicas so aquelas cujo
comprimento pode ser modificado a qualquer momento da execuo (tanto
expandindo como contraindo).
As clulas de arrays, sejam estticas ou dinmicas, suportam leitura/escrita
deste que o ndice utilizado esteja na faixa apropriada. A faixa apropriada em arrays estticas pode ser definida pelo programador tendo comumente como limite
inferior o valor 1. O ndice inferior de arrays dinmicas sempre zero.
Arrays podem possuir mais de uma dimenso. Uma array unidimensional representa, por exemplo, uma lista e necessita de um nico ndice para
referenciar suas clulas. Uma array bidimensional representa, por exemplo,
uma tabela ou uma matriz e precisa de dois ndices. Uma array tridimensional
utiliza trs ndices e assim por diante. No h restries em Pascal no nmero
de dimenses que uma array pode possuir.

73

74

Ricardo Reis Pereira

2.1. Arrays Unidimensionais


Para declarar uma array esttica unidimensional em Pascal deve-se utilizar a
seguinte sintaxe bsica,
var
<variavel> : array[<indice_inferior>..<indice_superior>] of <tipo_base>;

As palavras reservadas array e of significam arranjo e de. Os dois pontos


sequenciais, .., separam os dois valores limites de ndice sendo o primeiro o
inferior e o segundo o superior. Colchetes, [ ], devem necessariamente conter
a faixa de ndices. O tipo base aps of tambm obrigatrio. Para criar uma
array de 100 valores inteiros pode-se escrever,
var
x: array[1..100] of integer;

neste exemplo os ndices limites so 1 e 100. Para alterar uma dada clula de
x usa-se,
x[34] := 152;

neste caso a trigsima quarta clula recebe o valor 152. Para fazer x receber
os 100 primeiros mpares, pode-se escrever,
for i := 1 to length(x) do
x[i] := 2*i - 1;;

onde i um inteiro. Para programadores de linguagem C, acostumados


com arrays de ndice inicial zero, a declarao de x pode alternativamente
ser,
var
x: array[0..99] of integer;

Observe que essa alterao de ndices mantem o comprimento 100 da


array x de forma que para construir um lao de varredura completa deve-se
fazer o limite inferior zero e o superior length(x)-1, como em,
for i := 0 to length(x)-1 do
x[i] := 2*i + 1;

// o sinal deve mudar de para +

Os comandos low e high, unidade system, retornam respectivamente os


limites inferior e superior dos ndices de uma array. Utilizando tais comandos o
exemplo anterior pode ser reescrito para,
for i := low(x) to high(x) do
x[i] := 2*( i-low(x) ) + 1;

em zero

// i-low(x) inicia sempre

Linguagem de Programao I

A memria ocupada por uma varivel array a somatria das memrias de suas clulas e pode ser determinada pelo comando nativo sizeof. No
exemplo,
var
y: array[1..20] of Longint;

// usa 80-bytes

a quantidade de bytes de y determinada por sizeof(y). Isso equivalente ao


produto length(y)*sizeof(Longint).
Uma array esttica pode ser atribuda diretamente para outra desde que
possuam tipos compatveis. Duas arrays possuem tipos compatveis quando
possuem o mesmo comprimento, a mesma faixa de ndices e o o mesmo tipo
base. Assim no exemplo,
var
A: array[1..100] of integer;
B: array[1..100] of integer;
C: array[0..99] of integer;

A e B so compatveis e as atribuies entre elas, utilizando um nico :=,

so permitidas. Entretanto, apesar do mesmo comprimento e tipo base,


C no compatvel com A e B. Tentativas de atribuies diretas entre arrays
no compatveis so reportadas como erro na compilao.
Listagem 21
01

program arrays_compativeis;

02

var

03

i, n: integer;

04

A: array[1..5] of integer;

05

B: array[1..5] of integer;

06

begin;;

07

n := 257;

08

for i := low(A) to high(A) do begin

09

A[i] := n;

10

n := n div 2;

11

end;

12

B := A;

13

for i := low(B) to high(B) do B[i] := B[i]*2;

14

for i := 1 to 5 do

15
16

writeln(A[i], ' ', B[i]);


end.

75

76

Ricardo Reis Pereira

A Listagem 21 Ilustra a atribuio direta entre arrays compatveis. A


inicializada por um lao de contagem entre as Linhas 08 e 11 e seu novo
contedo diretamente atribudo (copiado) para B na Linha-12. O lao na
Linha-13 duplica os valores nas clulas da array B recm carregada. O lao
entre as Linhas 14 e 15 imprime o contedo das duas arrays. A sada deste
programa tem aspecto,
257 514
128 256
64 128
32 64
16 32

Este exemplo tambm mostra a possibilidade de modificar e escrever


arrays utilizando laos. Nestas situaes cada clula recebe tratamento individual numa dada iterao de um lao que efetua varredura completa. Nas
Linhas 14 e 15 do programa da Listagem - 21 foi inclusive possvel processar
duas arrays no mesmo lao.
Arrays unidimensionais constantes podem ser construdas em Pascal.
A sintaxe adicional, em complementao declarao de constantes e de
variveis arrays, so parnteses separando os valores invariveis, como no
exemplo,
const
x: array[1..10] of integer = (2, 4, 9, 3, 11, 13, 7, 5, 21, 19);

O acesso s clulas de constantes arrays, como x, feito exatamente


da mesma forma que variveis arrays. Entretanto o acesso somente leitura
(os valores nas clulas no podem ser modificados). Toda constante array em
Pascal precisa ser tipada.

2.2. Arrays Multidimensionais


Arrays multidimensionais so suportadas em Pascal. Para declarar, uma array
bidimensional esttica pode-se tanto escrever,
var
x: array[1..100] of array[1..50] of byte;

// primeira sintaxe

quanto,
var
x: array[1..100, 1..50] of byte;

sendo a segunda sintaxe preferencial.

// segunda sintaxe

Linguagem de Programao I

77

Cada dimenso de uma array multidimensional esttica em Pascal possui sua prpria faixa de ndices encapsuladas pela palavra reservada array e
por colchetes individuais (primeira sintaxe) ou separadas por vrgulas e envolvidas num colchete comum (segunda sintaxe). Para acessar uma clula de
uma array multidimensional, seja para leitura seja para modificao, deve-se
informar os ndices na quantidade que forem as dimenses e nas faixas previstas na declarao. No caso de x tem-se por exemplo,
x[20, 17] := 65;

que altera para 65 o contedo da clula da array x cujo ndice da primeira


dimenso 20 (deve estar entre 1 e 100) e da segunda dimenso 17 (deve
estar entre 1 e 50).
Em caso de arrays bidimensionais, como x, comum fazer a analogia
com matrizes (matemtica) dizendo ser a primeira dimenso a das linhas e a
segunda a das colunas. Assim x possui 100 linhas e 50 colunas. Abstraindo a
array seguinte como uma matriz quadrada de ordem cinco,
var
mat: array[1..5, 1..5] of real;

ento um cdigo para carreg-la com a matriz identidade ,


for lin := 1 to 5 do
for col := 1 to 5 do
if col = lin then
mat[lin, col] := 1.0
else
mat[lin, col] := 0.0;

onde col e lin so inteiros. O aninhamento dos laos neste exemplo permite varrer para cada linha (primeiro lao) as clulas em cada coluna (segundo lao).
O total de iteraes portanto o nmero de clulas da array (25 neste caso).
Este nmero de iteraes tambm o de decises tomadas com if.
So exemplos de arrays de quantidade de dimenses superior a dois,
var
A: array[1..5, 1..10, 1..100] of boolean;
Teste: array[1..2, 1..2, 1..2, 1..5] of double;

Na prtica arrays unidimensionais e bidimensionais so suficientes para


resoluo da maioria dos problemas.
Internamente arrays estticas, independentemente da quantidade de
de dimenses que possuam, so representadas em memria por sequencias

Matriz Identidade:
Na matemtica a matriz
quadrada (nmero de
linhas igual ao de colunas)
cujos elementos so todos
nulos, exceto aqueles da
diagonal principal (diagonal
cujo ndice da linha e da
coluna so idnticos), que
valem 1.

78

Ricardo Reis Pereira

contguas de clulas sendo o aspecto multidimensional um recurso da linguagem para melhorar a capacidade de abstrao.

2.3. Arrays Dinmicas


Uma array dinmica em Pascal uma array especial cujo comprimento
definido somente em tempo de execuo. A sintaxe bsica para declarao
de uma array dinmica idntica a de uma esttica, exceto pela ausncia de
ndices limites. A sintaxe bsica de declarao ,
var
<variavel>: array of <tipo_base>;

Exemplo,
var
x: array of integer;

onde x uma array dinmica de inteiros.


Aps a declarao, uma array dinmica ainda no est disponvel ao
uso. necessrio antes alocar memria para ela. A unidade system fornece o
comando setlength para este fim. Sua sintaxe bsica, para arrays unidimensionais, ,
setlength(<array_dinamica>, <comprimento>);

onde o primeiro argumento a varivel array dinmica que solicita a alocao


de memria e o segundo o total de clulas que a array dever ter aps a chamada de setlength. Para alocar em x memria de 100 inteiros utiliza-se,
setlength(x, 100);

Em outras linguagens de programao funes de uso similar recebem


a quantidade de bytes para alocar e no o nmero de clulas como em setlength. A memria de fato alocada o valor do segundo argumento de entrada
multiplicado pelo tamanho do tipo base (no caso de x, integer). O comando
length retorna zero antes da primeira chamada a setlength e o valor exato de
comprimento, depois. Assim a sada do cdigo,
var x: array of integer;
begin
write( length(x) );
setlength(x, 25);
writeln( ' ', length(x) );
end.

deve ser,
0 25

Linguagem de Programao I

Se outras chamadas a setlength ocorrerem no mesmo programa para


uma mesma array dinmica, ocorrer a chamada realocao de memria
sendo tanto possvel retrair quanto expandir memria. Na realocao com
expanso outro espao em memria alocado e o contedo do antigo
copiado para ele. A varivel array, que solicitou a realocao, passa ento
a se referenciar a nova memria alocada e a antiga limpa. Na realocao
com retrao, dados so perdidos. Realocao em excesso compromete
desempenho do programa.
Quando uma array dinmica perde o contexto (o programa termina ou um
mdulo que a criou retorna) ento ela eliminada automaticamente da memria.
O ndice inferior de uma array dinmica sempre zero. Assim para carregar
uma array dinmica com os primeiros 100 nmeros mpares deve-se escrever,
var
i: integer;
w: array of integer;
begin
setlength(w, 100);
for i := 0 to length(w)-1 do
w[i] := 2*i + 1;
end.

Listagem 22
01 program arrays_dinamicas;
02 var
03

i: integer;

04

x, y: array of integer;

05 const
06

max = 5;

07 begin
08

setlength(x, max);

09

for i := 0 to max-1 do

10

x[i] := 2*i+1;

11

y := x;

12

for i := 0 to max-1 do

13
14

y[i] := 2*y[i];

15

for i := 0 to max-1 do

16 end.

writeln( x[i], '

', y[i] );

79

80

Ricardo Reis Pereira

A atribuio direta de uma array dinmica a outra no gera uma nova array dinmica. Ao invs disso passam a existir duas referncias ao mesmo local
de memria. Isso ilustrado no programa da Listagem - 22. A array x alocada
na Linha-08 e recebe os valores dos primeiros cinco mpares (Linhas 09 e 10).
A atribuio direta na Linha-11 cria uma nova referncia para a memria
de x, ou seja, x e y agora se referem a mesma array dinmica. Nas Linhas 12
e 13 o contedo de cada clula da array dinmica y multiplicado por dois o
que equivalente a dobrar os valores das clulas de x. Assim as impresses
nas linhas 14 e 15 geram a sada,
2 2
6 6
10 10
14 14
18 18

Para declarar arrays dinmicas com mais de uma dimenso utiliza-se


a primeira sintaxe de declarao de arrays estticas, mas sem ndices limite.
Exemplos,
var
A: array of array of integer;

// array dinmica bidimensio-

nal
B: array of array of array of integer;

// array dinmica tridimensio-

nal

Arrays dinmicas multidimensionais so tambm alocadas com setlength. Surge nele um argumento adicional para cada comprimento de dimenso
novo. Exemplos,
setlength(A, 2, 5);

// aloca comprimentos 2 e 5 para as duas dimenses

da array A
setlength(B, 5, 3, 4);

// aloca comprimentos 5, 3 e 4 para as trs dimenses

da array B

Utilizando arrays dinmicas bidimensionais possvel generalizar o


exemplo da matriz identidade. A declarao geral se torna,
var
mat: array of array of real;

e a alocao,
readln(n);
setlength(mat, n, n);

onde n um inteiro fornecido via entrada padro. A inicializao fica portanto,

Linguagem de Programao I

for lin := 0 to length(mat)-1 do


for col := 0 to length( mat[0] )-1 do
if col = lin then
mat[lin, col] := 1.0
else
mat[lin, col] := 0.0;

onde lin e col so inteiros. Observe que na segunda chamada a length o argumento mat[0]. De fato se mat tivesse, por exemplo, cinco dimenses, o comprimento delas seriam calculados pelas respectivas instrues,
length( mat );
length( mat[0] );
length( mat[0][0] );
length( mat[0][0][0] );
length( mat[0][0][0][0] );

3. Estudos de Caso
3.1. Palndromos Numricos
Um palndromo qualquer sequencia de informao cuja disposio dos elementos na ordem reversa (de trs para a frente) origina a mesma sequencia.
As strings asa, abbba e tomamot so exemplos de palndromos. Palndromos
numricos so inteiros cuja sequencia de dgitos so palndromos. Exemplos
so 2, 121, 5665 e 10101.
A funo e_palind da Listagem 23 determina se seu argumento de entrada ou no um palndromo numrico. A primeira hiptese da funo de que
seja e por essa razo a varivel interna e_palind recebe true na Linha-05. O lao
entre as Linhas 08 e 11 determina quantos dgitos, t, possui o valor da entrada
em n. Para isso uma cpia deste valor feito para x e t iniciado com zero.
Cada iterao do lao reduz o valor em x para o quociente de sua razo por dez (Linha-10) e o lao encerra quando zero alcanado. Como t
incrementa da unidade em cada iterao, esta varivel conter no final das
iteraes a quantidade de dgitos do valor em n. Na Linha-12 a array dinmica
digs alocada para registrar os dgitos do valor em n e o lao entre as Linhas
13 e 16 carrega os dgitos. O lao decrescente para preencher os dgitos de
trs para frente (porque nesta ordem que eles so extrados). A expresso,
n mod 10, Linha-14, retorna o ltimo dgito do valor em n ao passo que, n := n div
10, Linha-15, fora sua extrao.

81

82

Ricardo Reis Pereira

Utilizando a array digs, agora convenientemente carregada, o lao entre


as Linhas 17 e 21 determina se existe um palndromo. Para tanto o contedo
das clulas de ndices entre 0 e (t div 2)-1 (esta expresso representa exatamente o maior valor de ndice da primeira metade da array excluindo o valor
central em caso de arrays de comprimento mpar) so comparadas com suas
imagens (os ndices da segunda metade da array calculados neste caso pela
expresso, t-i-1).
Para que digs contenha um palndromo, todas as clulas da primeira
metade (posies i) devem possuir o mesmo contedo que suas clulas imagem (posies t-i-1). Basta uma nica equivalncia no ocorrer (deciso da
Linha-18) para o status de e_palind ser revertido para false (Linha-19) e o lao
ser quebrado (Linha-20). Entretanto, se n contiver um palndromo numrico,
esta quebra nunca suceder e o retorno da funo (valor de e_palind) ser o da
hiptese inicial (true).
Listagem 23
01 function e_palind(n: longint): boolean;
02 var digs: array of byte;
03

x, t, i: integer;

04 begin
05

e_palind := true;

06

x := n;

07

t := 0;

08

while x>0 do begin

09

t := t + 1;

10

x := x div 10;

11

end;

12

setlength(digs, t);

13

for i := high(digs) downto low(digs) do begin

14

digs[i] := n mod 10;

15

n := n div 10;

16

end;

17

for i := 0 to (t div 2)-1 do

18

if digs[i] <> digs[t-i-1] then begin

19

e_palind := false;

20

break;

21
22 end;

end;

Linguagem de Programao I

83

3.2. Ordenao por Seleo


Seja o problema de classificar em ordem crescente os valores armazenados
numa array de inteiros. H muitos programas propostos para a resoluo deste problema. Apresentaremos aqui a ordenao por seleo.
Seja A uma array com limites inferior e superior 1 e n respectivamente.
A ordenao por seleo consiste em determinar, para cada posio i em A,,
a posio k do menor valor da subarray de A, com limites i e n, e trocar o contedo das posies i e k. O total de trocas realizadas est diretamente ligado
ao esforo de ordenao.
O programa da Listagem 24 implementa a ordenao por seleo em
Pascal. O lao entre as Linhas 10 e 13 carrega (e imprime) a array dat com dez valores aleatrios obtidos com o comando random. O comando random, unidade system, retorna um valor aleatrio entre 0 e o valor do argumento de entrada subtrado
de um. Para uso apropriado deve-se chamar previamente o comando randomize.

Subarray:
Array obtida a partir de
uma subsequncia de
clulas continuas de uma
array dada.

A ordenao por seleo de dat ocorre por ao dos laos entre as Linhas
14 e 21. A lao externo varre todas as clulas no intervalo 1..n-1 ao passo que o
lao interno busca, atravs de k, pela clula de menor valor no intervalo i..n. A primeira hiptese de k em cada iterao do lao externo o valor em i (Linha-15).
As trocas entre as clulas de ndices i e k so feitas pelas Linhas 18 a 20 usando
x como varivel auxiliar. O aspecto de sada deste programa ser,
94 17 31 50 20 73 64 84 69 59
17 20 31 50 59 64 69 73 84 94

Listagem 24
01

program ordenacao_selecao;

14

02

const

15

k := i;

16

for j := i+1 to n do

03
04

n = 10;
var

for i := 1 to n-1 do begin

17

if dat[j] < dat[k] then k := j;

05

dat: array[1..n] of integer;

18

x := dat[i];

06

i, j, k, x: integer;

19

dat[i] := dat[k];

20

dat[k] := x;

07

begin

08

randomize;

21

end;

09

writeln;

22

writeln;

10

for i:= 1 to n do begin

23

for i:= 1 to n do

11

dat[i] := random(100);

24

12

write( dat[i], #9 );

25

13

end;

26

write( dat[i], #9 );
writeln;
end.

84

Ricardo Reis Pereira

3.3. Hiper Fatorial


O fatorial de um nmero inteiro positivo igual ao produto dele por todos seus
antecessores maiores que zero (sendo ainda definido como 1 o fatorial de
zero). O tipo primitivo inteiro que pode representar o maior inteiro int64 e
mesmo assim tal limite representativo insuficiente para calcular fatoriais de
nmeros acima de 20. A soluo proposta neste estudo de caso permite, atravs da utilizao de arrays, determinar o fatorial de qualquer inteiro.
A tarefa de determinao do fatorial de um inteiro qualquer possui quatro etapas: (I) determinar o tamanho (em dgitos) do fatorial de um valor N
dado; (II) criar uma array de dgitos com o comprimento determinado na etapa
I e carreg-lo com zeros, exceto a ltima posio que dever conter 1; (III)
reprogramar a operao de multiplicao de forma a ser possvel fazer o produto entre um escalar e a array criada em II; (IV) repetir a etapa III para todos
os inteiros entre 2 e N. A array criada em II representa na verdade o nmero
procurado expresso como uma array de dgitos. Os zeros seguidos de um 1
denotam a representao do nmero 1 que o valor que deve ter a varivel
acumuladora antes dos produtos.
Varivel Escalar:
So todas as variveis
que no so arrays nem
strings nem estruturas
heterogneas (Veja
Captulo-3).

Para resolver a primeira etapa utilizamos a equao,, que determina a


quantidade de dgitos t na base b de um inteiro n. Assim a quantidade de dgitos do fatorial de N na base 10 ,

t = 1+ log10( N!) (1)


Como o logaritmo do produto a soma dos logaritmos, a Equao-2.1
pode ser reescrita como,
n

t = 1+ log10( j ) (2)
j= 1

Ao contrrio da Equao-2.1, a Equao-2.2 facilmente computvel.


Na segunda etapa uma array de dgitos data alocada, carregada e
deve assumir aspecto como o esquema,
0

0 0 0 1

A terceira etapa, da multiplicao de um escalar d pela array data, funciona da seguinte forma. Um valor inteiro de correo ac definido e iniciado
com zero. Uma srie de produtos de d por cada clula de data ocorrem varrendo data de trs para frente. O valor de cada produto somado a ac para
obter um valor p. Este valor potencialmente contm mais de um dgito sendo o
ltimo deles aquele que deve sobrepor a clula em data multiplicada.

Linguagem de Programao I

85

Para resolver isso registra-se em data apenas o resto da diviso de p


por 10 (que seu ltimo dgito) e guarda-se em ac o quociente ac/10. No
prximo produto o novo valor de ac entrar na computao. De fato ac pode
ser no nulo ao final de vrios estgios sendo sempre aproveitado no estgio
posterior. Para ilustrar essa etapa considere que data seja uma array de 3
dgitos contendo os valores {1, 3, 2} (representa o nmero 132) e deva ser
multiplicado pelo escalar 7. Os estgios de data, ac e p so mostrados a seguir em srie,
1 | 3 | 2

ac: 0 p: 2 x 7 = 14

1 | 3 | 4

ac: 1 p: 3 x 7 = 21

1 | 1 | 4

ac: 2 p: 1 x 7 = 7

7 | 1 | 4

ac: 0

Listagem 25
01

program hiper_fatorial;

15

data[t-1] := 1;

02

var s: real;

16

for d := 2 to n do begin

03

n, t, i, d, ac, p: integer;

17

ac := 0;

04

data: array of integer;

18

for i := t-1 downto 0 do begin

05

begin

19

p := data[i] * d + ac;

06

write('Valor> ');

20

data[i] := p mod 10;

07

readln(n);

21

ac := p div 10;

08

write('Fatorial> ');

22

09

s := 1.0;

23

end;

10

for i := 1 to n do

24

for i := 0 to t-1 do

11

s := s + ln(i)/ln(10.0);

end;

25

12

t := round(s);

26

13

setlength(data, t);

27

14

for i := 0 to t-1 do data[i] := 0;

write( data[i] );
writeln;
end.

O programa da Listagem 25 Implementa o programa de determinao


de fatoriais descrito anteriormente. A primeira etapa ocorre entre as Linhas
06 e 12. A varivel real s responsvel pela contabilizao da quantidade de
dgitos do fatorial (Equao-2.2) da entrada n. Devido a soma de logaritmos,
s deve ser real. Seu valor inicial 1.0 (Linha-09) para contabilizar a primeira
parcela do lado esquerdo da Equao-2.2. O lao nas Linhas 10 e 11 contabilizam a s os logaritmos calculados por ln(i)/ln(10.0). O comando ln, unidade
system, determina o logaritmo natural de um valor. O arrendondamento do
valor em s (comando round, unidade system), registrado em t, a quantidade
de dgitos procurada.
A segunda etapa ocorre entre as Linhas 13 e 15 onde ocorre alocao
da array data e seu preenchimento apropriado. A terceira etapa, Linhas 17 a
22, est aninhada na quarta etapa (Lao iniciado na Linha-16). Cada valor de

O logaritmo de um nmero
a na base b, ou seja, logb
(a) , pode ser reescrito
como a razo In(a)/In(b),
onde ln o logaritmo
natural.

86

Ricardo Reis Pereira

d (contador do lao) multiplicado pela array data e por essa razo ac sempre

reiniciado em zero (Linha-17). O valor calculado com p em cada iterao do


lao interno usa a i-sima clula de data que varrido de trs para frente. Os
operadores mod (na Linha-20) e div (na Linha-21) so respectivamente responsveis pela extrao do novo dgito que ir sobrepor aquele na posio i
corrente em data e pela atualizao de ac. As Linhas 24 e 25 imprimem a sada
obtida dgito a dgito, desta vez varrendo data na sequncia crescente. Um
exemplo de sada do programa ,
Valor> 50
Fatorial> 30414093201713378043612608166064768844377641568960512000000000000

Sntese da Parte 1
Foram apresentadas no Captulo-1 as estruturas bsicas de construo de
um programa em Pascal incluindo sintaxe bsica, utilizao de variveis e
constantes, uso de operadores e expresses, entrada e sada padres, controle de fluxo e fundamentos sobre procedimentos e funes. No Captulo-2
foram apresentadas as estruturas homogneas sequenciais da linguagem, ou
seja, strings que permitiram a representao e manipulao de informao
textual e as arrays que possibilitaram o sequenciamento de dados dos
mais diversos tipos nativos existentes.

Atividades de avaliao
1. Criar funo que receba um caractere e, caso seja uma letra, retorne sua
verso maiscula, quando a entrada for minscula, e minscula quando
a entrada for maiscula. Se a entrada no uma letra, o mesmo caractere deve ser retornado.
2. Escreva uma funo que receba uma string s e um caractere ch e retorne
o nmero de vezes que ch aparece em s.
3. Escreva programa que receba uma string da entrada padro e imprima
quantas palavras ela contm. Considere palavras como sendo pedaos
da string separados por espaos em branco.
4. Construa programa que receba uma array de inteiros e imprima como
sada o maior e o menor valor contidos nela.

Linguagem de Programao I

5. Construa programa que busque numa array os dois maiores valores contidos.
6. Construa um programa que receba uma array e altere seus valores de
forma a ficarem em ordem inversa.
7. Construir programa que carregue em uma array de comprimento n os
primeiros n valores primos.
8. Rotao o procedimento de deslocamento dos itens de uma array para
casas vizinhas. Numa rotao a direita todos os itens migram para posies logo a frente, exceto o ltimo que vai para a posio 1, ex: se v =
{1,2,3,4}, uma rotao a direita modifica v para {4,1,2,3}. De forma anloga uma rotao a esquerda de v geraria {2,3,4,1}. Construir programas
para os dois processos de rotao.
9. Construa um programa que calcule a mdia dos nmeros menores que
5000 que sejam divisveis por 7 mas no sejam divisveis por 3.
10. Considere uma array V que contenha os coeficientes de um polinmio P(x) de grau n. Construa programa que receba V, n e um valor de
x0 e imprima P(x0).
11. Seja uma lista L formada por n valores reais. Dado que:

onde xm a mdia dos elementos de L, xi cada um dos n elementos de


L (com i = {1..n}), implementar programa que receba L e n e calcule .
12. Um CPF tem nove dgitos e mais dois para verificao. A verificao se d da seguinte forma: Primeiro, multiplica-se
cada um dos nove dgitos por um peso, como no esquema:
d1 d2 d3 d4 d5 d6 d7 d8 d9 dgitos
X
10

pesos

a1 a2 a3
a4
a5
a6
a7
a8
a9
Depois se calcula a soma S1 de todos os nmeros resultantes. O dcimo dgito, d10, ser 11 (S1 mod 11),ou zero se esta conta der mais
que nove. Para calcular d11, faz-se como antes, mas leva-se em conta
tambm d10:
d1 d2 d3 d4 d5 d6 d7 d8 d9 d10
X
11
10
9
8
7
6
5
4
3
2
a1

a2

a3

a4

a5

a6

a7

a8

a9

a10

87

88

Ricardo Reis Pereira

Somam-se agora todos os nmeros obtidos. O dgito d11 ser 11 (S2


mod 11), ou zero se esta conta der mais que nove. Faa um programa
que verifique se um CFP est correto.
13. Escreva programa que determine a somatria dos dgitos do valor 100!.
14. Escreva dois programas um para a converso de nmeros inteiros decimais em sua forma binria e outro para a operao inversa.
15. O nmero 585 palndromo nas bases 10 e base 2 (1001001001).
Construir programa que determine a soma de todos os nmeros com
esta propriedade que sejam menores que um milho.
16. Dado uma array V ordenada de comprimento n no qual se busca o valor x,
a busca binria se procede como segue: (1) inf recebe 1 e sup recebe n; (2)
se inf for maior que sup, encerrar (valor no encontrado); (3) med recebe a
mdia de inf e sup; (4) x comparado a V[med] de forma que se este valor
igual a x o procedimento encerra (valor encontrado), se for maior que x o
valor de sup passa a ser med-1, seno se for menor que x, inf passa a ser
med+1; (5) voltar a 2. Construir programa para busca binria
17. Considere uma lista L de valores inteiros no repetidos contendo n elementos. Desenvolva um programa que selecione m elementos aleatrios
entre os n existentes de forma que tambm sejam todos diferentes. O
valor m deve ser sempre menor que n.
18. Temos uma array com 20 nmeros. Queremos reorganizar o array de
forma que dois nmeros pares no sejam vizinhos. Faa um programa
que reorganize o array desta forma, ou diga que no possvel.
19. Construa um programa que tenha como entrada duas matrizes quadradas de ordem n e oferea as operaes algbricas de soma, subtrao
e multiplicao.
20. Construa um programa que receba uma matriz quadrada de ordem n e
calcule seu determinante.
21. Considere uma grade 2X2 como a desenhada abaixo na qual se parte
do canto superior esquerda at o inferior direita: h um total de 6 trajetrias possveis. Construir programa que receba N e retorne o total de
trajetrias numa grade NXN.

Linguagem de Programao I

Referncias
SEBESTA, Robert W., Concepts of Programming Languages, Addison
Wesley; 9 edition (April 2, 2009)
CANNEYT, Michal Van, Reference guide for Free Pascal, Document
version 2.4 , March 2010
http://www.freepascal.org/docs-html/

89

90

Ricardo Reis Pereira

Parte
Tipos de Dados Personalizados

Captulo

Tipos de Dados
Personalizados
Objetivos:
Esta unidade tem por objetivo introduzir estruturas sofisticadas da linguagem Pascal. No Captulo-1 so apresentadas estruturas que permitem
abstrair e operar modelos ligados a objetos enumerveis, descritos por
campos ou associados a conjuntos. No Captulo-2 estudado o poderoso recurso dos ponteiros que tanto potencializam construes nativas do
Pascal quanto permitem um mais flexvel gerenciamento da memria do
computador. Alm das vantagens so tambm estudados os problemas
com ponteiros. Um estudo de caso prtico procura aplicar as principais
estruturas abordadas no captulo.

1. Definindo Novos Tipos


Um tipo de dados define um conjunto de regras utilizadas para representar
e operar dados atravs de variveis e constantes. Ao definir uma varivel
como smallint, por exemplo, ela poder representar valores inteiros no intervalo de -128 a 127, estar presente em expresses aritmticas em operaes
de soma, subtrao, multiplicao e diviso bem como ser alvo de uma atribuio. Todas essas caractersticas foram definidas na implementao da
Linguagem Pascal e os tipos de dados construdos sobre tal condio so
definidos como nativos da linguagem. Entre os tipos nativos esto os tipos primitivos (todos os numricos, caractere e booleanos) estudados nos Captulos
1 e 2, as sequencias homogneas (strings e arrays) estudadas no Captulo-2,
as enumeraes, estruturas heterogneas e os conjuntos. Os trs ltimos sero abordados neste captulo.
Em Pascal uma sesso rotulada com type utilizada para definir tipos
personalizados. Um tipo personalizado uma novo tipo de dados construdo
a partir de tipos nativos e com operabilidade definida, em alguns casos, pelo
programador. A forma mais simples de tipo de dados personalizado aquela
que define um novo nome para um tipo j existente. No exemplo,

94

Ricardo Reis Pereira

type

inteiro = integer;

o identificador inteiro passa a funcionar, aps essa definio, como o tipo primitivo integer. A declarao,
var x: inteiro;

legal neste contexto.


Cada nova definio da sesso type tem sintaxe geral,
type
<identificador_do_novo_tipo> = <tipo_de_dados>;

onde a igualdade, =, apesar da mesma representao do operador relacional


de comparao (Captulo-1), possui semntica completamente diferente, ou
seja, nomeia um tipo personalizado. O identificador que nomeia o novo tipo
segue as regras de identificadores da Linguagem Pascal.
Um tipo faixa em Pascal representa outro exemplo de tipo personalizado que construdo numa sesso type. Trata-se de um tipo que representa
uma subsequencia de nmeros inteiros oriunda de um tipo inteiro primitivo e
cuja construo feita a partir dos valores limites numricos inferior e superior
conforme sintaxe,
type
<identificador> = <limite_inferior>..<limite_superior>;

No exemplo,
type

faixa1 = 10..20;

var

x: faixa1;

um tipo denominado faixa1 definido para que suas variveis (tais como o
exemplo x) possam representar inteiros entre 10 e 20. Atribuies explcitas
de valores fora da faixa definida (como, x := 89, neste exemplo) fazem o compilador emitir uma advertncia, mas no um erro.
O tamanho em bytes de uma varivel de tipo faixa o menor valor inteiro n tal que 28n seja maior ou igual ao total de inteiros cobertos pelo tipo.
Por exemplo na faixa 10..20, so cobertos 11 inteiros e o menor valor de n
1-byte pois 281= 28= 256> 11. Para a faixa 10..1000, que cobre 991 inteiros, n vale
2-bytes pois 282= 216= 65536> 991. Vaiveis de tipo faixa so operadas normalmente como qualquer outra variveis inteira.

Linguagem de Programao I

Tipos arrays estticas podem tambm ser definidos numa sesso type.
No exemplo,
type

tarr = array[1..10] of integer;

O tipo tarr pode definir variveis e constantes que comportam sequencialmente dez inteiros. Nas declaraes,
const

c: tarr = (5,4,1,3,2,0,9,7,8,6);

var

x: tarr;

a constante c e a varivel x definem duas arrays de dez inteiros.


O compilador Pascal reconhece atribuies entre dados de um tipo array esttico personalizado. Assim, neste ltimo caso, a atribuio,
x := c;

pode ser utilizada para inicializar x. As dez clulas de c tm o contedo copiado para as clulas de x sem necessidade de um lao. O mesmo acontece
com strings, como no exemplo,
type
mensagem = string[100];
const
erro_1: mensagem = 'disco falhou!';
var
s: mensagem;
begin
s := erro_1;
writeln(s);
end.

95

96

Ricardo Reis Pereira

Listagem 26
01
02
03
04
05
06
07
08
09

program tipo_array_dinamico;
type
tdyarr = array of integer;
var
x, y: tdyarr;
i: integer;
begin
setlength(x, 20);
for i := low(x) to high(x) do x[i] := i*i;
y := x;
for i := low(x) to high(x) do y[i] := y[i]*2;
for i := low(x) to high(x) do write(x[i], );
end.

10
11
12
13

No caso de arrays dinmicas o tipo personalizado pode ser definido na


sesso type com a mesma sintaxe das definies anteriores. Entretanto as
atribuies diretas no so capazes de copiar os dados efetivamente (veja arrays dinmicas no Captulo - 2). No exemplo da Listagem 26, a array dinmica
x, de tipo tdyarr, alocada (Linha-08) e ilicializada com os dez primeiros quadrados perfeitos (Linha-09). A atribuio direta para y entretanto s torna esta
varivel uma nova referncia ao bloco de memria alocado na Linha-08. Isso
tanto verdade que, ao dobrar o valor de cada clula da array y (Linha-11), o
efeito sentido por x (impresso da Linha-12).

2. Enumeraes
Uma enumerao um tipo faixa especial cujos inteiros cobertos possuem
cada um seu prprio identificador. A sintaxe geral de um tipo enumerao
Pascal a seguinte,
type

<nome> = (<ident_1>, <ident_2>, <ident_3>, {...}, <ident_n>);

Tipos enumeraes so utilizados para modelar dados que seguem algum critrio numrico de ordenao e que comummente so manipulados
por nomes prprios. Um exemplo comum so os dias da semana que podem
ser representados por variveis da enumerao seguinte,
type

dia = (seg, ter, qua, qui, sex, sab, dom);

Linguagem de Programao I

Os identificadores entre parnteses no podem ser utilizados adiante


no mesmo programa, por exemplo, para representar constantes ou variveis.
Atrubuies a variveis de tipo enumerao so construdas repassando-se
diretamente um dos identificadores definidos no tipo. Exemplo,
var

hoje: dia;

begin

hoje := dom;

end.

Quando um valor enumerao impresso por write/writeln, uma verso


string do identificador repassada a sada padro. No exemplo,
write(Hoje e , hoje);

onde hoje contm dom, impresso hoje e dom.


Como enumeraes so casos especiais de faixas, seus identificadores possuem equivalentes numricos. No padro Pascal o primeiro elemento
de uma enumerao equivalente a zero, o segundo a um e assim por diante.
Para determinar o equivalente numrico de um identificador de uma enumerao utiliza-se o comando ord. No exemplo,
writeln( ord(hoje) );

onde hoje vale dom, impresso 7.


possvel modificar a sequncia numrica de equivalncia de uma
enumerao. Para tanto basta modificar o equivalente numrico de um dos
identificadores e os dos demais correspondero a valores sucessores ou antecessores, dependendo do caso. Para modificar o equivalente numrico de
um identificador deve-se atribuir a ele um valor inteiro com o operador de atribuio diretamente na definio da enumerao. Na redefinio da enumerao dia,
type

dia = (seg=27, ter, qua, qui, sex, sab, dom);

o primeiro identificador tem seu equivalente numrico modificado para


27 e os demais respectivamente para 28, 29, 30, 31, 32 e 33. Neste
outro exemplo,
type

dia = (seg, ter, qua=27, qui, sex, sab, dom);

a nova sequncia de equivalentes numricos 25, 26, 27, 28, 29, 30 e 31.
Os comandos low e high, da unidade system, podem ser utilizados para
determinar os identificadores de um tipo enumerao respectivamente de me-

97

98

Ricardo Reis Pereira

nor e maior equivalentes numricos. Estes comandos recebem apenas um


argumento que pode ser uma varivel enumerao ou o nome de um tipo
enumerao. No exemplo,
writeln( low(dia), a , high(dia) );

imprime em sada padro seg a dom.


Enumeraes podem constituir expresses relacionais sendo as comparaes efetuadas de acordo com os equivalentes numricos. No exemplo,
var a, b: dia;
begin
a := ter;
b := qui;
if a > b then writeln('passou o prazo') else writeln('ainda esta em tempo');
end.

impresso ainda esta em tempo na sada padro pois o equivalente numrico


de ter menor que o de qui.
Contadores de laos de contagem podem ser de tipo enumerao. O
exemplo,
type dia = (seg, ter, qua, qui, sex, sab, dom);
var d: dia;
begin
for d := seg to dom do
writeln( d, ' equivale a ', ord(d) );
end.

Imprime em sada padro,


seg equivale a 0
ter equivale a 1
qua equivale a 2
qui equivale a 3
sex equivale a 4
sab equivale a 5
dom equivale a 6

Utilizando os comandos low e high, o lao anterior pode ser reescrito


como,
for d := low(dia) to high(dia) do

writeln( d, equivale a , ord(d) );

Linguagem de Programao I

Uma enumerao pode ser annima, ou seja, definida diretamente com


as variveis numa sesso var. No exemplo seguinte,
var

mes: (jan, fev, mar, abr, mai, jun, jul, ago, stb, otb, nov, dez);

a varivel mes de um tipo enumerao annimo que modela os meses do ano.

3. Estruturas Heterogneas
Uma estrutura heterognea em Pascal um tipo de dados construdo pelo
encapsulamnto de outros tipos de dados que podem ser nativos ou pernonalizados. O encapsulamento funciona pela definio de identificadores e seus
tipos cada qual responsvel por uma fatia dos dados que uma varivel ou
constante desta estrutura dever conter. Cada par identificador/tipo de uma
estrutura heterognea denominado campo. A sintaxe geral de um tipo estrutura heterognea em Pascal ,
type
<nome> = record
<campo_1>: <tipo_1>;
<campo_2>: <tipo_2>;
<campo_3>: <tipo_3>;
...
<campo_n>: <tipo_n>;
end;

onde a palavra reservada record (que significa registro) forma com end o bloco encapsulador de campos. O exemplo,
type
aluno = record
nome: string[25];
idade: byte;
media: real;
end;

defiine um tipo de dados estrutura heterognea chamado aluno que contm


trs campos denominados respectivamente de nome, idade e media. O novo
tipo utilizado para representar, atravs de cada varivel que definir, informaes gerais de um aluno no final do semestre letivo. O campo nome usado
para armazenar o nome completo com at 25 caracteres, idade o valor da

99

100

Ricardo Reis Pereira

idade e media a mdia final. A declarao de variveis de tipo estrutura heterognea segue a mesma sintaxe j apresentada. No exemplo,
var

x: aluno;

define uma varivel de tipo aluno.


Os campos de uma varivel estrutura heterognea podem ser acessados diretamente como se fossem variveis independentes. Este acesso
contrudo com o operador ponto (.) posto entre a varivel estrutura heterognea e o identificador de um de seus campos. Por exemplo, para inicializar a
varivel x no exemplo anterior pode-se escrever,
x.nome := pedro da silva;
x.idade := 25;
x.media := 8.7;

De fato, em qualquer momento do programa, os campos de uma varivel estrutura heterognea podem ser modificados ou lidos independentemente. Para imprimir em sada padro o contedo de x pode-se implementar,
writeln(Nome: , x.aluno, Idade: , x.idade, Media: , x.media:0:1);

Uma forma alternativa de ler ou modificar os campos de uma varivel


estrutura heterognea, num mesmo contexto, utilizando referncias elpticas.
Uma referncia elptica um recurso que permite modificar os campos da varivel diretamente atravs de seus identificadores sem uso do operador ponto.
Para tando toda os acessos (tanto em expresses como em atribuies) devem
ocorrer dentro de um bloco with. A sintaxe de um bloco with Pascal ,
with <variavel_estrutura_heterogenea> do
begin
{ corpo }
end;

onde o corpo contm cdigo Pascal que utiliza os campos da varivel disposta entre with e do. Estas palavras reservadas significam com e faa respectivamente. No exemplo,
with x do begin
nome := 'pedro da silva';
idade := 25;
media := 8.7;
writeln('Nome: ', aluno, ' Idade: ', idade, ' Media: ', media:0:1);
end;

a varivel x inicializada e impressa atravs de referncias elpticas.

Linguagem de Programao I

101

Estruturas heterogneas podem conter campos de mesmo tipo desde


que possuam identificadores distintos. A estrutura seguinte, por exemplo,
type ponto = record
x, y: real;
end;

possui dois campos de nomes x e y e representa um ponto no plano.


Utilizando uma estrutura possvel abstrair uma entidade que facilite o
trabalho do programador. Por exemplo, aplicando a ideia de ponto no plano da
estrutura anterior possvel escrever funes e procedimentos que executem
tarefas de geometria analtica plana. Neste contexto uma funo que calcule
a distncia entre dois pontos no plano pode ser implementada como segue,
function dist(p, q: ponto) : real;
begin

dist := sqrt( sqr(p.x-q.x) + sqr(p.y-q.y) );

end;

onde sqrt e sqr so funes da unidade system que retornam respectivamente


a raiz quadrada e o quadrado de um nmero. Os argumentos de entrada p e
q, de tipo ponto, permitem uma codificao mais elucidativa sobre o problema
da distncia entre dois pontos no plano.
Um tipo estrutura heterognea pode ser utilizada como sada de uma
funo para permitir que mais de uma informao possa ser retornada. Por
exemplo, no problema da equao do segundo grau, duas razes precisam
ser devolvidas, quando existirem. Um modelo de estrutura heterognea proposta para resoluo do problema a seguinte,
type root = record

x1, x2: real;

erro: integer;

end;

Os dois primeiros campos, x1 e x2, de tipo real, representam as razes


reais do polinmio (se existirem) ao passo que erro, de tipo integer, indica se
houve ou no erro operacional. Quando nenhum erro ocorre o valor de erro
zero e x1 e x2 contm valores vlidos de razes. Quando erro no nulo ento
um erro ocorreu e os valores em x1 e x2 so inconsistentes.
Os demais cdigos de erros considerados so apenas dois: 1, quando
o polinmio no de segundo grau e 2, quando no existem razes reais. A
funo eq2g na Listagem-3.2 implementa o modelo. Na Linha-01 so recebidos os coeficientes da equao do segundo grau () via argumentos a, b e c.
Na Linha-04 faz-se a hiptese de que razes reais de fato existem at que se
prove o contrrio (o cdigo do erro zero).

Ponto no Plano: Os
pontos no plano cartesiano
so representados por
uma coordenada no eixo x
(abcissas) e outra no eixo
y (ordenadas).

Geometria Analtica
Plana: Parte da
matemtica que trata da
resoluo de problemas da
geometria plana atravs
do equacionamento de
entidades primitivas como
pontos, retas e cnicas.
A geometria analtica no
depende de desenhos
(apesar de ajudarem)
como a geometria plana
pura.

102

Ricardo Reis Pereira

O teste da Linha-05 avalia o quanto o valor em a est prximo de zero (a


funo abs, unidade system, retorna o valor numrico absoluto). Estando muito
prximo de zero ento o processamento desvia para a Linha-13 onde o cdigo
de erro mudado para 1 e a funo encerrada (um valor de a nulo, ou muito
prximo disso, descaracteriza a equao que passa a ser de primeiro grau).
Do contrrio o valor de delta calculado (Linha-06) e testado (Linha-07).
Caso este seja negativo ento o processamento desviado para a Linha-11
onde o cdigo de erro mudado para 2 (delta negativo significa razes complexas) e a funo encerrada. Do contrrio as Linhas 08 e 09 processam os valores
das razes corretamente. Atente que neste caso o cdigo de erro no muda pois
a primeira hiptese verdade.
Listagem 27
01
02
03
04
05
06
07
08
09
10

function eq2g(a,b,c: real): root;


var delta: real;
begin
eq2g.erro := 0;
if abs(a)>1.0e-5 then begin
delta := sqr(b) - 4*a*c;
if delta>=0 then begin
eq2g.x1 := (-b+sqrt(delta))/(2*a);
eq2g.x2 := (-b-sqrt(delta))/(2*a);
end else
eq2g.erro := 2;
end else
eq2g.erro := 1;
end;

11
12
13
14

A utilizao da funo eq2g da Listagem 27 pode ser ilustrada por,


var

a,b,c: real;

r: root;

begin
readln(a,b,c);

r := eq2g(a,b,c);

case r.erro of

0: writeln(Raizes: , r.x1:7:3, r.x2:7:3);

1: writeln(Polinomio invalido);

2: writeln(Raizes complexas);

end;
end.

Linguagem de Programao I

Estruturas heterogneas podem agrupar arrays, enumeraes ou mesmo outras estruturas heterogneas. No exemplo,
type estudante = record

nome: string[30];

notas: array[1..4] of real;

turma: record

serie: byte;
letra: char;

turno: (manha, tarde, noite);

end;
end;

O campo notas pode registrar quatro notas de um estudante em uma


mesma varivel. Para modificar tais notas faz-se a associao das sintaxes j
apresentadas, por exemplo,
x.notas[1] := 7.6;
x.notas[2] := 8.7;
x.notas[3] := 8.0;
x.notas[4] := 6.2;

onde x do novo tipo estudante. O campo turma de um tipo estrutura heterognea annima com trs campos por se configurar sendo o terceiro de um
tipo enumerao, tambm annimo. Usando referncias elpticas pode-se,
por exemplo, escrever,
with x.turma do begin

serie := 8;

letra := C;

turno := manha;

end;

ou equivalentemente sem referncias elpticas,


x.turma.serie := 8;
x.turma.letra := C;
x.turma.turno := manha;

Neste caso dois nveis de chamada ao operador ponto ocorrem devido


a hierarquia dentro da estrutura.
Estruturas heterogneas annimas podem ser aplicadas diretamente
em varveis como no exemplo,

103

104

Ricardo Reis Pereira

var y: record

check: boolean;

lote: integer;

end;

Nestes casos o novo tipo fica ancorado e de uso exclusivo das variveis
definidas juntamente com ele. O acesso a campos descrito anteriormente funciona da mesma forma.
Para definir uma constante de estrutura heterognea utiliza-se a sintaxe
geral seguinte,
const
<nome>: <tipo_estrutura_heterogenea> =
(<campo1>:<valor1>;
<campo2>:<valor2>;
<campo3>:<valor3>;
...
<campon>:<valorn>);

O exemplo a seguir ilustra a definio de algumas constantes de estruturas heterogneas declaradas anteriormente,
const
um_aluno: aluno = (nome: 'pedro'; idade: 25; media: 8.5);
p: ponto = (x: 10.0; y: 30.0);
my_root: root

= (x1: 0.0; x2: 0.0; erro: 0).

aplicado: estudante =
( nome: 'raul';
notas: (9.5, 10.0, 8.5, 9.4);
turma: (serie: 8; letra: 'C'; turno: manha) );

possvel definir uma array cujas clulas so de um tipo estrutura heterognea. Elas seguem a mesma sintaxe das arrays comuns. No exemplo,
var

lista: array[1..100] of ponto;

a array lista comporta 100 dados de tipo ponto.


O acesso individual aos campos de cada uma das clulas de uma array
de estrutura heterognea construdo tambm com o operador ponto que
neste caso posto entre o segundo colchete do operador de indexao e o
identificador do campo. Por exemplo, para carregar lista com 100 pontos da
funo, com x no intervalo [5: 50], pode-se escrever,

Linguagem de Programao I

for i := 1 to 100 do begin


lista[i].x := 5.0 + 45.0*(i-1)/99;
lista[i].y := sqr( lista[i].x );
end;

ou ainda utilizando referncias elpticas,


for i := 1 to 100 do
with lista[i] do begin
x := 5.0 + 45.0*(i-1)/99;
y := sqr( x );
end;

4. Conjuntos
As trs opes mais comuns de estilos de formatao de texto so o negrito,
o itlico e o sublinhado. Tais estilos podem ocorrer ao mesmo tempo, aos
pares, apenas um ou mesmo nenhum deles fazendo um total de oito possibilidades. Aos estilos de formatao denominamos de domnio de representao
do problema e s possibilidades combinatrias de conjuntos. De forma geral
um domnio com n elementos rende um total de 2n conjuntos.
A linguagem Pascal suporta a implementao de conjuntos. Um conjunto em Pascal construdo sobre um tipo inteiro, faixa ou enumerao
(denominado tipo base) e registra quaisquer uma das combinaes que os
elementos deste tipo podem formar. A sinaxe bsica de definio de um tipo
conjunto Pascal ,
type
<nome> = set of <tipo_base>;

onde as palavras reservadas set of significam conjunto de. Para modelar o


exemplo dos estilos de texto ilustrado no incio da sesso, pode-se implementar,
type

estilo = (negrito, italico, sublinhado);

estilos = set of estilo;

Neste exemplo o tipo estilo define uma enumerao de estilos de texto


ao passo que estilos define um tipo conjunto de estilos de texto.
As operaes bsicas suportadas por conjuntos em Pascal so,
Atribuio
Incluso

105

106

Ricardo Reis Pereira

Remoo
Verificao
Numa atribuio a varivel conjunto recebe integralmente os itens que
dever conter. Se ela contm outras informaes, estas so sobrepostas. A
sintaxe geral de uma atribuio para uma varivel conjunto ,
<variavel_conjunto> := [ <lista_de_itens> ];

So obrigatrios os colchetes e a lista de itens pode inclusive ser vazia.


Quando mais de um item esta presente, devem ser separados por vrgulas. As
seguintes atribuies,
s := [];
s := [italico];
s := [negrito, sublinhado];
s := [negrito, italico, sublinhado];

so todas vlidas e inicializam s, de tipo estilos, em vrias possibilidades.


A ordem que os identificadores aparecem nas atribuies no importante. A repetio de um mesmo identificador numa dada atribuio gera um
erro de compilao.
Uma operao de incluso aquela que adiciona um ou mais itens a
uma dada varivel de tipo conjunto. Caso o conjunto j contenha algum ou alguns dos itens que se almeja inserir ento so inseridos apenas os que ainda
no esto presentes. Uma incluso construda com uma soma (operador +)
e uma atribuio (operador :=). Os novos itens includos devem estar sempre
entre colchetes (separados por vrgulas). Nos exemplo,
s := s + [negrito];
t := t + [sublinhado, negrito];

caso ainda no estejam presentes, a opo negrito includa na varvel conjunto s e as opes negrito e sublinhado na varivel conjunto t.
Uma operao de remoo exclui de uma varivel conjunto um ou
mais itens se eles estiverem presentes. A construo similar a incluso, mas
substitui o operador + por -. No exemplo,
s := s - [negrito, sublinhado];

as opes de negrito e sublinhado so removidas da varivel conjunto s caso


estejam presentes. Se apenas uma estiver presente, ser removida. Se nenhuma estiver presente, nada ocorrer.
A operao de verificao em conjuntos consiste na checagem da presena de um determinado item. Ao contrrio da atribuio, incluso e remoo, a verificao s pode ser executada item a item. A Linguagem Pascal

Linguagem de Programao I

possui o operador in exclusivo para verificao de itens em conjuntos. Tratase de um operador relacional posto entre o item que se deseja verificar a
presena e a varivel conjunto. Sintaticamente,
<identificador_do_item> in <conjunto>

Por exemplo, para verificar se a varivel conjunto s, de tipo estilos, contm a opo negrito, pode-se usar,
if negrito in s then

writeln(Texto em negrito!);

Sematicamente a expresso em if pergunta se negrito parte do conjunto s.


Para verificar simultaneamente mais de um item deve-se usar operadores lgicos, como em,
if (italico in s) and (sublinhado in s) then

writeln(Texto em italico e sublinhado);

Atividades de avaliao
1. Construa uma estrutura heterognea que modele uma data incluindo dia,
ms e ano. Use uma enumerao para representar os meses.
2. Utilizando o modelo de data do problema-1 construa programa que leia
duas datas e diga qual delas est a frente da outra.
3. So considerados anos bissextos todos os anos mltiplos de 400 ou os
mltiplos de 4 e no mltiplos de 100. Utilizando essas informaes, uma
estrutura heterognea para datas e uma enumerao para os dias da
semana, construir programa que determine em que dia da semana cai
determinada data.
4. Utilizando estruturas heterogneas montar um modelo para nmeros
complexos e implementar funes que efetuem as operaes de soma,
subtrao, multiplicao e diviso de dois complexos dados.
5. Expandir o modelo da questo anterior e criar uma funo que retorne
razes reais ou complexas de um polinmio de segundo grau.
6. Vetores no espao possuem trs componentes referentes aos eixos x, y e
z. Construir modelo para vetor e implementar funo que retorne o mdulo
de um vetor recebido como argumento. O mdulo de um vetor calculado
pela raiz quadrada da somatria dos quadrados de suas componentes.

107

108

Ricardo Reis Pereira

7. O produto vetorial de dois vetores no espao de componentes ax , a y , az


e bx , b y , bz dado pelo determinante

. Criar programa que, uti-

lizando o modelo de vetores do problema-4, determine o produto vetorial


de dois vetores dados.
8. Construir modelo, utilizando arrays e estruturas heterogneas, que represente uma lista de partculas no plano. Uma partcula deve conter
informaes sobre coordenadas e sua massa. O centro de massa de
um sistema de partculas um ponto cujas coordenadas so calculadas
poronde (xi, yi), mi e M so respectivamente a coordenada e massa da
i-sima partcula e a massa do sistema. Construir funo que, utilizando
o modelo construdo, receba uma lista de partculas e retorne a coordenada do centro de massa equivalente.
9. Num jogo de computador deve-se clicar numa rea na tela com o boto
esquerdo do mouse para se ver o que h por trs. Se houver uma bomba
o jogo se encerra. Se a rea estiver trancada ela no poder ser aberta
desta forma. Uma rea trancada e destrancada com o clicar do boto
direito do mouse. Crie um conjunto que defina o estado desta rea (minado, aberto, trancado e detonado) e construa uma funo que simule
uma tentativa de clique.

31

Captulo

Ponteiros

1. Fundamentos
Ponteiro um tipo de varvel utilizada para armazenar endereos de outras
variveis. Assim a informao registrada em um ponteiro um endereo de
memria. Como a forma de endereamento pode mudar entre arquiteturas
distintas, ento o contedo de um ponteiro vai depender do hardware utilizado
e do sistema operacional instalado.
Mas convenientemente, num mesmo sistema em operao, qualquer
referncia a memria feita com a mesma nomenclatura e cada varivel instanciada tem um endereo distinto. Dificilmente um programador que trabalha
com uma linguagem de alto nvel, como Pascal, ter diretamente que tratar
com valores de endereos das variveis de seus programas. Como se ver
neste captulo o uso de ponteiros quase sempre para uma operao indireta.
A ttulo de visualizao, abstraindo-se a memria como uma estrutura
linear, possvel conceber um modelo que define o endereo como a quantidade de bytes que antecede a varivel endereada (Figura - 7).
Endereo de memria
Varivel armazenada

Memria Principal

Ponteiros possuem duas aplicaes prticas,


Referenciamento Indireto.
Gerenciamento dinmico de memria.
O referenciamento indireto o mecanismo pelo qual um ponteiro, utilizando o endereo de varivel que armazena, l ou modifica o contedo desta

Endereo de Memria
A memria de um
computador segmentada
em agrupamentos de
clulas cujas as posies
so controladas por
valores numricos
denominados de
endereos de memria.
Eles normalmente so
representados em forma
hexadecimal (como nas
mensagens de erro do
sistema operacional). A
quantidade de bits de um
endereo de memria varia
conforme CPU e sistema
utilizados, sendo os mais
comuns os de 32-bits e
64-bits.

110

Ricardo Reis Pereira

varivel. O referenciamento indireto de ponteiros tambm conhecido como


desreferenciamento.
Gerenciar dinamicamente a memria significa, em tempo de execuo,
requerer blocos de memria e devolv-los quando no mais so necessrios.
Este requerimento feito diretamente ao sistema operacional sobre o qual o
programa executa. O sistema responde repassando, para cada solicitao,
um valor de endereo de uma rea livre de memria com o tamanho solicitado. Para cada solicitao o programa dever manter um ponteiro que receber o valor de endereo repassado pelo sistema.
Este processo de requisio de memria conhecido como alocao
dinmica de memria. Utilizando o desreferenciamento e aritmtica de endereos (que ser estudada mais adiante) o programa poder efetuar operaes de
leitura e escrita na nova rea de memria alocada. Antes que o programa se encerre, toda memria dinamicamente alocada dever ser formalmente devolvida
(desalocao dinmica). Quando isso no ocorre a rea de memria mantm o
status de ocupada (memria ociosa) enquanto o programa executa.
O gerenciador de memria do sistema divide a memria entre memria
de alocao esttica (stack) e memria de alocao dinmica (heap). Todas
as variveis declaradas explicitamente num programa, ou seja, que possuem
um nome, so alocadas em stack, ao passo que toda alocao dinmica requer memria em heap.
Na alocao esttica todas as variveis possuem nome e a desalocao automtica. Na alocao dinmica os blocos de memria alocados so
tambm variveis, mas sem nome e por essa razo necessitam de ponteiros
para poderem ser manipuladas devidamente. Num processo de alocao dinmica duas variveis esto presentes: o ponteiro e a varivel sem nome cujo
endereo ele armazena.
Diz-se que ponteiros apontam para outras variveis. Assim, o valor
apontado por um ponteiro corresponde ao contedo da varivel endereada e
no ao contedo do ponteiro em si. Se um desreferenciamento com atribuio
ocorre, o contedo do ponteiro no muda, mas sim o da varivel apontada. Se
o contedo do ponteiro mudado por alguma razo, ele deixa de ter acesso
varivel que endereava e passa a atuar sobre o novo endereo que recebeu.
O contedo para o qual um ponteiro aponta pode diversificar em tipo e
tamanho. Um ponteiro pode apontar para um escalar (integer, real, char e etc),
para uma estrutura heterognea (record), para uma array ou mesmo para outro ponteiro. J o contedo de um ponteiro, ou seja, o valor de endereo que
ele armazena, possui para uma dada arquitetura de CPU sempre o mesmo
tamanho em bits no importando a natureza do contedo apontado.

Linguagem de Programao I

Uma arquitetura cujos endereos de memria tm n-bits, pode representar um total de 2n endereos distintos. Haja vista que cada endereo refere-se a 1-byte distinto (veja Figura-4.1) ento o tamanho mximo de memria
principal gerencivel deve ser exatamente 2n-bytes. Para se ter uma ideia,
em arquiteturas populares onde n 32-bits, este total de 232 bytes, ou seja,
4-GB. Quando a memria mxima gerencivel ultrapassada no hardware, o
sistema no reconhece a memria excedente.

2. Declarao e Inicializao
de Ponteiros
Existem duas categorias de ponteiros em linguagem Pascal: os ponteiros tipados, que conhecem o tipo das variveis para onde apontam, e os no-tipados,
que no conhecem o tipo da varivel para onde apontam, mas que em contra
partida, podem apontar para variveis de quaisquer tipo.
A sintaxe para declarar um ponteiro tipado em Pascal ,
var
<ponteiro>: ^<tipo_base>;

onde o circunflexo (^) denominado de operador de declarao de ponteiro.


Ele deve ser pr-fixado a um tipo de dados indicando que o ponteiro declarado apontar para uma varivel deste tipo base. O tipo base pode ser um tipo
primitivo como,
var
p: ^integer;
q: ^real;
pt: ^boolean;

pode ser um tipo estrutura heterognea,


type

TReg = record

x, y, z: Byte;

end;
var

reg: ^TReg;

Diz-se que p um ponteiro para


inteiro, q para real e pt para
booleano.

111

112

Ricardo Reis Pereira

pode ser de um tipo array,


type

MyVec = array[1..3] of integer;

var

pVec: ^MyVec;

ou mesmo ser de um tipo ponteiro,


type

MyPtInt = ^integer;

var

pp: ^MyPtInt;

Note que a formao de um tipo ponteiro, como no exemplo de MyPtInt,


segue a mesma sintaxe de declarao, exceto pela igualdade (=) exigida em
definies de tipos personalizados (veja Captulo-3).
Para declarar ponteiros no-tipados deve-se utilizar a palavra chave
pointer como tipo (sem o operador de inicializao, ^). Esquematicamente,
var
<variavel>: pointer;

Um ponteiro declarado e no inicializado pode conter um valor descontextualizado de endereo. Diz-se, neste caso, que o ponteiro armazena um
endereo no seguro. Operar endereos no seguros pode causar efeitos
colaterais de funcionamento ou mesmo suspenso de execuo do programa
(isso ocorre quando o sistema operacional se defende do uso inapropriado da
memria feito pelo programa). H trs maneiras em Pascal de inicializar um
ponteiro com um valor seguro de endereo,
Fazer o ponteiro apontar para lugar nenhum.
Atribuir diretamente ao ponteiro o endereo de uma varivel j existente.
Alocar dinamicamente um bloco de memria e deleg-lo ao ponteiro.
Analisaremos os dois primeiros tpicos nessa sesso. O terceiro tpico
ser estudado na Sesso- 4.5 .
Um ponteiro aponta para lugar nenhum quando seu contedo no conduz a uma posio real da memria. A palavra chave nil, em Pascal, utilizada
para se referir a este valor inerte de endereo. Atribuir diretamente nil a quaisquer ponteiros (tipados ou no), fazem-nos apontar para lugar nenhum. Assim,
p := nil;

faz com que o ponteiro p aponte para parte alguma.

Linguagem de Programao I

113

Para atribuir diretamente o endereo de uma varivel a um ponteiro, utiliza-se o operador @. Este operador determina o endereo de uma varivel qualquer
qual est pr-fixado. O resultado deve ser atribudo a um ponteiro. Exemplo,
p := @i;

Neste exemplo, i um inteiro e p um ponteiro de inteiro. Aqui p recebe


o endereo de i (apenas uma cpia do endereo de i e no o contedo de i).
Passam a existir duas referncias para a mesma posio na memria como
se pode visualizar na Figura - 8.

Figura 8
Listagem 28
01

program PonteiroAplicado;

07

p := @i;

02

var

08

writeln(p^);

03

i: integer;

09

p^ := 231;

04

p: ^integer;

10

writeln(' ', i);

05

begin

06

11

end.

i := 127;

Para ler ou modificar o contedo de uma varivel apontada por um


ponteiro, utiliza-se o operador de desreferenciamento, cujo smbolo ^. Este
novo operador, apesar da mesma simbologia do operador de declarao,
ps-fixado na varivel ponteiro para indicar que se trata da varivel apontada
e no do prprio ponteiro (a ideia de uso do circunflexo remete a uma seta
vertical que aponta para cima lembrando que se est apontado para outra
parte da memria). A Listagem 28 Ilustra o desreferenciamento de ponteiros.
Na Linha-08 o valor da varivel apontada por p, ou seja, i, apenas lido da
memria e impresso pelo writeln. Na Linha-09 a varivel apontada, ainda i,
modificada pela atribuio. Assim a sada deste programa deve ser,
127 231

A indireo dos ponteiros se mantem em cpias dos ponteiros. Assim,


por exemplo, se no exemplo da Listagem-4.1 houvesse outro ponteiro de inteiro q ainda seria legal escrever,

Para acessar uma varivel


via ponteiro recorre-se
inicialmente a clula
de memria onde est
o endereo, valor o
qual conduzir a outra
clula. O fato de se no
ir diretamente ao local
final caracteriza uma
indireo. Vrios nveis de
indireo surgem quando
se operam com ponteiros
de ponteiros.

114

Ricardo Reis Pereira

Um modelador um
recurso da Linguagem
Pascal que obriga um valor
de um tipo a se tornar de
outro tipo. a chamada
coero de dados. A
sintaxe de uma coero
tipo(valor) onde tipo denota
o tipo de dados para o qual
valor deve ser coagido.

i := 127;
p := @i;
q := p;

// Cpia de ponteiro

writeln(q^);

// A cpia mantm a indireo

A atribuio q:=p copia o endereo armazenado em p para o ponteiro


q. Assim q^ funciona como p^, ou seja, duas referncias varivel i. Se o tipo
base do ponteiro q no for o mesmo do ponteiro p a atribuio falhar (ocorre
um erro de compilao). Entretanto, utilizando a coero de modeladores
possvel driblar essa restrio.
Listagem 29

01

program PonteiroAplicado2;

02

type

03

PtInt = ^integer;

04
05

PtReal = ^real;
var

06

i: integer;

07

p, q: PtInt;

08

r: PtReal;

09

begin

10

i := 127;

11

p := @i;

12

r := PtReal(p);

13

q := PtInt(r);

14

writeln(q^);

15

// Coero de ponteiro de inteiro para real


// Coero de ponteiro de real para inteiro

end.

A coero de ponteiros ilustrado na Listagem 29. Foram definidos os


tipos ponteiro de inteiro (PtInt) e ponteiro de real (PtReal), nas respectivas
Linhas 03 e 04, para serem utilizados como modeladores. Na Linha-12 o
modelador coage o ponteiro de real r a receber o endereo do ponteiro de
inteiro p. O processo inverso ocorre na Linha-13 onde desta vez o ponteiro
de inteiro q coagido a receber o contedo do ponteiro de real r. Apesar
das coaes q definido como referncia da varivel i e a Linha-14 deve
imprimir 127.
No caso de ponteiros de ponteiros fundamental lembrar que para declar-los necessrio criar tipos auxiliares. J o desreferenciamento feito
com ^^. A inicializado requer compatibilidade de tipos. A Listagem 30 ilustra
o uso de ponteiros de ponteiros. Neste programa p recebe o endereo de i e
em seguida q recebe o endereo de p (q do tipo ponteiro de ponteiro). Na

Linguagem de Programao I

Linha-12 o desreferenciamento duplo q^^ necessrio porque dois nveis de


indireo esto presentes. A sada deste programa ser,
127 127 127

Listagem 30
01

program PonteiroAplicado3;

08

02

type

09

i := 127;

10

p := @i;

11

q := @p;
writeln(i, ' ', p^, ' ', q^^);

03
04

PtInt = ^integer;
var

05

i: integer;

12

06

p: PtInt;

13

07

q: ^PtInt;

begin

end.

3. Ponteiros e Arrays
Se um ponteiro aponta para uma array possvel utilizar este ponteiro como se
fosse a prpria array. O operador de indexao, [], igualmente ps-fixo no ponteiro e o valor de ndice um nmero entre 0 e len-1, onde len o comprimento
do array. No h conservao dos limites de ndices adotados no array original.
Listagem 31
01

program AplicacaoPonteiro4;

02

var

03

arr: array[1..5] of integer = (7,4,11,8,6);

04

pt: ^integer;

05

i: integer;

06

begin

07

pt := @arr[1];

08

for i := 0 to 4 do

09
10

write(pt[i], ' ');


end.

Na Listagem 31 pt recebe o endereo da primeira clula do array arr


e dessa forma pode ter acesso ao array completo. Apesar da indexao no
intervalo 1..5, o lao da Linha-08 varre a estrutura com ndices no intervalo 0..4
haja vista que o acesso realizado via ponteiro (Linha-09).
Intuitivamente percebe-se que este mecanismo de acesso de arrays
via ponteiros no implica necessariamente no apontamento para a primeira
clula. Poder-se-ia ter escrito,
pt := @arr[2];

115

116

Ricardo Reis Pereira

Nesse caso, se o limite nulo inferior for mantido, o vetor manipulvel


ser menor (em uma unidade). O lao,
for i := 0 to 3 do write(pt[i], );

imprimir os quatro elementos finais de arr. J o lao,


for i := -1 to 3 do write(pt[i], );

imprimir todo contedo de arr.


Uma string em Pascal um caso especial de array formada de caracteres. Quando um ponteiro de caractere aponta para o primeiro caractere de
uma string, este ponteiro se comporta como a prpria string podendo inclusive
ser repassado diretamente aos comandos de sada write/writeln (observe que
o mesmo no acontecem para outros tipos de arrays, apenas de caracteres).
Listagem 32
01

program ponteiros_e_strings;

02

var

03

s: string[20] = 'ola mundo!';

04

p: ^char;

05
06

p := @s[1];

07

write(p);

08

Contador de referncia
uma metodologia
utilizada para otimizar o
gerenciamento de memria
dinmica associado aos
ponteiros. Baseia-se na
definio implcita de
um contador para cada
ponteiro que armazena
o nmero de variveis
que se referem a ele.
Quando este contador zera
a memria apontada
desalocada. Dessa forma
o programador no precisa
se preocupar em desalocar
memria dinmica que
requisitou pois isso ocorre
automaticamente.

begin

end.

Na Listagem 32 o ponteiro p recebe o endereo da cadeia s (Linha-06).


A impresso (Linha-07) feita diretamente via ponteiro.
O tipo PChar em Pascal denota ponteiro de caractere (^char) com a
convenincia de permitir atribuies diretamente. Internamente uma varivel
Pchar aloca e desaloca memria convenientemente utilizando contadores
de referncia de forma a manter strings de tamanho variante.
A Listagem 33 ilustra o uso de Pchar. Nas Linhas 06 e 08 so respectivamente inicializadas, com caracteres de constantes strings, as variveis p de
tipo PChar e s de tipo string. Quando p recebe o endereo da cadeia apontada
por s (Linha-09), o contador de referncia de teste de uso de PChar zerado
e esta string desalocada. A string uma string possui agora contador de referncia igual a dois e pode ser tanto acessada por s quanto por p (Linha-10). A
sada deste programa ,
teste de uso do PChar
uma string

Linguagem de Programao I

Listagem 33
01

program uso_de_pchar;

02

var

03

p: Pchar;

04

s: string;

05

begin

06

p := 'teste de uso do PChar';

07

writeln(p);

08

s := 'uma string';

09

p := @s[1];

10

writeln(p);

11

end.

4. Ponteiros em Mdulos
Argumentos ponteiros em mdulos, sejam procedimentos ou funes, so comumente utilizados para se referir a variveis fora do escopo do mdulo (ou
seja, variveis que no so locais ao mdulo). Esse mecanismo permite que
provisoriamente seja possvel ler ou alterar variveis alheias, sejam elas escalares ou vetoriais.
Argumentos ponteiros funcionam como quaisquer ponteiros permitindo
aritmtica e desreferenciamento clula de memria endereada. H o inconveniente entretanto de, para se declarar um argumento ponteiro em um mdulo
Pascal, necessrio definir previamente um tipo ponteiro como em,
type PtInt = ^integer;
procedure proc(q: PtInt);

// O argumento de proc um ponteiro

Uma aplicao usual de argumentos ponteiros so os chamados argumentos sada. Ao invs do ponteiro trazer o endereo de uma varivel que se
deseja ler o valor, ele traz o endereo de uma varivel para onde se deseja
escrever um valor. Esta estratgia quebra as restries tanto da sada nica
das funes (pode-se usar vrios ponteiros cada qual associado a uma sada
diferente) quanto de ausncia de sada formal nos procedimentos (argumentos ponteiros agem como sada nos procedimentos).

117

118

Ricardo Reis Pereira

Listagem 34
01 program equacao_do_segundo_grau;
02 type
03

ptreal = ^real;

04
05 function eq2g(a,b,c: real; p, q: ptreal): boolean;
06 const TOL = 1.0e-8;
07 var delta: real;
08 begin
09

delta := b*b - 4*a*c;

10

if (abs(a) < TOL) or (delta<0) then begin

11

eq2g := false;

12

exit;

13

end;

14

p^ := (-b + sqrt(delta))/(2*a);

15

q^ := (-b - sqrt(delta))/(2*a);

16

eq2g := true;

17 end;
18
19 var
20

a,b,c,x1,x2: real;

21 begin
22

writeln('Coeficientes: ');

23

readln(a,b,c);

24

if eq2g(a, b, c, @x1, @x2) then

25
26

writeln('Raizes: ', x1:0:2, ' e ', x2:0:2)


else

27

writeln('Razes no podem ser calculadas!');

28 end.

Seja o problema da soluo do polinmio de segundo grau,

a x 2+ b x+ c= 0
onde devem ser fornecidos os coeficientes a, b e c e calculadas as razes, se
existirem. Pelo mtodo de Bskara as duas razes reais so dadas por,

Linguagem de Programao I

x=

b , onde
= b2 4 a c
2a

desde que a seja no nulo e seja no negativo (se a no nulo e negativo, as razes so complexas).
O programa da Listagem 34 resolve o problema da equao de segundo grau. A funo eq2g (das Linhas 05 a 17), que possui cinco argumentos,
recebe os trs coeficientes do polinmio de segundo grau via argumentos a,
b e c. A funo retorna trs sadas: as duas primeiras atravs dos argumentos
ponteiros p e q e a terceira via sada natural da funo (boolean). A sada booleana retrata o sucesso da operao.
Quando true retorna significa que existem razes reais e elas esto nas
clulas de memria apontadas por p e q. Quando false retorna, no h razes
(seja por porque a = 0 ou <0) e os valores apontados por p e q devem ser ignorados. O teste de nulidade de (no programa representado pela varivel delta)
consiste da expresso abs(delta)<TOL que verifica se o mdulo do valor em
delta est suficientemente prximo de zero para ser considerado como tal (este
o teste mais consistente para verificar nulidade de valores de ponto flutuante).
Quanto menor o valor da constante TOL (tolerncia) mais rigoroso ser o
teste de nulidade (na prtica valores de tolerncia demasiado pequenos so problemticos. Por exemplo, para uma tolerncia na ordem de 10-15, 0.0000000001
no passaria num teste de nulidade o que, em muitos casos, incoerente). Se
um dos testes da Linha-10 falhar o status da varivel interna eq2g mudado
para false e a funo manualmente encerrada (exit, Linha-12).
Do contrrio as razes so calculadas e, por desreferenciamento, registradas nas clulas apontadas por p e q (Linhas 14 e 15). Antes do encerramento da funo, eq2g (varivel interna) mudada para true (Linha-16) indicando que razes foram calculadas com xito.
A chamada de eq2g no programa principal acontece dentro de uma estrutura de deciso (Linha-24) ilustrando como possvel tomar diretamente uma
deciso a partir da sada de uma funo. Quando qualquer um dos blocos da
deciso bidirecional for executado (Linhas 25 ou 27), eq2g j ter sido executada.
A chamada a eq2g repassa como dois ltimos parmetros os endereos das variveis globais x1 e x2 que ao final portaro as razes, se existirem.
Uma importante habilidade que ponteiros permitem a mdulos o acesso a arrays fora de escopo (no locais). Para estruturar isso, repassa-se ao
mdulo o endereo da primeira clula do vetor (que pode ser ou no tipado) e
um inteiro que represente o comprimento da array ou a memria em bytes que
ela ocupa. Estando isso disponvel nos parmetros do mdulo, o acesso s

119

120

Ricardo Reis Pereira

clulas da array externa se far com a ps-fixao do operador de indexao


no ponteiro. Como visto na Sesso - 3 , o ponteiro se portar como se fosse
a array original (lembre-se que neste caso o ndice inferior sempre zero). No
prottipo,
type PtReal = ^real;
function Max(vec: PtReal; len: longint): real;

a funo Max recebe, atravs do ponteiro vec, o endereo da primeira clula de uma array cujo comprimento repassado por len. Esta funo deve
retornar o maior valor contido na array endereada por vec. O programa da
Listagem 35 contextualiza a funo Max. Nesta funo a primeira hiptese
de retorno o primeiro elemento da array (Linha-09). O lao da Linha-10,
associado ao teste aninhado na Linha-11, faz a varivel local Max ser atualizada constantemente para o maior valor at a iterao corrente. Com o
encerramento do lao Max conter o valor procurado. No programa principal,
a array global x carregada com valores aleatrios ao mesmo tempo em que
impresso na tela (Linhas 20 a 23). A chamada a Max efetuada de dentro
do writeln (Linha-25) sendo os argumentos o endereo da primeira clula de x
(@x[1]) e seu comprimento (length(x)). Um exemplo de sada do programa ,
23 82 50 49 81 90 80 73 17 32 79 45 86 56 39 89 57 49 1 26
Valor mximo = 90

Linguagem de Programao I

Listagem 35
01

program extremos;

02
03

type

04

PtReal = ^real;

05
06

function Max(vec: PtReal; len: integer): real;

07

var i: integer;

08

begin

09

Max := vec[0];

10

for i:= 1 to len-1 do

11

if vec[i]>Max then

12

Max := vec[i];

13

end;

14
15

var

16

x: array[1..20] of real;

17
18

i: integer;
begin

19

randomize;

20

for i := 1 to length(x) do begin

21

x[i] := random(100);

22

write(x[i]:0:0, );

23

end;

24

writeln;

25

writeln(Valor mximo = , Max( @x[1], length(x) ):0:0);

26

end.

5. Alocao Dinmica
Novas variveis podem ser criadas em tempo de execuo atravs do mecanismo de alocao dinmica. Estas variveis no possuem nomes e dependem de ponteiros para serem manipuladas. Ponteiros tipados possuem em
Pascal duas abordagens de alocao, a escalar e a vetorial, que so estudadas nas Sesses 5.1 e 5.2 . A alocao com ponteiros no tipados estudada
Sesso 5.3 .

121

122

Ricardo Reis Pereira

5.1. Alocao Dinmica Escalar


Na abordagem escalar uma nica clula de memria, de tamanho igual ao do
tipo base, alocada. Como no h operadores em Pascal que proporcionem
alocao dinmica, a unidade system disponibiliza os comandos new e dispose para respectivas alocao e desalocao escalar.
Listagem 36
01

program Alocacao_Dinamica_1;

02

var

03

i: integer;

04

p: ^integer;

05

begin

06

i := 120;

07

new(p);

08

p^:= i;

09

i := i div 2;

10

writeln(i, , p^);

11

dispose(p);

12

end.

O programa da Listagem 36 ilustra o uso da alocao dinmica escalar.


Uma nova varivel alocada na Linha-07. O comando new recebe como argumento o ponteiro que armazenar o endereo da varivel dinmica criada
em heap. Qualquer desreferenciamento feito com p, depois da chamada de
new, afetar a nova varivel sem nome criada dinamicamente. Na Linha-08
ocorre uma cpia do contedo em i para a varivel apontada por p. No h
relao, neste exemplo, entre i e p. Ao fazer i receber metade do prprio valor
(Linha-09) e em seguida imprimir-se i e p^ obtm-se,
60 120

Na Linha-13 dispose, que tambm recebe um ponteiro como argumento, libera a memria alocada por new.
Listagem - 37
01

program Alocacao_dinamica_2;

08

02

type

09

new(q);

10

q^.x := 3.0;

11

q^.y := 1.0;

12

q^.z := 0.5;

13

dispose(q);

03

ponto = record

04

x,y,z: real;

05
06
07

end;
var
q: ^ponto;

14

begin

end.

Linguagem de Programao I

As mesmas regras se mantm para variveis de tipo estrutura heterognea. O operador de resoluo de campo (.) mantm a mesma sintaxe. A
Listagem 37 ilustra a alocao escalar com tipo estrutura heterognea. Neste
programa o tipo record precisa ser definido (Linha-03) para que possa atuar
como tipo base na declarao do ponteiro q (Linha-07). Cada campo do record precisa de seu prprio desreferenciamento (Linhas 10, 11 e 12).

5.2. Alocao Dinmica Vetorial


Na abordagem vetorial com ponteiros tipados a memria alocada representada por uma ou mais clulas contguas de tamanho igual ao do tipo base
(ou seja, uma array). A unidade system disponibiliza, para tal abordagem, os
comandos getmem para a alocao e freemem para a desalocao. O comando getmem pode ser usado com a sintaxe,
getmem(<ponteiro>, <memria_em_bytes>);

ou ainda,
<ponteiro> := getmem(<memria_em_bytes>);

onde, em ambas, o ponteiro recebe o endereo de um bloco de memria cujo


tamanho em bytes passado como argumento. comum utilizar este comando associado com sizeof para facilitar os clculos. Por exemplo em,
getmem(pt, sizeof(integer)*10); // se integer tem 4-bytes

// ento 40-bytes so alocados

aloca um bloco de memria que compota dez inteiros e atribui para pt o endereo.
O comando freemem similar a dispose contendo como argumento
nico o ponteiro para a rea de memria que deve ser liberada. No exemplo,
freemem(pt);

a memria apontada por pt liberada.


Listagem 38
01
02
03
04
05
06
07
08
09
10
11
12
13

program Alocacao_Dinamica_3;
var

i, j, n: integer;
p, q: ^integer;

begin

write('Total: ');
read(n);
i := 0;
j := 0;

getmem(p, sizeof(integer)*n);
q := p;

while j<n do begin

if (i mod 3 = 0) and (i mod 7 <> 0) then begin

14

q^ := i;

15

q := q + sizeof(integer);

16

inc(j);

17
18
19
20
21
22
23
24
25

end;

inc(i);

end;

for i := n-1 downto 0 do begin

q := p + i * sizeof(integer);
write(q^, ' ');

end;

freemem(p);

end.

123

124

Ricardo Reis Pereira

O programa da Listagem 38 ilustra o uso de getmem e freemem. O programa imprime em ordem decrescente os primeiros n inteiros (n fornecido pelo
usurio) que so divisveis por 3 mas no so divisveis por 7. Para armazenar
estes valores alocado, na Linha-10, o espao necessrio em heap.
Para acessar individualmente cada uma das n clulas que compe o bloco, utiliza-se um ponteiro auxiliar q. H dois contextos de uso de q no programa:
o da Linha-15, engajado na inicializao da array e o da Linha-21, utilizado na
impresso dos dados.
Os comandos inc e
dec, unidade system,
fazem respectivamente
a incrementao e
decrementao numrica
de variveis ordinais
(inteiros, caracteres e
enumeraes). Estes
comandos possuem
verses de um e dois
argumentos. Na verso
de um argumento o
total incrementado (ou
decrementado) um. Na
verso de dois argumentos
este valor corresponde
ao segundo argumento.
Assim, se x contm 3, as
chamadas inc(x) e dec(x)
fazem x mudar para 4 e
2 e as chamadas inc(x,3)
e dec(x,2) para 6 e 1
respectivamente.

Na Linha-15 o valor do endereo em q incrementado de sizeof(integer)


em cada iterao do lao da Linha-12 cujo teste da Linha-13 obtm sucesso.
Haja vista que o valor inicial de q o mesmo de p (Linha-11), ento q passa por
cada clula da array dinmica (ver Figura - 9). Assim as atribuies da Linha-14
armazenam os valores encontrados em suas posies apropriadas na array.
J na Linha-21 as posies apropriadas so calculadas diretamente por uma
expresso completa causando o mesmo efeito de acesso.

Figura 9

O operador de indexao, [], pode ser usado com ponteiros tipados que
apontam para vetores dinmicos. O resultado exatamente a mesma sintaxe
de arrays estticas. Por exemplo,
q := p + sizeof(integer)*i;
q^ := 21;

equivalente a,
p[i] := 21;
Essa sintaxe dispensa o uso na varivel auxiliar.

Linguagem de Programao I

Listagem 39
01

program Alocacao_Dinamica_4;

11

02

var

12

while j<n do begin


if (i mod 3 = 0) and (i mod 7 <> 0) then begin

03

i, j, n: integer;

13

p[j] := i;

04

p: ^integer;

14

inc(j);

05

15

end;

06

begin
write('Total: ');

16

inc(i);

07

read(n);

17

end;

08

i := 0;

18

for i := n-1 downto 0 do write(p[i], ' ');

09

j := 0;

19

freemem(p);

10

getmem(p, sizeof(integer)*n);

20

end.

Reescrevendo-se a Listagem - 38 utilizando o operador de indexao,


obtido o programa da Listagem 39.
Em alguns compiladores Pascal o uso do operador de indexao ps-fixado
a ponteiros no diretamente suportado. Se este for o caso a sada alocar memria para um ponteiro de um array de uma nica clula. A Listagem 40 ilustra o uso
desta tcnica. O programa imprime em ordem inversa os primeiros dez termos da
srie de Fibonacci. O tipo array na Linha-08 permite a criao de arrays de apenas
uma clula (indexao de zero a zero) e vec (Linha-05) um ponteiro deste tipo.
A memria alocada para vec (Linha-10) deve ser a do vetor completo (neste caso
um total de max clulas). Como o tipo IntVec restringe os limites entre zero e zero,
o compilador emitir advertncias sobre o uso de limites fora desta faixa (isso no
compromete o funcionamento programa). Nas Linhas 11, 12, 14 e 16 notrio que
o uso do vetor dinmico exige o circunflexo de acordo com a sintaxe,
<ponteiro>^[<indice>]

que s necessria no contexto apresentado dos ponteiros de arrays.

125

126

Ricardo Reis Pereira

Listagem 40
01 program Alocacao_Dinamica_5;
02 type
03

IntVec = array[0..0] of integer;

04 var
05

vec: ^IntVec;

06

i: integer;

07 const
08

max = 10;

09 begin
10

vec := getmem( sizeof(integer)*max );

11

vec^[0] := 1;

12

vec^[1] := 1;

13

for i := 2 to max-1 do

14

vec^[i] := vec^[i-1] + vec^[i-2];

15

for i := max-1 downto 0 do

16

write(vec^[i], ' ');

17

freemem(vec);

18 end.

5.3. Usando Ponteiros No Tipados


Ponteiros no tipados podem conter endereos para quaisquer variveis. Isso
significa que, se o ponteiro for a nica varivel disponvel num dado contexto,
ento no ser possvel determinar o tipo da informao apontada. Na maioria
dos casos necessrio fornecer alguma informao adicional como tamanho
da clula de memria apontada.
Para ilustrar isso considere o problema geral de zerar todos os bytes
de uma estrutura qualquer, independente de ser um escalar (como inteiro
ou real), uma estrutura heterognea ou uma array. O procedimento zerar da
Listagem 41 resolve a questo. O argumento p recebe o endereo de uma
estrutura qualquer enquanto size recebe seu tamanho em bytes. Utilizando o
lao da Linha-05 e a expresso p+i na Linha-06, o ponteiro p passa por cada
um dos bytes que forma a estrutura (como uma array de bytes) e por desreferenciamento zera-se o contedo ali (Linha-07). O nmero de passos do lao
o total de bytes da estrutura.

Linguagem de Programao I

127

Listagem 41
01

procedure zerar(p: pointer; size: longint);

02

var i: longint;

03

b: ^byte;

04

begin

05

for i := 0 to size-1 do begin

06

b := p + i;

07

b^ := 0;

08

end;

09

end;

Se x uma varivel real e precisa ter os bytes zerados pelo procedimento zerar, deve-se escrever,
zerar(@x, sizeof(real));

Se y for uma varivel de uma estrutura heterognea chamada Reg, seus bytes
podem ser zerados com,
zerar(@y, sizeof(Reg));

Se vec for uma array de inteiros que precisa ter os bytes zerados ento deve-se escrever,
zerar( @vec[1], sizeof(integer)*length(vec) );

Em caso de alocao dinmica, os comandos getmem e freemem, da


unidade system, permitem tambm a alocao de memria utilizando pomeiros no tipados. A memria alocada com ponteiros no tipados pode ser manipulada utilizando aritmtica de ponteiros. Por exemplo, para criar um bloco
de memria que armazene 25 valores reais de 4-bytes utiliza-se,
getmem(p, 100); // 25x4 = 100-bytes

onde p no tipado. Para aplicar a aritmtica deve-se utilizar um ponteiro


auxiliar de real conforme expresso,
q := p + i*4;

onde q de tipo ^real e i inteiro. Variando i entre 0 a 24 faz-se q referir-se a


cada uma das 25 posies de clulas dentro do bloco alocado. Para acessar
cada clula deve-se desreferenciar q logo aps receber o resultado na expresso. No exemplo,
for i := 0 to 24 do begin
q := p + i*4;
q^ := 1000/(i+1);
end;

o bloco alocado via p recebe os valores 1000.0, 500.0, 333.4, 250.0 40.0.

Aritmtica de Ponteiros:
termo utilizado para se
referir s operaes
de soma e subtrao
de ponteiros com
deslocamentos de
memria (medidos em
bytes). Esta aritmtica
no prev operaes
entre ponteiros por ser
incoerente. Seu grande
objetivo referenciar
corretamente clulas de
memria vizinhas a uma
clula dada.

128

Ricardo Reis Pereira

Uma alternativa s expresses oriundas da aritmtica de ponteiros a


coero do ponteiro no tipado em tipado. Neste caso retoma-se o operador
de indexao []. Reescrevendo-se o exemplo anterior tem-se,
q := p;

// Coero

for i := 0 to 24 do
q[i] := 1000/(i+1);

onde p no tipado e q de tipo ^real. A coero faz q funcionar como uma


array de 25 valores real.

6. Problemas com Ponteiros


Os principais problemas causados por ponteiros so,
Ponteiros Pendurados
Vazamento de Memria
Um ponteiro pendurado aquele cujo endereo armazenado deixou
de ser seguro. Aps uma chamada a dispose ou freemem a rea de memria apontada liberada, mas o valor de endereo armazenado pelo ponteiro
mantido. O desreferenciamento acidental deste ponteiro a partir deste
ponto (sem reapontamento ou realocao) caracterizar acesso ilegal de
memria. Se o programador no puder redefinir o valor do ponteiro logo
aps a liberao de memria ento aconselha-se faz-lo apontar para lugar
nenhum, ou seja,
...
dispose(p);
p := nil;

// ponteiro novamente seguro

Vazamento de memria (memory leak) a perda de acesso a um bloco


de memria alocado dinamicamente. Isso acontece quando o ponteiro que
aponta para a rea dinmica alocada passa acidentalmente a apontar para
outra parte da memria sem desalocao prvia. O bloco de memria sem
referncia chamado memria perdida em heap e no pode ser reutilizado
at que o programa seja encerrado.

Linguagem de Programao I

129

Listagem 42
01 program Vazamento_de_Memoria;
02 var
03

p: ^integer;

04

i: integer;

05 begin
06

new(p);

07

p := @i;

08

dispose(p);

09 end.

O programa da Listagem 42 Ilustra o vazamento de memria. A memria


alocada via p (Linha-06) perdida em heap quando p redefinido para apontar
para i (Linha-07). A chamada a dispose (Linha-08) no surte efeito nem sobre a
rea alocada dinamicamente (ela est perdida em heap) nem sobre a de i que
p agora aponta (por ter sido alocada estaticamente). A Figura - 10 esquematiza
o vazamento de memria implementado na Listagem 42.

Figura 10

Um exemplo crtico de vazamento de memria, conhecido como ladro


de memria, usa um lao infinito para gerar incontveis blocos perdidos em
heap. Em Pascal implementa-se,
while true do new(p);

No recomendada a execuo do ladro de memria.

7. Estudo de Caso: Lista Escadeada Elementar


O primeiro passo para implementar uma lista encadeada elementar em
Pascal a definio de uma estrutura heterognea para os nodos da lista.
Considerando uma lista de valores inteiros ento o tipo nodo proposto ,

Lista Encadeada
Elementar: uma lista
de objetos, denominados
nodos, cujo tipo
corresponde a um tipo
estruturado heterogneo
contendo um campo da
chave e outro de ponteiro
do prprio tipo estrutura
heterognea em questo.
Isso permite que o primeiro
nodo da lista contenha
uma chave e o endereo
para o segundo nodo que
contm outra chave e o
endereo para o terceiro
nodo e assim por diante.
O ltimo nodo da lista
aquele que contm uma
chave e um endereo para
parte alguma.

130

Ricardo Reis Pereira

pnodo = ^nodo;
nodo = record
chave: integer;
prox: pnodo;
end;

Observe a necessidade de definio de um tipo ponteiro de nodo antes da definio da prpria estrutura. Isso levanta duas questes. A primeira
para que? e a segunda como possvel?. A resposta da primeira pela
necessidade de definio de prox que conter uma referncia ao prximo
nodo da lista e dinamicamente isso deve ser feito via um endereo de nodo.
A segunda na realidade uma nova faceta do Pascal. Apesar de ser apenas
definido na linha seguinte, o tipo nodo pode sim ser utilizado para definir pnodo. Esse fenmeno conhecido como declarao prematura e exclusiva
dos tipos ponteiros.
Para definir a lista propriamente dita propomos um outro tipo estrutura
heterognea denominado lista como segue,
lista = record
raiz: pnodo;
total: integer;
end;
plista = ^lista;

Este novo tipo mantm um ponteiro raiz para o primeiro nodo da lista
e o total de nodos listados. Apesar de no serem visveis diretamente nessa
estrutura, os demais nodos estaro presentes pois o primeiro aponta para o
segundo, que aponta para o terceiro e assim sucessivamente. O tipo plista
necessrio para possibilitar a mdulos afetarem uma lista que recebam como
argumento. Por exemplo para inicializar uma lista deve-se utilizar o procedimento,
procedure Init(Q: plista);
begin
Q^.raiz := nil;
Q^.total := 0;
end;

init zera uma lista tanto em nodos quanto em contagem. Pode ser chamado
assim,

Linguagem de Programao I

var
L: lista;
begin
init(@L);
...

Para inserir uma nova chave numa lista prope-se o seguinte algoritmo:
(i) constri-se dinamicamente um novo nodo contendo a chave de insero; (ii)
Faz-se o prox desse novo nodo apontar para o primeiro nodo da lista, ou seja,
raiz, (iii) faz-se raiz da lista apontar para este nodo e (iv) incrementar o campo
total da lista em uma unidade para indicar que um novo nodo foi inserido.
Assim a ltima chave inserida sempre a primeira da lista e a proporo
que novas chaves so inseridas as mais antigas vo ficando mais distantes de
raiz. O procedimento da Listagem 43 implementa a insero. A lista repassada via ponteiro Q e a chave de insero via inteiro x. As etapas so marcadas
como comentrios.
Listagem 43
01

procedure inserir(Q: plista; x: integer);

02

var p: pnodo;

03

begin

04

new(p);

05

p^.chave := x;

06

p^.prox := Q^.raiz;

// (ii)

07

Q^.raiz := p;

// (iii)

08

inc(Q^.total);

09

// (i)

// (iv)

end;

Para imprimir em sada padro o contedo de uma lista deve-se varr-la desde o nodo raiz at o ltimo nodo (aquele cujo prox vale nil). Para tanto
utiliza-se um ponteiro auxiliar de pnodo e um lao pr-teste. O procedimento
imprimir na Listagem 44 Implementa o processo. O ponteiro auxiliar p inicializado com o valor de raiz da lista apontada por Q (Linha-04). O lao na
Linha-05 verifica se o final da lista j foi alcanado ao passo que a atribuio
na Linha-07 provoca um salto de um nodo para outro. Cada nodo visitado por
p tem a chave impressa na Linha-06.
Para eliminar toda uma lista encadeada elementar da memria propomos o seguinte algoritmo: (i) Se o campo raiz diferente de nil ento siga para
o passo ii, do contrrio termine; (ii) Fazer uma cpia do endereo em raiz
num ponteiro auxiliar de pnodo; (iii) Fazer prox de raiz se tornar o novo raiz;
(iv) aplicar dispose no ponteiro auxiliar e voltar para i. A Listagem 45 ilustra o

131

132

Ricardo Reis Pereira

processo e os passos so marcados como comentrios. A Linha-09 adicionalmente zera o campo de contagem de nodos trazendo a lista ao estado inicial
de vazia.
Listagem 44
01

procedure imprimir(Q: plista);

02

var p: pnodo;

03

begin

04

p := Q^.raiz;

05

while p <> nil do begin

06

write(p^.chave, ' ');

07

p := p^.prox;

08
09

end;
end;
Listagem 45

01

procedure limpar(Q: plista);

02

var p: pnodo;

03

begin

04

while Q^.raiz <> nil do begin

// i

05

p := Q^.raiz;

// ii

06

Q^.raiz := p^.prox;

// iii

07

dispose(p);

// iv

08

end;

09

Q^.total := 0;

10

end;

Sntese da Parte 2
No Captulo - 3 foi tanto apresentada a sintaxe bsica de definio de
tipos personalizados quanto as estruturas nativas do Pascal que permitem a
modelagem de objetos enumerados (enumeraes), de objetos segmentados
por campos (estruturas heterogneas) e objetos agrupveis (conjuntos). No
Captulo - 4 foram introduzidos e contextualizados os ponteiros. Foram apresentadas que relaes eles mantm com outras construes da linguagem
como arrays e mdulos assim como a importante participao que exercem
no mbito da alocao dinmica de memria. Problemas com ponteiros so
tambm abordados. O captulo encerra com o estudo de caso da lista encadeada elementar.

Linguagem de Programao I

Atividades de avaliao
1. Reescreva o programa da Listagem-4.7 de forma que seja possvel, com
as informaes de sada, saber o tipo de problema que inviabilizou o clculo das razes, quando esse for o caso.
2. Construir mdulo que inverta a sequncia dos caracteres de uma string
(use Pchar).
3. Construa mdulo que receba um vetor e retorne o maior e menor valor
existente.
4. Construa mdulo que receba um vetor e retorne os dois maiores valores
existentes.
5. Escrever duas verses de programa, uma utilizando arrays dinmicas e
outra utilizando alocao dinmica, para resolver o problema de receber
uma quantidade arbitrria de notas de alunos (esta quantidade de notas
tambm entrada) e determine o valor do desvio padro da amostra. O desvio padro de uma amostra x 1 , x 2 , x 3 , ... , x n dada por,
onde x i se refere a i-sima nota e

mdia de todas as notas.

6. Seja P um ponteiro que aponta para um bloco de memria alocado dinamicamente. Se P precisar apontar para um bloco de memria maior, sem
perder as informaes para as quais j aponta, deve-se: (I) alocar o novo
espao, maior que o anterior; (II) copiar todo contedo do bloco apontado
por P para a nova memria alocada; (III) desalocar o espao apontado
por P; (IV) apontar P para a nova memria alocada. O processo de cpia
deve ser de tal forma que independa do tipo de informao apontada.
Construir mdulo com este fim e contextualiz-lo num programa.
7. Crie uma estrutura vector (usando estruturas heterogneas) que mantenha dois campos: um ponteiro de real data e um inteiro n. O campo data
refere-se a um vetor de real cujo comprimento o valor do campo n.
Construa tambm mdulos que permitam as seguintes operaes com
variveis de tipo vector: (a) construtor (recebe um comprimento qualquer
e retorna um vector novo com tal comprimento e com todos os elementos
de data iguais a zero); (b) valor modular (retorna raiz quadrada da somatria dos quadrados dos elementos de data); (c) normalizador (modifica
um vector de forma que todos os elementos em data sejam divididos
pelo valor modular); (d) destrutor (recebe um vector, desaloca a memria
apontada por data e zera seu comprimento).

133

134

Ricardo Reis Pereira

8. Implementar para a lista encadeada elementar as operaes seguintes:


busca de uma chave, remoo de uma chave e reverso da lista (disp-la no sentido contrrio).

Referncias
CANNEYT, Michal Van, Reference guide for Free Pascal, Document
version 2.4 , March 2010
http://www.freepascal.org/docs-html/
http://en.wikipedia.org/wiki/Tower_of_Hanoi

Parte
Modularizao

Captulo

Modularizao
Objetivos:
A modularizao, estudada no Captulo-1 desta unidade, uma tcnica
que permite a segmentao de um programa em unidades menores mais
fceis de gerenciar. So as funes e os procedimentos. Para estud-la
com mais detalhes o captulo aborda noes sobre controle e processo
bem como um estudo mais aprofundado sobre o mecanismo de passagem de argumentos introduzido no Captulo-1. O captulo ainda cobre
outros importantes conceitos relacionados como a recursividade e o aninhamento modular. O Captulo-2 finaliza a unidade apresentado os recursos que o Pascal disponibiliza para a manipulao de arquivos. Isso inclui
desde fundamentos sobre o funcionamento da memria secundria at
recursos e comandos que permitiro a implementao de programas que
manipulem arquivos.

1. Noes de Controle e Processo


Sistemas operacionais modernos permitem a execuo simultnea de vrios
programas. Esta simultaneidade na verdade aparente porque existem poucos processadores (ou mesmo somente um) que devem resolver todas as
solicitaes dos programas em execuo. O sistema operacional cria uma fila
de solicitaes dos programas (chamados comumente de processos) para
que sejam resolvidas uma a uma pela primeira CPU livre.
As solicitaes entram na fila conforme o momento que so invocadas
de forma que pendncias de diversos programas podem estar presentes. A
alta velocidade de processamento faz os usurios no sentirem a permutao
de atendimento de solicitaes entre programas. O multiprocessamento se
resume ento no compartilhamento do tempo de trabalho das CPUs entre
fragmentos de tarefas nos quais os processos so quebrados.

O Compartilhamento de
Tempo ou Time Sharing
um recurso das CPUs
modernas que surgiu pela
necessidade de execuo
concorrente de vrias
aplicaes. Sistemas
que tiram proveiro deste
recurso so denominados
Sistemas Multitarefas

138

Ricardo Reis Pereira

O compartilhamento de tempo entre processos ocorre de forma similar dentro de cada processo onde tarefas internas competem pelo tempo
de CPU(s) da aplicao. Estes subprocessos competindo entre si so denominados threads. Se mais de um thread est envolvido diz-se tratar-se
uma aplicao multithreading.
Cada thread (caso mais de um esteja envolvido) segue um fluxo de
execuo que comea num programa principal e pode ser desviado para um
mdulo (funo ou procedimento). Dessa forma apenas um dado mdulo (ou
o programa principal), num thread, executa por vez. Diz-se neste contexto que
aquele mdulo (ou o programa principal) possui o controle do fluxo. Quando
ocorre desvio de controle, ou seja, um mdulo chamado, este passa a possuir o controle e o chamador deve aguardar sua finalizao para resgat-lo de
volta. Um programa termina sua execuo quando o controle, que est com o
programa principal, retornado ao sistema operacional.
Os programas em Pascal estudados neste livro executam sobre um
nico thread de forma que o fluxo de controle est exatamente com foco num
nico mdulo (ou no programa principal) num dado instante da execuo.
Os comandos round, trunc,
frac e int, unidade system,
so comandos utilizados
para operar nmeros
reais. Todos possuem
apenas um argumento de
entrada. Round e trunc
retornam respectivamente
o arrendondamento e o
piso do valor de entrada,
ambos inteiros. Frac
retorna a parte fracionria
da entrada, tambm real e
Int retorna uma verso real
da parte inteira da entrada.
Os exemplos round(4.8),
trunc(4.8), Frac(4.8)
e Int(4.8) devolvem
respectivamente 5, 4, 0.8
e 4.0.

O controle de uma funo ou procedimento pode foradamente ser devolvido ao seu chamador, ou seja, antes do trmino da execuo completa de
seu cdigo. O comando exit, unidade system, efetua esta tarefa. Por exemplo,
no procedimento,
procedure print(n: integer);
begin

if n<0 then exit;

while n>0 do begin


write(n);

n = n div 3;

end;

end;

quando valores negativos so repassados o procedimento chama exit devolvendo imediatamente o controle ao chamador. Do contrrio uma sequencia
de valores impressa por ao da execuo do lao while.
Como visto anteriormente, funes possuem uma varivel interna com
mesmo nome da funo e cujo valor antes da devoluo de controle ao chamador justamente seu retorno. Assim a presena de um exit numa funo
estratgica quando o valor de retorno j foi determinado, mas o final da funo
ainda no foi alcanado (linha contendo o ltimo end; da funo) . No exemplo,

Linguagem de Programao I

139

procedure print(n: integer);


begin
if n<0 then exit;
while n>0 do begin
write(n);
n = n div 3;
end;
end;

caso a entrada seja um valor negativo, ento a funo deve retornar imediatamente ao chamador com retorno zero. Para implementar esse comportamento
associou-se uma estrutura de deciso (que verifica a possvel negatividade de
n), uma atribuio direta do valor 0 a fnc (varivel interna) e uma chamada a exit.
Um programa tambm pode devolver diretamente o controle ao sistema
operacional independendo do mdulo que esteja executando. Isso representa
matar o programa e em Pascal conseguido com uma chamada ao comando
halt, unidade system.

2. Parmetros Formais e Reais


No Captulo-1 as funes e os procedimentos foram introduzidos como mdulos construtivos de um programa. De fato estes devem trabalhar como subprogramas cujas entradas so os parmetros e a sada o retorno (para o caso
de funes). Se um dado mdulo possui argumentos, eles devem ser fornecidos no momento da chamada seguindo a ordem de declarao e utilizando
tipos apropriados. As variveis utilizadas na definio dos argumentos de um
mdulo so chamadas de parmetros formais do mdulo. As constantes e/
ou variveis repassadas numa chamada de mdulo, e que alimentarem os
parmetros formais, so chamados parmetros reais.
Seja, por exemplo, o prottipo (cabealho) de funo,
function teste(x: integer; y: real): boolean;

ento a chamada seguinte legal,


b := teste(5, 6.0);

onde b booleano. Aqui x e y so parmetros formais e 5 e 6.0 so parmetros


reais. A presena da parte decimal no segundo argumento ajuda o compilador
a reconhecer o valor como real. Se os valores repassados como parmetros
reais possuem tipos diferentes dos parmetros formais, o compilador tenta
fazer a converso, como no exemplo,
teste(5, 6);

O piso de um valor real x


o maior inteiro menor ou
igual a x. Representa-se
por.O teto de um valor real
x o menor inteiro maior
ou igual a x. Representa-se
por.

140

Ricardo Reis Pereira

Neste caso o 6 inteiro convertido para um valor real. Se for porm a situao
seguinte,
teste(5.0, 6.0);

causar um erro de compilao porque 5.0 (que real) no pode ser transformado em inteiro diretamente. Estas situaes caracterizam a coero em
Pascal. Coagir um valor significa transform-lo noutro tipo. A coero pode ser
de estreitamento ou de alargamento. No estreitamento o tipo final do valor
menos expressivo (possui menor memria ou representa faixas mais restritas
de valores) e por isso pode ocorrer perda de dados. Exemplos so, de real
para integer, de longint para char, extended para real e etc. No alargamento
ocorre exatamente o inverso e logo no h perda de dados.
Em Pascal a coero de alargamento entre parmetros reais e formais normalmente aceita pelo compilador desde que haja compatibilidade.
Entretanto a coero de estreitamento frequentemente reporta um erro. A rigor
as restries de coero tambm ocorrem em atribuies explcitas como,
x := y;

se x e y forem de tipos distintos ou for necessria uma coero de estreitamento, o compilador reportar um erro de converso.
A passagem de valores entre parmetros formais e reais conhecida
como atribuio implcita.

3. Modos de Passagem de Argumentos


H em Pascal trs modos distintos de passagem de argumentos em mdulos
(sejam procedimentos ou funes). So,
Por Valor (ou cpia)
Por Endereo
Por Referncia
Na passagem por valor os parmetros reais tm seus valores copiados
para os parmetros formais (como a maioria dos exemplos vistos at aqui).
Este modelo isola ao mximo o contexto de quem chama do contexto de
quem chamado.
Na chamada por endereo o parmetro formal de tipo ponteiro do tipo
do parmetro real. Este modelo permite que um dado mdulo tenha acesso a
informaes que esto em outras partes do programa. Na prtica o chamador
conceder ao argumento ponteiro do mdulo chamado acesso a uma de suas
variveis locais, a uma varivel global ou ainda a um ponteiro que detm. Por
exemplo em,

Linguagem de Programao I

type
ptint = ^integer;
procedure inc(q: ptint);
begin
q^:= q^ + 1;
end;

o argumento formal q recebe o endereo de um inteiro que est fora do procedimento inc e, por desreferenciamento, permite mudar a clula de memria
apontada (neste exemplo aumenta de uma unidade o inteiro com endereo
em q). Em Pascal necessrio antes predefinir o tipo ponteiro (uso de type)
antes de utiliz-lo como tipo de um argumento formal (neste exemplo ptint
definido previamente). Como o argumento real precisa ser um endereo, ento uma chamada vlida a inc ,
x := 56;

// x inteiro

inc(@x);
write(x);

// 57

Como j visto no Captulo - 4, a prefixao de @ numa varivel representa


semanticamente o endereo desta varivel. Repassar apenas o x significa
naturalmente uma tentativa invlida de coero (inteiro para endereo de inteiro) reportada com erro pelo compilador. Como o procedimento inc possui
permisso de mudar o contedo da clula de memria com endereo em q,
ento o valor em x de fato incrementado da unidade.
Ponteiros, em argumentos formais, so comumente utilizados para se referir a arrays (em aplicaes que lidam com arrays muito grandes seria problemtica a passagem de argumentos por valor pois demandaria muito tempo em cpia
de dados alm do desperdcio de memria). Uma funo, por exemplo, para procurar o valor mximo em uma array de inteiros pode ter prottipo,
type ptint = ^integer;
function max(arr: ptint; int len): integer;

Neste caso como deve ser repassado uma array de inteiros, ento o primeiro
argumento um ponteiro de inteiro (ir receber o endereo para o primeiro
inteiro da array). O comprimento da array deve ser repassada como segundo
argumento (por valor) e as clulas individuais podero ser acessadas pelo
operador ps-fixo [] (os valores de ndice esto entre 0 e len-1). Para usar a
funo max deve-se repassar naturalmente o endereo da primeira clula de
uma array de inteiros existente como,

141

142

Ricardo Reis Pereira

var
data: array[1..10] of integer;
x: integer;
begin
{...}
x := max(@data[1], 10);
{...}

Esta sintaxe entretanto problemtica porque depende do comprimento da


array e do uso explcito de ponteiros. Uma alternativa definir o parmetro
formal com a mesma sintaxe de uma array dinmica. Exemplo,
procedure teste(x: array of integer);
{...}

O efeito o uso da passagem por endereo, mas sem necessidade de fornecer o comprimento ou usar operadores de ponteiros. A Listagem 46 Ilustra
o uso deste recurso. Na Linha-03, data no uma array dinmica mas sim
um ponteiro para uma array. Seu uso similar entretanto a uma array dinmica incluindo ndice limite inferior igual a zero (Linha-06). A array definida na
Linha-12 repassada a max (Linha-14) sem o uso dos operadores @ e [].
Listagem 46
01

program maximo;

02
03

function max(data: array of integer): integer;

04

var k: integer;

05

begin

06

max := data[0];

07

for k := low(data) to high(data) do

08
09

if data[k] > max then max := data[k];


end;

10
11

const

12
13

arr: array[1..10] of integer = (23,41,64,11,9,2,29,88,76,52);


begin

14
15

writeln( max(arr) );

// 88

end.

A terceira e ltima forma de passar um argumento para um mdulo


Pascal utilizando referncias. Uma referncia nada mais que um ponteiro camuflado. Elas permitem que um argumento formal se torne um apelido

Linguagem de Programao I

do parmetro real sem uso explcito de ponteiros ou seu operadores. Assim


qualquer modificao realizada sobre o argumento formal estar de fato alterando o argumento real. Esta estrada de duas vias obriga ento que argumentos reais, cujos argumentos formais so referncias, sejam necessariamente
variveis. Para definir um argumento de mdulo como uma referncia basta
torn-lo membro de uma sesso interna var. Nos exemplos de prottipos,
procedure teste_1 (var x: integer);
function teste_2 (var a, b: real): boolean;
procedure teste_3 (y: integer; var ch: char);

os argumentos formais x, a, b e ch so exemplos de referncias. Observe em


teste_3 que y no referncia pois no est numa sesso interna var. Para
demonstrar o uso de referncias considere o procedimento,
procedure dobrar(var x: integer);
begin
x := x*2;
end;;

O procedimento dobrar duplica o valor que est armazenado no parmetro formal x. Como x uma referncia, a operao ter efeito sobre o
parmetro real que for repassado numa chamada a dobrar. Exemplo,
var
q: integer;
begin
q := 26;
dobrar(q);
writeln(q);

// 52

end.

O uso de referncias permite que procedimentos possam funcionar como


funes, ou seja, possuam uma sada tangvel. Por exemplo, no prottipo,
procedure get(a, b, c: integer; var x: real);

pode-se abstrair que a, b e c so argumentos de entrada e que x um argumento de sada. Em geral o valor que x contm na entrada do mdulo no
importante, mas seu estado final, antes do retorno do controle, representa o
valor de sada. No programa da Listagem 47 a funo eq2g recebe trs argumentos por valor (coeficientes de um polinmio de segundo grau) e gera trs
sadas: duas atravs dos argumentos (referncias) x1 e x2 (razes do polinmio) e uma terceira sada natural da funo (booleano). Semanticamente a
funo tenta calcular as razes e coloc-las em x1 e x2.

143

144

Ricardo Reis Pereira

Quando o primeiro coeficiente nulo ou o delta negativo (teste da


Linha-07) a funo retorna com false (associao das Linhas 08 e 09). As
razes so calculadas nas Linhas 11 e 12 e a validade delas validada pelo
retorno true adiante (Linha-13). No programa principal p e q funcionam como
argumentos reais de eq2g que chamada dentro de uma estrutura de deciso (Linha-22). Um retorno true de eq2g indica que as razes de fato existem,
foram calculadas e armazenadas nas variveis p e q. A deciso ento desvia
para a impresso dos valores de razes (Linha-23). Do contrrio nenhuma raiz
calculada e sequer o contedo de p e q so modificados. O desvio para a
impresso da mensagem na Linha-25 indica isso.
Listagem 47
01

program equacao_do_segundo_grau;

02
03

function eq2g(a, b, c: real; var x1, x2: real): boolean;

04

var delta: real;

05

begin

06

delta := b*b - 4*a*c;

07

if (abs(a)<0.001) or (delta<0) then begin

08

eq2g := false;

09

exit;

10

end;

11

x1 := ( -b + sqrt(delta) )/(2*a);

12

x2 := ( -b - sqrt(delta) )/(2*a);

13

eq2g := true;

14

end;

15
16

var

17

c: array[1..3] of real;

18

p, q: real;

19

begin

20

write('Coeficientes: ');

21

readln(c[1], c[2], c[3]);

22

if eq2g(c[1], c[2], c[3], p, q) then

23

writeln( p:0:3, ' ', q:0:3 )

24

else

25
26

writeln('Polinomio invalido ou raizes complexas!');


end.

Linguagem de Programao I

145

4. Recursividade
A recursividade um recurso de linguagem que permite um mdulo, seja
ele funo ou procedimento, fazer uma chamada de si mesmo, ou seja,
dentro do corpo de cdigo do mdulo possvel fazer uma ou mais chamadas daquele mdulo. A recursividade permite implementaes mais
claras de diversos algoritmos e por essa razo um recurso nativo do
Pascal. Para calcular, por exemplo, o fatorial de um inteiro pode-se usar
a seguinte funo,
function fat(n: integer): integer;
begin
if n<2 then
fat := 1
else
fat := n * fat(n-1);
end;

Nesta funo o identificador fat, sem qualquer cdigo ps-fixado, representa a varivel interna cujo valor antes da finalizao da funo seu valor de
retorno. O mesmo identificador com os parnteses ps-fixados, fat(n-1), possui semntica diferente e representa uma chamada recursiva ao mdulo fat.
Observe que o argumento desta chamada o valor de entrada n decrescido
de uma unidade e logo o retorno da funo deve ser n multiplicado pelo fatorial
de n-1.
Este retorno entretanto no pode devolver imediatamente o controle ao
chamador porque depende do retorno da chamada a fat(n-1). Por sua vez esta
chamada causar outra chamada, desta vez a fat(n-2), e esta a fat(n-3) e assim
por diante. Cada vez que uma nova chamada realizada a fat, uma nova verso da funo empilhada em memria sobre aquela que a chamou gerando
uma cadeia de dependncias de retorno.
O processo de empilhamento de funes seria infinito no fosse a condio de parada implementada nas duas primeiras linhas de cdigo do corpo de
fat. O if obriga que entradas menores que 2 retornem imediatamente o valor 1
(o fatorial de 0 e 1 de fato 1, mas o fatorial de valores negativos no existe, por
isso cautela no uso desta funo).
Assim quando o empilhamento alcanar valores menores que 2, nenhuma nova chamada recursiva ser realizada e comear um processo, de trs
para a frente (em relao a ordem das chamadas recursivas) de resolues de
retornos at que a chamada original seja alcanada. A sequncia de operaes
a seguir descreve o clculo do fatorial de 5 pela funo fat,

Alm da palavra reservada


var, as sesses de
argumentos formais em
mdulos contam com a
palavra reservada out
para definir referncias.
Out ajuda, pelo menos em
ingls, a lembrar que o
argumento deve funcionar
como sada.

146

Ricardo Reis Pereira

Fat(5)

// 1 chamada pendente

5 * fat(4)

// 2 chamadas pendentes

5 * 4 * fat(4)

// 3 chamadas pendentes

5 * 4 * 3 * fat(2)

// 4 chamadas pendentes

5 * 4 * 3 * 2 * fat(1) // 5 chamadas pendentes


5 * 4 * 3 * 2 * 1

// 4 chamadas pendentes

5 * 4 * 3 * 2

// 3 chamadas pendentes

5 * 4 * 6

// 2 chamadas pendentes

5 * 24

// 1 chamada pendente

120 // resolvido

O jogo Torre de Hani foi


inventado pelo matemtico
Francs douard Lucas
em 1883. douard teve
inspirao de uma lenda
Hindu para construir o
jogo. J seu nome foi
inspirado na torre smbolo
da cidade de Hani, capital
e segunda maior cidade do
Vietn.

Para ilustrar um uso mais sofisticado da recursividade, consideremos


o problema da Torre da Hani. Sejam trs pinos A, B e C onde se podem
empilhar discos perfurados de dimetros distintos. O objetivo do problema
mover todos os discos que esto no pino A (origem) para o pino B (destino)
utilizando o pino C como auxiliar. H duas restries associadas, (i) nunca um
disco poder ficar sobre outro de dimetro menor e (ii) s poder ser movido
um disco de cada vez. Inicialmente A contm n discos empilhados em ordem
decrescente de dimetro de baixo para cima e os outros dois esto vazios.

Para movimentar n discos do pino A para o pino B, usando C como


auxiliar, necessrio primeiramente mover os n-1 discos do topo de A para
o pino C deixando caminho livre para que o disco na base de A (o ensimo
disco) possa ser movido para sua posio final em B. Da mesma forma, para
proporcionar o movimento dos n-1 discos, agora em C, para seu destino final

Linguagem de Programao I

em B, necessrio movimentar todos os n-2 no topo de C para A usando B


como auxiliar. O raciocnio prossegue recursivamente gerando pendncias de
movimentos e tendo como condio de parada a tentativa de movimentao
de zero discos.
O programa da Listagem 48 ilustra como implementar uma soluo
para o problema da Torre de Hani em Pascal. O procedimento hanoi tem
por objetivo listar a sequencia de movimentaes que devem ser feitas para
a resoluo do problema. Seu primeiro argumento corresponde a quantidade
de discos a serem movidos.
Os trs argumentos finais referem-se respectivamente aos rtulos dos
pinos origem, destino e auxiliar. Na Linha-05 est a condio de parada quando no h mais discos a movimentar. Na Linha-06 ocorre a primeira chamada
recursiva que movimenta os n-1 discos do topo de A para C usando B como
auxiliar (observe a sequencia dos pinos de entrada).
Quando estes so resolvidos (na verdade so criados apenas pendncias), feita a movimentao do disco na base do pino A para o pino B
na Linha-07 (neste caso a movimentao mecnica substituda por uma
mensagem de texto indicando os rtulos dos pinos de partida e chegada). Na
Linha-08 ocorre a segunda chamada recursiva que movimenta os n-1 discos
em C para B utilizando A como auxiliar (novamente os parmetros mudam).
No programa principal, Linha-12, o procedimento hanoi chamado para o
caso de trs discos rotulados por A, B e C. A sada do programa (veja
tambm Figura-5.1),
A > B | A > C | B > C | A > B | C > A | C > B | A > B |

Listagem 48
01

program torre_de_hanoi;

02
03

procedure hanoi(n: integer; A, B, C: char);

04

begin

05

if n = 0 then exit;

06

hanoi(n-1, A, C, B);

07

write(A, ' > ', B, ' | ');

08

hanoi(n-1, C, B, A);

09

end;

10
11

begin

12
13

hanoi(3, 'A', 'B', 'C');


end.

147

148

Ricardo Reis Pereira

5. Aninhamento Modular
Em Pascal possvel construir um mdulo (funo ou procedimento) dentro
do corpo de outro mdulo. Este recurso conhecido como aninhamento modular e os mdulos aninhados de mdulos internos. No exemplo,
procedure teste;
function soma(a,b: integer): integer;
begin
return a+b;
end;
begin
write( soma(3, 8) );
end;

a funo soma interna ao procedimento teste.


Um mdulo interno de propriedade exclusiva do mdulo que o contm
e dessa forma no pode ser chamado fora dele. Assim soma, no exemplo anterior, s pode ser chamado dentro do corpo da funo teste (como ilustrado)
ou de dentro de outras funes internas a teste (neste caso no h nenhuma).
Para ilustrar o aninhamento modular, consideremos o problema de
implementao da busca binria. Este algoritmo consiste na busca por uma
chave em uma array cujos valores esto ordenados. A seguir descrevemos o
algoritmo da busca binria. Seja L uma array ordenada onde se deseja determinar a posio de uma chave x (caso esteja contida) e uma subarray de L.
Seja M() a funo que determina o valor da clula mediana de , **
a subarray de formada pelas clulas anteriores a M() e ** a subarray de
formada pelas clulas de posteriores a M(). Cada etapa de uma busca
binria consiste em comparar M() com x. Caso os valores sejam iguais, significa que obteve sucesso e a posio procurada o ndice em L onde est
M(). Do contrrio, se M() for diferente de x, ento passa a ser ou *, caso
M() seja maior que x, ou **, caso M() seja menor que x, e o processo
repetido at que x seja encontrado ou tenha comprimento zero (busca sem
sucesso). Na primeira etapa da busca binria, tomada como sendo a
array L integral.

Linguagem de Programao I

Listagem 49
01

program busca_binaria;

02
03

function busca_bin(L: array of integer; x: integer): integer;

04

function rbusca(min, max: integer): integer;

05

var med: integer;

06

begin

07

rbusca := -1;

08

if max<min then exit;

09

med := (min + max) div 2;

10

if L[med] = x then

11

rbusca := med

12

else if L[med]>x then

13

rbusca := rbusca(min, med-1)

14

else

15

rbusca := rbusca(med+1, max);

16
17

end;
begin

18
19

busca_bin := rbusca( 0, length(L)-1 );


end;

20
21

const

22
23
24
25

M: array[0..11] of integer = (2,3,6,11,21,24,38,39,44,50,70,78);


var
x: integer;
begin

26

x := busca_bin(M, 11);

27

if x > 0 then

28
29

writeln(x)
else

30
31

writeln('nao encontrado');
end.

Na Listagem 49 a funo busca_bin implementa a busca binria em


Pascal. A array de busca e a chave procurada so recebidos respectivamente atravs dos argumentos L e x (Linha-03). Internamente busca_bin aninha
a funo recursiva rbusca que efetua a busca propriamente dita. Os argumentos de rbusca (min e max na Linha-04) representam respectivamente os
ndices em L (mdulos internos tem acesso a todos os recursos locais do

149

150

Ricardo Reis Pereira

mdulo que os aninha) e que limitam a subarray investigada (). Na Linha-07


supe-se que x no est em L (primeira hiptese) e por isso a varivel interna
rbusca recebe -1 (definimos que uma busca sem sucesso deve retornar um
valor de ndice negativo).
A Linha-08 contm a condio de parada da recurso causando retorno imediato quando o ndice inferior (min) extrapola o superior (max). Na
Linha-09, med utilizada para calcular a posio mediana da subarray investigada (). O processo de deciso entre as Linhas 10 e 15 verifica se a chave
foi encontrada (Linha-11), se a pesquisa continua em * (chamada recursiva
da Linha-13) ou em ** (chamada recursiva da Linha-15).
Nenhuma das duas chamadas recursivas mencionadas inclui o valor
em med e por essa razo utiliza-se med-1 na Linha-13 e med+1 na Linha-15.
Na Linha-18 busca_bin faz uso de rbusca passando os ndices apropriados de
L (array completa) como argumentos. O programa principal entre as Linhas 21
e 31 ilustra o uso de busca_bin utilizando como entrada a array constante M.
Esta array declarada com ndice inferior zero afim de o retorno de busca_bin
no necessitar de correo (lembre-se que o ndice inferior de L zero).

6. Unidades
A sada gerada pelo compilador quando recebe como entrada um arquivo
de cdigo de um programa um arquivo binrio executvel. Ele representa
o cdigo de mquina que pode ser executado diretamente em hardware e
ao mesmo tempo est atrelado a servies do sistema operacional sobre o
qual se procedeu a compilao. Se sesses de clusula uses esto presentes, ento o compilador acessar e anexar recursos de outros arquivos que
so binrios mas que no so executveis. Em Pascal estes arquivos so
denominados unidades e so tambm provenientes de outros processos de
compilao mas a estrutura bsica de implementao diferente.
A estrutura bsica para implementao de uma unidade Pascal a seguinte,
unit <nome_da_unidade>;
<recursos>
interface
<interfaces>
implementation
<implementaes>
end.

Linguagem de Programao I

As palavras reservadas unit, interface e implementation formam o corpo


estrutural de quaisquer unidades em Pascal. Unit deve ser seguido por um identificador que d nome a unidade e ao arquivo desta unidade (que ainda possui
uma extenso .pas). Se o nome do arquivo de unidade for diferente do nome de
unidade o compilador emitir um um erro de compilao.
Como acontece com programas, a identificao da unidade encerra em
ponto-e-vrgula. Interface e implementation abrem respectivamente as sesses
de interface e implementao da unidade. A sesso de implementao essencialmente um continer de mdulos (que podem ser funes ou procedimentos)
que desempenham tarefas relacionadas a uma determinada rea de aplicao
(como redes, computao grfica, aritmtica, matrizes, recursos de sistema, manipulao de arquivos, programao web e etc).
Entretanto nem tudo que fica nessa sesso deve ser acessado por usurios da unidade (imagine, por exemplo, uma funo que deva ser utilizada por outras funes da unidade mas nunca pelo usurio da unidade). Somente recursos
que so atalhados na sesso de interface so de fato acessveis por usurios da
unidade. Para atalhar, por exemplo, um mdulo basta copiar seu prottipo para a
sesso de interface. No exemplo,
unit teste;

interface

procedure ola;

implementation

procedure ola;
begin
write('OLA');
end;

procedure tchau;
begin
write('TCHAU');
end;

end.

151

152

Ricardo Reis Pereira

existem dois procedimentos implementados, mas apenas um deles est atalhado na sesso de interface. Dessa forma a compilao do programa,
program novo;
uses teste;
begin
ola;
tchau;
end;

reconhece o mdulo ola, mas emite erro de compilao ao encontrar tchau


alegando no existir o procedimento.
De forma geral, se uma constante, varivel, tipo ou mdulo definido
ou prototipado na sesso de interface, ele ser acessvel ao usurio, mas se
esta definio ocorrer na sesso de implementao, ser de uso exclusivo da
prpria unidade.
As unidades que acompanham o Free Pascal ficam num mesmo diretrio (por exemplo, no Linux utilizado para compilar os exemplos deste livro elas
esto em /usr/lib/fpc/2.4.0/units/). O arquivo fpc.cfg (a localizao depender
do sistema) contm, entre outras informaes relevantes ao compilador, os
endereos para as unidades instaladas e por essa razo a simples referncia
com uses suficiente para carregar apropriadamente unidades declaradas.
Entretanto, se as unidades estiverem no mesmo diretrio do arquivo fonte que
as solicita (com uses), elas so carregadas normalmente.
Cada nova unidade implementada em um projeto deve ser compilada
independentemente. Para compilar um arquivo de cdigo fonte de unidade,
em linha de comando, utiliza-se a mesma sintaxe de compilao de programas. Exemplo,
$ fpc teste.pas

A compilao de um arquivo fonte de unidade tem como sada dois arquivos com mesmo nome da entrada mas com extenses diferentes, em geral
.o e .ppu. O arquivo de extenso .o o arquivo objeto (que surge tambm na
compilao de programas) e representa uma ponte entre o arquivo de cdigo
fonte e o arquivo binrio final de extenso .ppu. Mesmo havendo no mesmo diretrio do projeto o arquivo de cdigo de unidade .pas, o arquivo binrio .ppu
que o compilador requer quando uma clusula uses precisa ser resolvida em
outra parte do projeto. Assim se o .pas de uma unidade modificado, ele precisa ser recompilado ou do contrrio o .ppu antigo ser utilizado. Em projetos
assistidos por uma IDE, normalmente uma compilao resolve os problemas
de recompilao de unidades que tiveram seus cdigos modificados.

Linguagem de Programao I

A Listagem 50 mostra a implementao da unidade ncomplex que permite representar e operar nmeros complexos (soma, subtrao, multiplicao e diviso). Na interface ficam a definio do tipo de dados complex, que
representa um nmero complexo (re representa a parte real e im a imaginria)
alm dos prottipos das operaes bsicas. Apenas a funo conj, Linha-39,
no possui interface.
Listagem 50

Ainda na Listagem 50, o procedimento init inicializa um nmero complexo, que recebe por referncia no primeiro argumento, com os valores
de seus dois ltimos argumentos. As funes soma, subt, mult e quoc retornam um novo complexo respectivamente igual a soma, subtrao, mul-

153

Quando uma raiz de


nmero negativo surge
na resoluo de um
problema baseado em
nmeros reais, diz-se que
o problema no possui
soluo real. Como
alternativa a matemtica
definiu a constante i = 1 e
chamou todos os nmeros
escritos com formato
a+bi, sendo a e b reais,
de nmeros complexos.
O valor de a chamado
de parte real e b de parte
imaginria. O nmero a-bi
dito conjugado de a+bi.
As operaes bsicas
de soma, subtrao,
multiplicao e diviso
so obtidas assim,

154

Ricardo Reis Pereira

tiplicao e diviso dos dois complexos que recebem como argumentos. A


funo conj, sem interface, retorna o conjugado do complexo que recebe
(o conjugado do complexo ). Ela utilizada em quoc para facilitar a implementao da diviso. Print imprime o complexo de entrada em notao
de parnteses.
Listagem 51
01

program teste_complexos; 07

print( soma(a,b) );

02

uses ncomplex;

08

print( subt(a,b) );

03

var a, b: complex;

09

print( mult(a,b) );

04

begin

10

05

init(a, 3, 2);

06

init(b, -2, 6);

11

print( quoc(a,b) );
end.

O programa da Listagem 51 ilustra o uso da unidade ncomplex imprimindo o resultado das quatro operaes bsicas implementadas para dois
complexos dados. A sada obtida ,
(1.0,8.0)
(5.0,-4.0)
(-18.0,14.0)
(0.2,-0.6)

Atividades de avaliao
1. Se uma array for passada por referncia a um mdulo, ele poder modific-lo. Utilizando este recurso implemente uma funo capaz receber e
ordenar uma array de comprimento qualquer.
2. Implemente uma verso de resoluo do problema da Torre de Hani utilizando quatro pinos (um origem, um destino e dois auxiliares) de forma
a diminuir, para uma mesma quantidade de discos dada, o nmero de
movimentaes.
3. Implementar uma verso no recursiva (iterativa) para a busca binria.
4. A sequncia de Fibonacci uma srie infinita de nmeros naturais cujos
dois primeiros termos so 1 e os demais so calculados pela soma dos
dois termos anteriores. Os seis primeiros termos da sequncia so ento
1, 1, 2, 3, 5 e 8. Criar duas verses de procedimentos, uma iterativa e
outra recursiva, que imprimam os n primeiros termos da sequncia de
Fibonacci, onde n um argumento de entrada.

Linguagem de Programao I

5. O algoritmo de Euclides para clculo do mximo divisor comum (mdc)


de dois nmeros naturais a e b possui os seguintes passos: (i) se b for
zero, ento pare pois o mdc(a, b) o prprio a, do contrrio, prossiga;
(ii) c recebe o resto da diviso de a por b; (iii) a recebe o valor de b e
b recebe o valor de c; (iv) volte ao passo i. Utilizando este algoritmo
implemente uma funo para o clculo do mdc de dois naturais recebidos como argumentos.
6. Construa uma verso recursiva para o algoritmo de Euclides descrito na
questo anterior.
7. O mnimo mltiplo comum (mmc) de dois inteiros, a e b, pode ser calcuab
lado por mmc (a,b)=
. No caso de uma lista de inteiros, o mmc
mdc (a,b)
recursivamente definido por F(L) = mmc( x, F(L*) ), onde F o mmc da
lista de inteiros L, x o primeiro valor de L e L* a sub-lista de L obtida
pela extrao de x. Escreva funo que receba uma lista de inteiros e
retorne o mmc entre seus valores.
8. Inverter uma array significa dispor seus elementos em ordem inversa.
Construa uma funo recursiva para essa tarefa.
9. Construa uma unidade que permita manipular fraes reduzidas. Uma
frao reduzida aquela cujos numerador e denominador so inteiros
primos entre si (o mdc entre eles um). Devem estar presentes mdulos para inicializar, somar, subtrair, multiplicar, dividir e imprimir fraes
reduzidas.
10. Use a unidade construda na questo anterior para obter o numerador
200

de

2k+k 1 .
k= 0

155

Captulo

61
Arquivos

1. Memria Secundria
Executar um programa significa processar sequencialmente suas instrues
de mquina. Este processo requer no apenas uma CPU de processamento
eficiente, mas tambm de memria onde possam ser armazenadas e buscadas rapidamente as instrues. a chamada memria principal. A performance desta memria justificada pela associao de duas caractersticas:
o acesso aleatrio e a volatilidade. O acesso aleatrio a capacidade que o
hardware possui de permitir que qualquer clula de memria seja acessada
num tempo constante e muito pequeno. A volatilidade refere-se a condio
de presena de corrente eltrica no dispositivo para que alguma informao
esteja presente.
Memria Secundria um termo utilizado para se referir a qualquer
dispositivo que almeje o armazenamento no voltil de informaes (estaro
registradas mesmo aps o desligamento do dispositivo). De forma geral, devido a diferena funcional, existe maior quantidade de memria secundria
em relao a primria (que tambm mais cara). A memria secundria
representada por dispositivos como discos rgidos, pendrivers e cartes de
memria (de cmeras digitais, celulares e etc).
O gerenciamento de memria principal e secundria pelo sistema operacional feita de forma distinta. A disposio dos programas em execuo
na memria principal no diretamente visvel ao usurio que apenas pode
obter informaes gerais como o total de memria utilizado. No caso da memria secundria toda informao visualizvel em forma de uma rvore de
diretrios e arquivos.
Um arquivo tecnicamente uma sequencia de bytes com nome prprio, tamanho definido e endereo exclusivo (veja Figura - 10). Um diretrio ou
pasta um continer de arquivos e tambm de outras pastas (por isso a hierarquia de dados em memria secundria anloga a uma rvore). A primeira

158

Ricardo Reis Pereira

Partio Lgica
possvel aos sistemas
operacionais atuais definir
que parte, por exemplo,
de um disco ser utilizada.
Na prtica, uma vez
estabelecido isso, todas
as operaes de leitura
e gravao de arquivos
ocorrero nessa parte. No
existe uma barreira fsica
de acesso ao restante do
disco e por essa razo dizse que o particionamento
lgico.

Para acessar informaes


num dispositivo de
armazenamento primrio
ou secundrio necessrio
inicialmente deslocarse at o endereo onde
fica o dado pretendido
e s ento efetuar a
leitura e/ou gravao.
Em alguns hardwares
esse deslocamento
instantneo, mas em
outros toma um tempo
considervel. Essa
disparidade ocorre devido
a presena de partes
mveis no segundo caso
(inrcia de dispositivo).
Assim os dispositivos do
primeiro caso esto haptos
ao acesso aleatrio, ou
seja, acesso a qualquer
parte do disco em qualquer
tempo enquanto os da
segunda categoria so
melhores aproveitados
no acesso sequencial, ou
seja, ao invs de saltar
entre dados distantes
mais interessante efetuar
acessos seguidos a clulas
sequenciais minimizando o
efeito do deslocamento.

pasta, aquela que contm todas as demais, chamada de raiz e o conjunto


de todas as pastas e seus respectivos arquivos, de sistema de arquivos. H
regras para montar um sistema de arquivos e elas mudam conforme o sistema
operacional e o dispositivo utilizados.
O mesmo dispositivo de memria secundria, como por exemplo discos
rgidos, pode inclusive possuir mais de um sistema de arquivo com mesmas
regras ou regras diferentes. Cada fatia lgica em memria secundria, que
mantm um sistema de arquivos, denominada de partio. Usualmente as regras de montagem de um sistema de arquivos so referenciadas simplesmente
como sistema de arquivos. Assim so exemplos de sistemas de arquivos o FAT
e o NTFS da Microsoft, o ext3, ext4 e reiserFS do Linux e o HPFS da IBM.
Discos rgidos representam a mais comum forma de memria secundria que permite o armazenamento macio de informao. Internamente eles
so formados por discos magnticos rgidos (da a origem do nome) fixos a
um eixo central que gira em uma alta velocidade sobre um mancal de preciso. Um brao mecnico, com liberdade angular de movimentao, mantm
diversas extenses com agulhas magnetizadas que interagem com a superfcie de cada uma das faces dos discos rgidos efetuando operaes de leitura
e gravao.
Essa parafernlia justifica a lentido das operaes em discos rgidos,
pelo menos quando comparadas quelas em memria principal (que devido
a volatilidade, dispensa partes mecnicas). Apesar disso ainda representam
a melhor opo para armazenamento macio no voltil no que diz respeito
a anlise custo versus quantidade de memria versus velocidade de acesso.
Tamanho do Arquivo

Memria
Arquivo
Endereo do incio do arquivo

H dispositivos de memria secundria de acesso aleatrio e de acesso sequencial. Nos dispositivos de acesso aleatrio, como os discos rgidos, o
tempo de acesso a blocos fundamentais de bytes ocorre num tempo aproximadamente constante definido pelo fabricante, mas que ir variar de modelo para
modelo. Nos dispositivos de acesso sequencial, como as fitas magnticas, o
tempo de acesso a blocos fundamentais de bytes muda consideravelmente.
Nestes dispositivos uma agulha magnetizada de leitura fica fixa enquanto dois rolos, compartilhando uma mesma fita magntica (como num cassete)
giram levando ou trazendo a fita conforme a posio que ela deva ficar sob a

Linguagem de Programao I

159

agulha. A restrio de acesso nativa de dispositivos de acesso sequencial os


tornam mais interessantes para operaes de gravao sequencial de grandes quantidades de dados como em backups (cpias de segurana).
Um sistema de manipulao de arquivos, em uma linguagem de programao, um conjunto de recursos que permite criar, modificar ou excluir
arquivos de um sistema de arquivos. Tais sistemas devem manter uma camada abstrata que permita ao programador tratar arquivos em diferentes tipos de
memria secundria com o mesmo conjunto de recursos de linguagem. Para
que isso seja possvel, um sistema de manipulao de arquivos no trabalha
diretamente em memria secundria.
Ao invs disso ele cria e manipula arquivos em memria principal. Cada
instncia em memria principal de um arquivo, chamada de fluxo ou stream,
ligada logicamente a uma instncia em memria secundria (arquivo propriamente dito) e ocasionalmente, ou foradamente, o contedo copiado
de uma para outra. Esse processo conhecido como descarregamento ou
flushing. Um arquivo que requer muitas operaes tem a opo de fazer poucos descarregamentos e assim tira proveito do que cada tipo de memria
melhor oferece. Eventualmente, enquanto se manipula um arquivo, se houver
queda de anergia por exemplo, o contedo em memria perdido e aquele no
arquivo corresponder ao proveniente do ltimo descarregamento
Pascal possui mais de um sistema de manipulao de arquivos. O mais
comumente abordado aquele mantido pela unidade system e que ser estudado neste captulo. A unidade sysutils possui um sistema de manipulao de
arquivos alternativo semelhante ao da linguagem C.

2. Fluxos
Em Pascal os arquivos so classificados em binrios e de texto. Um arquivo
binrio aquele gerado pela concatenao de dados provenientes diretamente da memria principal e sem processamento adicional (isso significa que o
arquivo contm uma imagem do que esteve em memria). Arquivos binrios
podem ser tipados e no tipados. Um arquivo binrio tipado aquele formado
pela concatenao de dados binrios de mesmo tipo e tamanho denominados
de registros de arquivo.
Um arquivo de dados no tipado concatena dados binrios no necessariamente de mesmo tipo ou tamanho. Um arquivo texto aquele constitudo
exclusivamente por caracteres visveis (da tabela ASCII) e comummente representam algum tipo de documentao. Eles requerem processamento adicional para serem gerados, ou seja, os dados em memria, que precisam ser
gravados num arquivo texto, precisam ser primeiramente transformados do

Salvar um documento,
uma imagem, uma
planinha, um desenho
e etc, utilizando uma
aplicao especializada,
constitui uma tarefa de
descarregamento forado
da memria principal para
a secundria.

160

Ricardo Reis Pereira

formato original para strings antes de poderem ser registrados.


Para lidar com arquivos em Pascal necessrio definir primeiramente um
fluxo (stream) para ele. Uma varivel que define um fluxo denominada manipulador. Para criar um manipulador de fluxo binrio no tipado usa-se a sintaxe,
var
<manipulador>: file;

onde a palavra reservada file significa arquivo. Exemplo,


var

F: file;

onde F define um fluxo para um arquivo binrio no tipado. Para definir um


fluxo de arquivo binrio tipado, usa-se a sintaxe,
var

F: file of <tipo_base>;

onde file of so palavras reversavas que significam arquivo de. O tipo base
define o tipo comum dos dados concatenados no arquivo. No exemplo,
var

F: file of integer;

F define um fluxo para um arquivo tipado constitudo pela concatenao


de nmeros inteiros.
Para definir um manipulador para um fluxo de texto usa-se a sintaxe,
Na maioria dos sistemas
um nome de arquivo
construdo pela sequncia
das pastas que se
sucedem hierarquicamente
desde a raiz at o nome
propriamente dito do
arquivo. No Linux, e
demais sistemas baseados
no Unix, estas pastas so
separadas pelo caractere
barra comum, /, como no
exemplo /temp/data/teste.
dat. No Windows a raiz
de cada partio recebe
uma letra e utiliza-se barra
invertida, \ para separar
as pastas. Um exemplo
equivalente ao anterior
c:\temp\data\teste.dat.

var

<manipulador>: text;

onde text uma palavra reservada que significa texto. No exemplo,


var

T: text;

T define um manipulador para um fluxo de arquivo texto.


Um fluxo, depois de definido, precisa ser vinculado a um arquivo (que
necessariamente no precisa existir ainda) em um dispositivo real (como um
disco). Esta vinculao realizada pelo comando assign cuja sintaxe ,
assign(<fluxo>, <nome_do_arquivo_no_dispositivo_real>);

O primeiro argumento uma referncia a um fluxo que deve ser vinculado a um arquivo cujo nome o segundo argumento. Um nome de arquivo em
geral segue as regras de endereamento de arquivos do sistema operacional
onde o programa compilado. Se o arquivo aberto ou criado na mesma pasta do binrio executvel, no necessrio detalhar o endereo com hierarquia
de pastas, como em,

Linguagem de Programao I

assign(F, teste.dat);

Neste exemplo o fluxo F se vincula a um arquivo de nome teste.dat


na mesma pasta do binrio executvel. Se existir uma subpasta na pasta do
binrio executvel, o programador poder usar a notao ponto para acessar
arquivos dentro dela. Exemplo,
assign(F, './data/teste.dat');

// Linux

000110010111101111001000000011100011011101010100

000110010111101111001000000011100011011101010100

000110010111101111001000000011100011011101010100

000110010111101111001000000011100011011101010100

Incio do Arquivo
(Posio zero)
Posio dois

Posio trs

Final do Arquivo

no Linux ou,
assign('.\data\teste.dat');

//Windows

em Windows. Em ambos casos a subpasta data deve existir dentro da pasta


que contm o binrio executvel. Do contrrio haver erro de acesso.

3. Modos de Acesso
Depois da vinculao, o passo seguinte definir o modo de acesso do arquivo. O modo de um arquivo define basicamente o suporte s operaes de
leitura (verificao dos dados que ele contm) e escrita (adio de novos dados ou modificao de dados j existentes). O modo de um arquivo tambm
define a sua chamada posio corrente que equivale a um ponto de entrada
de uma nova operao de leitura ou escrita no arquivo.
A posio corrente representada por uma medida em registros entre o
incio do arquivo e o ponto de operao. Assim, por exemplo, a posio zero
indica que zero registros precedem a posio corrente (incio do arquivo). Na
Figura-6.2 uma seta ilustra a posio corrente em quatro pontos distintos de
um mesmo arquivo cujos registros possuem um byte cada.
H trs modos de acesso de arquivos em Pascal,
Modo de Escrita
Modo de Leitura
Modo de Anexao

161

162

Ricardo Reis Pereira

No modo de escrita, para fluxos de texto, ser permitida apenas a gravao de dados. Para fluxos binrios ser possvel leitura e gravao. Neste
modo, se o arquivo ainda no existir, ele logicamente criado em memria
secundria. Se ele j existir ento seu contedo sumariamente apagado
antes das novas operaes de escrita. Assim o processamento inicia sempre
com um arquivo de tamanho zero (bytes). Para definir um arquivo em modo de
escrita usa-se o comando rewrite que recebe como argumento nico o fluxo
que deve configurar. Exemplo,
assign(F, teste.dat);
rewrite(F);
...

onde F um fluxo. Neste exemplo, se teste.dat no existe ainda, ele criado,


mas do contrrio, tem o contedo apagado.
No modo de leitura, o arquivo precisa existir para que possa ser aberto.
Neste modo, caso seja um arquivo de texto, os dados j existentes podero
ser lidos mas nunca modificados nem novos dados adicionados. Para arquivos binrios as operaes de leitura e gravao so permitidas. A posio
corrente de um arquivo aberto em modo de leitura zero (incio do arquivo).
Para abrir um arquivo em modo de leitura usa-se o comando reset cujo nico
argumento o fluxo que deve ser vinculado ao arquivo. No exemplo,
assign(F, teste.dat);
reset(F);
...

o arquivo teste.dat, que precisa existir, vinculado ao fluxo F e sua posio


corrente marcada no incio do arquivo.
No modo de anexao um arquivo j existente aberto para receber
novos dados. Se o arquivo ainda no existe um erro ocorrer. Se ele j existe,
seu contedo original mantido. Um arquivo aberto no modo de anexao
tem sua posio corrente apontada para o fim do arquivo afim de que as novas operaes agreguem novos dados e no sobrescrevam os que j existem. Somente fluxos para arquivos texto podem ser abertos neste modo. Para
abrir um arquivo texto em modo de anexao usa-se o comando append cujo
nico argumento o fluxo que ser vinculado ao arquivo. No exemplo,
assign(F, teste.txt);
append(F);
...

o fluxo de texto F vinculado ao arquivo teste.txt.

Linguagem de Programao I

Nem sempre possvel abrir um arquivo. Quando este for o caso ento um erro em tempo de execuo ocorrer e o programa ser suspenso.
Utilizando a diretiva {$I-}, antes do cdigo de abertura do arquivo, possvel
desligar a emisso explcita do erro e manter a execuo. O custo desta desabilitao a necessidade de checar manualmente se ocorreu silenciosamente um erro e impedir que ele cause outros erros mais adiante.
Essa checagem manual feita com a funo IOResult que retorna o
status da ltima operao executada pelo sistema de manipulao de arquivos. Se IOResult retornar zero, nenhum erro ter ocorrido. Do contrrio o valor
de retorno, que um inteiro, corresponder ao cdigo de um erro. A Tabela-6.1
lista os possveis cdigos de erros de sada de IOResult e seus respectivos
significados. Para religar a emisso de erros usa-se a diretiva {$I+}.

Tabela 1

A funo existe na Listagem 52 testa a existncia de um arquivo cujo


nome repassado como argumento (nome). A diretiva de desligamento na
Linha-04 impede que, no caso de no existncia do arquivo, um erro causado
por reset (Linha-06) suspenda o programa. Se nome for uma string no vazia
e IOResult retornar zero ento o arquivo existe. Estas condies so implementadas na expresso booleana da Linha-08 cujo valor atribudo a varivel
interna existe (retorno da funo).

163

164

Ricardo Reis Pereira

Listagem 52
01

function existe(nome: string): boolean;

02

var F : file;

03

begin

04

{$I-}

05

assign (F, nome);

06

reset (F);

07

{$I+}

08

existe := (IoResult = 0) and (nome <>


'');

09

close(F);

10

end;

Para fechar um fluxo aberto (e descarregar o ltimo contedo em memria principal) usa-se o comando close com sintaxe,
close(<fluxo>);

Para forar o descarregamento da memria principal para a secundria


antes mesmo do fechamento do arquivo, use o comando flush cuja sintaxe ,
flush(<fluxo>);

Para renomear um arquivo utiliza-se o comando rename. Ele requer


dois argumentos sendo o primeiro o nome do fluxo do arquivo que se deseja
renomear e o segundo uma string com o novo nome (as regras de nomes so
regidas pelo sistema operacional que o programador utiliza). Este comando
requer a vinculao de assign mas deve ser chamado sem que o arquivo seja
aberto (por reset, rewrite ou append). No exemplo,
var
F: file;
begin
assign(F, 'teste.dat');
rename(F, 'novo.dat');
end.

o arquivo teste.dat renomeado para novo.dat.


Para excluir um arquivo definitivamente utiliza-se o comando erase. Ele
possui como argumento nico o fluxo que se vincula ao arquivo que deve ser
eliminado da memria secundria. De forma anloga a rename, erase requer
a vinculao de assign mas deve ser chamado sem que o arquivo esteja aberto. No exemplo,

Linguagem de Programao I

var
F: file;
begin
assign(F, 'teste.dat');
remove(F);
end.

o arquivo teste.dat definitivamente excludo.

4. Utilizando Arquivos Binrios


Os comandos read e write, utilizados at agora para leitura via entrada padro e escrita para a sada padro, possuem verses para leitura e escrita em
arquivos. Adicionalmente eles recebem como primeiro argumento o fluxo de
onde sero lidos ou para onde sero escritos dados. Os demais argumentos
correspondem a uma lista de variveis ou constantes cujos contedos devero ser copiados, sem processamento adicional, para o arquivo vinculado ao
fluxo no primeiro argumento. Detalhes de formatao, como espaos, tabulaes, novas linhas ou controle de casas decimais no possuem funcionalidade no mbito dos arquivos binrios.
No exemplo,
write(F, x, y);

se F for um fluxo binrio ento o contedo das variveis x e y sero escritos


sequencialmente no arquivo vinculado a F. Similarmente em,
read(F, x, y);

dois dados consecutivos do arquivo vinculado ao fluxo F so lidos atravs das


variveis x e y.
As operaes de leitura de read e escrita de write ocorrem na posio
corrente do arquivo. Depois que a operao se encerra a posio corrente
tem sido deslocada do total de bytes processados. Assim, por exemplo, escrever continuamente dados para o final do arquivo mantm a posio corrente
sempre no final. No programa da Listagem 53 100 valores inteiros so gerados aleatoriamente e gravados num arquivo de fluxo F. As 100 chamadas a
write na Linha-10 copiam cada valor inteiro para o arquivo e ao mesmo tempo
deslocam a posio corrente para o novo fim de arquivo. Da na prxima iterao no haver sobreposio, mas sim concatenao do novo inteiro.

165

166

Ricardo Reis Pereira

Listagem 53
01 program arquivo_de_inteiros;
02 var
03

f: file of integer;

04

i: integer;

05 begin
06

assign(f, 'teste.dat');

07

rewrite(f);

08

randomize;

09

for i := 1 to 100 do

10

write(f, random(100));

11

close(f);

12 end.

Os comandos ramdomize
e random, unidade system,
so utilizados para gerar
nmeros pseudo aleatrios
em Pascal. ramdomize
um procedimento sem
argumentos que deve ser
chamado uma nica vez
antes de chamadas futuras
a random para possibilitar
o mximo de aleatoriedade
possvel. As chamadas
a random requerem um
ou nenhum argumento e
retornam nmeros pseudo
aleatrios. Quando no h
argumento o valor pseudo
aleatrio gerado real e
est entre 0.0 e 1.0. Se o
argumento existe, ele deve
ser um inteiro n e a sada
gerada um inteiro entre 0
e n-1.

Para verificar ou modificar manualmente a posio corrente de um arquivo, a unidade system dispe os comandos a seguir,
eof
filepos
seek

Abreviao de end of file (fim de arquivo). Recebe um fluxo como


argumento e retorna verdadeiro se a posio corrente atingiu o
final do arquivo vinculado. Do contrrio retorna falso.

Recebe um fluxo e retorna o valor da posio corrente (int64) do


arquivo vinculado.
Modifica a posio corrente do arquivo cujo fluxo passado como
primeiro argumento. A nova posio (int64) dada como segundo
argumento.

Para ler o contedo do arquivo gerado pelo programa da Listagem-6.2,


construiu-se o programa da Listagem 54. Neste novo programa reset, na
Linha-07, acessa o arquivo em disco e define a posio corrente para o incio
do arquivo. O lao while da Linha-08 utiliza eof para examinar sucessivamente
se a posio corrente de f j atingiu o fim do arquivo. As chamadas a read,
Linha-09, fazem tanto a varivel i assumir em cada iterao do lao cada um
dos inteiros armazenados no arquivo quanto avanar automaticamente a posio corrente. Cada valor de inteiro lido atravs de i impresso pelo lao em
sada padro (Linha-10).

Linguagem de Programao I

Listagem 54
01

program lendo_arquivo_de_inteiros;

08

while not eof(f) do begin

02

var

09

read(f, i);
write(i, ' ');

03

f: file of integer;

10

04

i: integer;

11

end;

12

close(f);

05

begin

06

assign(f, 'teste.dat');

07

reset(f);

13 end.

Se duas variveis inteiras, a e b, tomarem o lugar de i no programa da


Listagem-6.3, o lao principal poder ser equivalentemente escrito assim,
while not eof(f) do begin
read(f, a, b);
write(a, ' ', b, ' ');
end;

o que demonstra a flexibilidade, no contexto dos arquivos, do comando read.


Para mudar manualmente a posio corrente em um arquivo binrio
utiliza-se o comando seek. O primeiro argumento o fluxo vinculado ao arquivo e o segundo argumento o valor da nova posio corrente. Em Pascal,
ao invs de bytes, a posio corrente medida em nmero de registros. Um
registro um bloco cuja memria igual a do tipo base em arquivos tipados
e 128-bytes em arquivos no tipados. Seek no funciona com arquivos de
texto. Zero o valor da posio inicial de um arquivo ao passo que o n-simo
registro possui posio n-1.
O total de registros de um arquivo retornado pelo comando filesize
cujo nico argumento o fluxo vinculado ao arquivo que se deseja saber o
nmero de registros. Por exemplo, para apontar para o octogsimo inteiro do
arquivo gerado pelo programa da Listagem-6.2, usa-se,
seek(f, 79);

Quando a posio corrente de um arquivo binrio no est no fim do arquivo ento uma operao de escrita causa uma sobreposio como ilustrado
na Figura 11. Por exemplo, para substituir o quadragsimo inteiro do arquivo
gerado pelo programa da Listagem 53 usa-se,
seek(F, 39);
write(F, 123);

Esta operao ir gravar o valor 123 sobre aquele que est na quadragsima posio do arquivo com fluxo F. O tamanho do arquivo no modificado e a posio corrente final a quadragsima primeira.

167

168

Ricardo Reis Pereira

Posio corrente 2
Escreveu trs bytes (sobreposio)
Posio corrente agora 5

Figura 11
Listagem 55
01

procedure inserir(fnome: string; pos, x: integer);

02

var F: file of integer;

03
04

tmp, a: integer;
begin

05

assign(F, fnome);

06

reset(F);

07

seek(F, pos);

08

read(F, tmp);

09

seek(F, pos);

10

write(F, x);

11

while not eof(F) do begin

12

read(F, a);

13

seek(F, filepos(F)-1);

14

write(F, tmp);

15

tmp := a;

16

end;

17

write(F, tmp);

18

close(F);

19

end;

Caso seja necessrio inserir dados no meio do arquivo ento o comportamento padro de sobreposio no ser desejvel. Uma forma de resolver o
problema proposta pela funo na Listagem 55. Os argumentos de entrada
so o nome do arquivo, lido pela string fnome, o valor da posio onde deve
haver a insero, lido pelo inteiro pos e o item de insero lido pelo inteiro x
(supe-se um arquivo binrio de inteiros). O primeiro passo abrir o arquivo
em modo de leitura (Linhas 05 e 06) e Ir para a posio onde deve ocorrer a
insero do novo registro (Linha-07).
Em seguida faz-se uma cpia do registro nesta posio em tmp
(Linha-08) e retorna-se a posio de insero (a leitura causou avano da

Linguagem de Programao I

posio corrente e por essa razo necessrio regredir manualmente com


seek, conforme Linha-09). A insero acontece em seguida por sobreposio
(Linha-10). O item sobreposto no foi perdido porque possui cpia em tmp.
No lao entre as Linhas 11 e 16 a varivel a recebe uma copia do registro na posio corrente (Linha-12) e em seguida regride a essa posio
(Linha-13) para gravar o ltimo valor em tmp (Linha-14). Com o valor de a
atribudo a tmp (Linha-15) fecha-se um ciclo de permutaes de dados que
provocam o deslocamento em uma posio para a frente de todos os registros
que sucedem a posio de insero.
Quando o lao se encerra, o valor em tmp o do antigo ltimo registro
do arquivo. Sua concatenao ao arquivo (Linha-17) conclui a transposio
de dados e promove o aumento real do arquivo. Veja Figura 12.
Posio de Insero

tmp

tmp

tmp
tmp

Figura 12

A remoo de dados em arquivos binrios realizada por operaes de


truncagem. Uma truncagem corresponde a eliminao de todo contedo do
arquivo a partir da posio corrente. Para efetuar uma truncagem em Pascal
usa-se o comando truncate repassando como nico argumento o fluxo vinculado ao arquivo que se deseja truncar. Por exemplo para eliminar os trs ltimos
inteiros de um arquivo binrio de inteiros chamado teste.dat, implementa-se,
assign(F, teste.dat);
reset(F);
seek(F, filesize(F) - 3);
truncate(F);
close(F);

Observe que a expresso filesize(F)-3 calcula a posio no arquivo vinculado a F do terceiro inteiro contado de trs para frente. A chamada seguinte
truncate elimina os trs inteiros reduzindo o arquivo.
A eliminao de registros internos a um arquivo binrio requer que eles
primeiramente sejam movidos para o final do arquivo antes da truncagem
(veja esquema na Figura 13). Para movimentar um registro indesejado para o

169

170

Ricardo Reis Pereira

final do arquivo deve-se efetuar sucessivas trocas entre ele e o registro logo
esquerda. Isso deslocar tal registro em direo ao final do arquivo ao mesmo tempo que trar em uma posio para trs todos os demais registros que
inicialmente se encontravam a sua frente. Na Figura 14 o registro indesejado
possui valor 9. Aps seis trocas ele atinge a ltima posio, onde eliminado.
Movimentao de dados
para o fim do arquivo

Truncamento

Figura 13

2 7 9 1 3 6 4 7 1
2 7 1 9 3 6 4 7 1
2 7 1 3 9 6 4 7 1
2 7 1 3 6 9 4 7 1
2 7 1 3 6 4 9 7 1
2 7 1 3 6 4 7 9 1
2 7 1 3 6 4 7 1 9
2 7 1 3 6 4 7 1
Figura 14
Listagem 56
01 procedure remover(fnome: string; pos: integer);

09

read(F, a, b);

02 var F: file of integer;

10

seek(F, filepos(F)-2);

03

11

write(F, b, a);

04 begin

12

seek(F, filepos(F)-1);

05

assign(F, fnome);

13

end;

06

reset(F);

14

truncate(F);

07

seek(F, pos);

15

close(F);

08

while filepos(F) < filesize(F)-1 do begin

16

a, b: integer;

end;

Linguagem de Programao I

O procedimento da Listagem 56 implementa a movimentao com remoo de um registro interno a um arquivo binrio de inteiros. Os argumentos de
entrada so o nome do arquivo (fnome) e a posio onde se localiza o registro
indesejado (pos). Primeiramente o arquivo vinculado ao fluxo F e a posio
corrente mudada para a do registro indesejado (Linhas 05, 06 e 07). O lao entre as Linhas 08 e 13 efetua as trocas dos registros vizinhos.
Para tanto so lidos de cada vez dois registros usando as variveis a e
b (Linha-09). Em seguida regride-se duas posies para trs (Linha-10) e, por
sobreposio, grava-se b e a nesta ordem (Linha-11) (troca propriamente dita).
Para que na iterao seguinte a nova troca possa ocorrer corretamente, deve-se regredir uma posio para trs (Linha-12).
O teste de continuao do lao na Linha-08 verifica se a posio corrente
do arquivo atingiu a penltima posio haja vista que so lidos dois registros
de cada vez. O uso de eof neste caso causaria uma tentativa de leitura alm
do fim do arquivo. Quando o lao se encerra a posio corrente ter atingido o
ltimo registro que por sua vez possuir o valor indesejado. O truncamento na
Linha-14 elimina o ltimo registro do arquivo.
Todas as operaes descritas nessa sesso se estendem a quaisquer
tipos base que definam um fluxo. No seguinte exemplo,
type
aluno = record
nome: string[25];
idade: byte;
media_final: real;
end;
var
G: file of aluno;

F define um fluxo para um arquivo binrio cujos registros so de um tipo


estrutura heterognea. Cada registro utiliza 30-bytes (25 + 1 + 4) de forma
que o avano, ou recuo, da posio corrente ocorre em mltiplos desse valor,
ou seja, a posio 0 est a zero bytes do incio do arquivo, a posio um a
30-bytes, a posio dois a 60-bytes e assim por diante. No exemplo,
x.nome := Raul;
x.idade := 30;
x.media_final := 9.5;
write(G, x);

171

172

Ricardo Reis Pereira

a varivel x, de tipo aluno, inicializada e seu novo contedo gravado no


arquivo binrio de fluxo G. Se o mesmo arquivo for aberto para leitura, estas
informaes podero ser resgatadas usando-se,
read(F, x);
writeln('Nome: ', x.nome,
', idade: ', x.idade,
', Media final: ', x.media_final:0:1);

5. Utilizando Arquivos de Texto


Assim como acontece com a sada padro, a escrita de dados em um arquivo texto efetua em bastidores uma converso de dados para o formato texto
(string) antes da impresso propriamente dita. A gravao feita pelos comandos write/writeln cujo primeiro argumento deve ser um fluxo de arquivo de
texto. Os demais argumentos, independente de seus formatos, so um a um
convertidos em strings formatadas para por fim serem gravadas no arquivo. A
notao com dois-pontos (:), vista rapidamente no Captulo-1, estendida aqui
para permitir essa formatao.
Para formatar um valor inteiro em write/writeln usa-se a notao i:n
onde i define o inteiro e n o nmero de caracteres que a verso em texto do
nmero i deve ter. Se n for maior que o nmero de caracteres mnimo para
representar i ento ocorrer preenchimento com caracteres em branco
esquerda. Na chamada,
x := 5;
writeln(|, x:4, |);

onde x inteiro, imprime em sada padro,


| 5|

Para formatar um valor real em write/writeln usa-se a notao r:m:d onde


r define um valor real, m o total de caracteres que a string final deve ter e d o
nmero de casas decimais que devem ser consideradas. Se m for maior que
o mnimo de caracteres para representar o real ento ocorrer preenchimento
esquerda com caracteres em branco. No exemplo,
x := 3.14159;
writeln(|, x:5:2, |);

onde x real, imprime,


| 3.14|

Linguagem de Programao I

Observe que o ponto (.) tambm entra na contagem do total de caracteres da string e por essa razo entre | e 3 existe apenas um caractere
em branco.
Para formatar uma string em write/writeln usa-se a notao s:n onde s
define uma string e n o total de caracteres que a string final deve possuir. Se
o valor em n for maior que o comprimento de s, haver preenchimento com
caracteres em branco esquerda. No exemplo,
x := carro;
writeln(|, x:10, |);

onde x uma string, imprime,


| carro|

Para ilustrar o uso da notao com dois-pontos em arquivos de texto,


consideremos o exemplo seguinte,
program alo_mundo;
var
F: text;
x: integer;
q: real;
begin
assign(F, 'saida.txt');
rewrite(F);
x := 123;
q := 34.0/125;
writeln(F, x:5, q:12:5, 'Ola mundo!!':20);
close(F);
end.
123

Este programa gera um arquivo de texto chamado saida.txt cujo contedo ,


0.27200

Ola mundo!!

writeln insere adicionalmente um caractere de nova linha. Assim uma anexao futura (uso de append) ocorrer na linha seguinte do arquivo. Por exemplo
a execuo de,
assign(F, 'saida.txt');
append(F);
writeln(F, x:5, q:12:5, 'Ola mundo!!':20);
close(F);

173

174

Ricardo Reis Pereira

Adiciona texto saida.txt cujo contedo final fica,


123

0.27200

Ola mundo!!

123

0.27200

Ola mundo!!

Ao contrrio de um arquivo binrio, saida.txt pode ser visualizado em


um editor de texto (como o notepad, word no Windows ou pico, gedit, kedit
em Linux).
Listagem 57
01

program Alunos;

02
03

procedure inserir(fnome, nome: string; idade: byte; media: real);

04
05

var F: text;

06

begin

07

{$I-}

08

assign(F, fnome);

09

reset(F);

10

{$I+}

11

if ioResult=0 then

12

append(F)

13

else

14

rewrite(F);

15
16

writeln(F, nome:25, idade:3, media:5:1);


end;

17
18

var s: string;

19

i: byte;

20

m: real;

21

ch: char;

22

begin

23

repeat

24

write('Nome> ');

25

write('Idade> '); readln(i);

26

write('Media> '); readln(m);

27

inserir('aluno.txt', s, i, m);

28

writeln('continuar S/N?');

29

readln(ch);

30
31

readln(s);

until (ch='n') or (ch='N');


end.

Linguagem de Programao I

O programa da Listagem 57 ilustra a insero de dados num arquivo texto chamado aluno.txt. Cada linha do arquivo deve conter sequencialmente o nome de aluno, sua idade e sua mdia final. A insero dos
dados de um novo aluno feita pelo procedimento inserir que recebe
como argumentos o nome do arquivo base de insero (argumento fnome), o nome do aluno (argumento nome), a idade (argumento idade) e a
mdia final (argumento media).
Na primeira parte do procedimento testada a existncia do arquivo base (Linhas 06 a 09). Caso ele exista, aberto em modo de
anexao (Linha-11) seno ele criado (Linha-13). A insero de dados propriamente dita ocorre na Linha-14 e o fechamento do arquivo na
Linha-15.
O programa principal mantm um lao entre as Linhas 23 e 30
que requisita constantemente por dados de novos alunos e os insere em
aluno.txt (Linha-27). Cada chamada repassa o nome deste arquivo e os
dados do novo aluno, abre o arquivo, grava e por fim o fecha.
No final de cada insero o usurio tem a opo de parar ou continuar dependendo do valor que fornecer a ch (Linhas 29 e 30). Um aspecto de aluno.txt aps algumas inseres listado a seguir,
joao da silva 25

9.5

maria joana da silva 23

8.0

antonio manuel alves 31

9.0

isabel moura brasil 23

7.0

emanuel lucas sousa 30

8.7

arthur brandao lima 22

5.6

alfedro pacheco 29

7.8

A leitura de um arquivo de texto em Pascal realizada linha a linha


usando-se o comando readln com dois argumentos sendo o primeiro o fluxo
vinculado ao arquivo que se deseja ler e o segundo uma string (com tamanho
suficiente para caber a linha de maior comprimento). O final de um arquivo
texto deve ser testado pelo comando seekeof similar a eof em arquivos binrios (a sintaxe equivalente). No exemplo,

175

176

Ricardo Reis Pereira

var F: text;
linha: string;
begin
{$I-}
assign(F, 'aluno.txt');
reset(F);
{$I+}
if ioResult=0 then
while not seekeof(F) do begin
readln(F, linha);
writeln(linha);
end;
close(F);
end;

o arquivo aluno.txt lido linha a linha atravs da varivel linha e impresso na


sada padro.
Arquivos de texto gerados pela transformao de dados numricos
em strings no podem ser diretamente lidos como contineres de nmeros. Para trazer dados de volta a formatos como real ou integer o programador precisar usar o comando val (veja Captulo-2) em cada string
numrica gravada.
Um arquivo de texto pode ser lido como uma sequncia de caracteres.
Operacionalmente como lidar com um arquivo binrio cujos registros so
caracteres. O reconhecimento de final de linha nesta nova abordagem feita
pelo comando seekeofln que identifica o caractere especial de nova linha. O
lao,
while not seekeoln(F) do begin
read(F, ch);
write(ch);
end;

onde ch uma varivel de tipo char, imprime em sada padro o contedo da


primeira linha de um arquivo de texto ao qual o fluxo F est vinculado.

Linguagem de Programao I

Sntese da Parte 3
No Captulo 1 foi estudada a modularizao que incluiu noes sobre controle de execuo em um processo monothread, aspectos sobre a passagem de argumentos em procedimentos e funes, noes
sobre uso e aplicaes da recursividade, a importncia do aninhamento modular e por fim a compilao de mdulos afins numa unidade Pascal. No Captulo 2 foi estudado o sistema padro de manipulao de arquivos da Linguagem Pascal incluindo a noo de
fluxo de informaes entre memria principal e secundria. Os principais comandos desde sistema foram apresentados convenientemente em suas respectivas categorias (dos arquivos binrio e de texto)
e adicionalmente exemplificados para melhor fixar suas funcionalidades.

Atividades de avaliao
1. Construir programa que gere um arquivo binrio contendo 1000 inteiros
aleatrios entre 200 e 5000.
2. Construir programa que crie um arquivo contendo apenas inteiros pares
oriundos de um arquivo gerado pelo programa da questo anterior.
3. Construir programa que crie uma cpia de um arquivo dado, mas com
nome distinto.
4. Construir programa que leia um arquivo gerado pelo programa do problema-1 e inverta sua sequencia original de inteiros.
5. Uma estrutura heterognea chamado ponto mantm dois campos, x e y,
que representam uma coordenada no plano. Utilizando este tipo de dados, construir programa que crie um arquivo binrio contendo 200 pontos
da funo f(x) = 5x3 - 7x com x no intervalo [5, 50]. Escolha valores de x
equidistantes.
6. Construir programa que leia o arquivo gerado na questo anterior e crie
uma verso texto dele.
7. O procedimento da Listagem-6.5 ilustra como movimentar um registro para o fim do arquivo e depois elimin-lo por truncamento.
Reconstruir o procedimento de forma que seja possvel movimentar

177

178

Ricardo Reis Pereira

mais de um registro para o final do arquivo para elimin-los com uma


nica truncagem.
8. Utilizando o programa da Listagem 57 como base, construir um programa
que fornea ao usurio as possibilidades de cadastro de novo aluno e de
visualizao da listagem, em sada padro, de alunos cadastrados.
9. Inserir no programa do problema 8 a capacidade de busca por nome, ou
seja, o usurio fornece um fragmento de nome de aluno e o programa
lista as linhas que contm aquele fragmento.
10. Inserir no programa do problema 8 a possibilidade de remover um registro (remover um aluno).

Referncias
CANNEYT , Michal Van, Reference guide for Free Pascal, Document
version 2.4 , March 2010
http://www.freepascal.org/docs-html/

Linguagem de Programao I

Sobre o autor
Ricardo Reis Pereira: Possui graduao em Engenharia Mecnica pela
Universidade Federal do Cear (2000) e mestrado em Programa de Mestrado
em Enganha ria Qumica pela Universidade Federal do Cear (2004).
Atualmente professor assistente do curso Sistemas de Informao do
Campus de Quixad da Universidade Federal do Cear. Ministra as disciplinas de fundamentos de programao, clculo diferencial e integral, estruturas
de dados e computao grfica e atua nas reas de algoritmos, computao
grfica e mais recentemente em viso computacional.

179