Você está na página 1de 181

Computao

Linguagem de Programao I
iel a sua misso de interiorizar o ensino superior no estado Cear, a UECE,
como uma instituio que participa do Sistema Universidade Aberta do

Computao
Brasil, vem ampliando a oferta de cursos de graduao e ps-graduao
na modalidade de educao a distncia, e gerando experincias e possibili-
dades inovadoras com uso das novas plataformas tecnolgicas decorren-
tes da popularizao da internet, funcionamento do cinturo digital e
massificao dos computadores pessoais.

Linguagem de Programao I
Comprometida com a formao de professores em todos os nveis e
a qualificao dos servidores pblicos para bem servir ao Estado,
os cursos da UAB/UECE atendem aos padres de qualidade
estabelecidos pelos normativos legais do Governo Fede-
ral e se articulam com as demandas de desenvolvi-
mento das regies do Cear.

Ricardo Reis Pereira

Universidade Estadual do Cear - Universidade Aberta do Brasil


Geografia

12

Histria

Educao
Fsica

Cincias Artes
Qumica Biolgicas Plsticas Computao Fsica Matemtica Pedagogia
Informtica
Linguagem de Programao I

Ricardo Reis Pereira

Geografia

12

3 edio
a 3

Fortaleza
2015 Histria

Educao
Fsica

Cincias
Cincias Artes
Artes
Qumica
Qumica Biolgicas
Biolgicas Plsticas Computao
Plsticas Informtica Fsica
Fsica Matemtica
Matemtica Pedagogia
Pedagogia
Copyright 2015. 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.
Editora Filiada

Presidenta da Repblica Conselho Editorial


Dilma Vana Rousseff
Antnio Luciano Pontes
Ministro da Educao
Renato Janine Ribeiro Eduardo Diatahy Bezerra de Menezes
Presidente da CAPES Emanuel ngelo da Rocha Fragoso
Carlos Afonso Nobre Francisco Horcio da Silva Frota
Diretor de Educao a Distncia da CAPES Francisco Josnio Camelo Parente
Jean Marc Georges Mutzig
Gisafran Nazareno Mota Juc
Governador do Estado do Cear
Camilo Sobreira de Santana Jos Ferreira Nunes
Reitor da Universidade Estadual do Cear Liduina Farias Almeida da Costa
Jos Jackson Coelho Sampaio
Lucili Grangeiro Cortez
Vice-Reitor
Hidelbrando dos Santos Soares Luiz Cruz Lima
Pr-Reitora de Graduao Manfredo Ramos
Marclia Chagas Barreto Marcelo Gurgel Carlos da Silva
Coordenador da SATE e UAB/UECE Marcony Silva Cunha
Francisco Fbio Castelo Branco
Maria do Socorro Ferreira Osterne
Coordenadora Adjunta UAB/UECE
Elosa Maia Vidal Maria Salete Bessa Jorge
Diretor do CCT/UECE Silvia Maria Nbrega-Therrien
Luciano Moura Cavalcante
Coordenador da Licenciatura em Informtica Conselho Consultivo
Francisco Assis Amaral Bastos Antnio Torres Montenegro (UFPE)
Coordenadora de Tutoria e Docncia em Informtica Eliane P. Zamith Brito (FGV)
Maria Wilda Fernandes
Homero Santiago (USP)
Editor da EdUECE
Erasmo Miessa Ruiz Ieda Maria Alves (USP)
Coordenadora Editorial Manuel Domingos Neto (UFF)
Rocylnia Isidio de Oliveira Maria do Socorro Silva Arago (UFC)
Projeto Grfico e Capa
Maria Lrida Callou de Arajo e Mendona (UNIFOR)
Roberto Santos
Diagramador Pierre Salama (Universidade de Paris VIII)
Francisco Jos da Silva Saraiva Romeu Gomes (FIOCRUZ)
Tlio Batista Franco (UFF)

Editora da Universidade Estadual do Cear EdUECE


Av. Dr. Silas Munguba, 1700 Campus do Itaperi Reitoria Fortaleza Cear
CEP: 60714-903 Fone: (85) 3101-9893
Internet: www.uece.br E-mail: eduece@uece.br
Secretaria de Apoio s Tecnologias Educacionais
Fone: (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! Trata-
se 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 traba-
lha 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 pro-
gramador 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 conhe-
cimentos 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 arti-
fcios 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 per-
mitir que o leitor programe o mais prematu- ramente possvel de forma prtica,
desafiadora e estimulante.
O autor
Parte 1
Introduo Programao de
Computadores
Captulo 1
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 implementa-
o 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 estu-
dante 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 funcio-
namento 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. Sistema Operacional:
O software passou a representar a alma de um computador e sua inoculao O sistema operacional
nos circuitos dos equipamentos passou a ser referenciada como instalao um conjunto de
softwares que trabalham
de software. cooperativamente para
Softwares so instalados em camadas, ou seja, um software, para proporcionar ao usurio
funcionar, utiliza outros softwares. A exceo naturalmente a camada de acesso a recursos
do computador. Ele
software instalada diretamente sobre o hardware: o sistema operacional. As esconde detalhes,
demais camadas se instalam sobre este ou sobre uma ou mais camadas exis- muitas vezes complexos,
tentes. considerado um programa um software de aplicao especfica. H de funcionamento do
programas para edio de imagens, reproduo de arquivos de som, navega- hardware atravs de
abstraes simples.
o na internet, edio de texto e etc. Exemplos so Linux,
Um programa um arquivo que contm uma listagem de instrues de Windows, OS2, Unix e etc
mquina. Estas instrues devem ser executadas por uma CPU na ordem
que se apresentam no arquivo. Este processo denominado execuo do
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 exe-
cuo 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 ins-
trues 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 com-
putadores) naturalmente aquela utilizada para projetar e construir programas.
Quanto mais elaborada for uma linguagem, no sentido de propiciar melhor com-
preenso 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 prin-
cipal origem a produtividade de software pelas pessoas. Para os computado-
res, entretanto, a melhor e mais compreensvel forma ainda a em cdigo de
mquina. Na prtica um programa, escrito numa dada linguagem de progra-
mao, precisa primeiramente ser traduzido em linguagem de mquina para
que enfim possa ser executado. Essa traduo pode ser abordada generica-
mente de duas formas.
Na primeira forma um cdigo em alto nvel completamente converti-
do 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 ar-
quivo em cdigo de mquina (executvel) gerado como sada. O arquivo exe-
cutvel 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 m-
quina. 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
11
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 de-
pendncia direta com o hardware e o sistema operacional sobre o qual foi cria-
do. 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 compila-
dores C1 e C2, ambos da mesma linguagem X, para os respectivos sistemas.
Similar ao que acontece com compiladores, tradutores tambm reque-
rem uma verso por sistema operacional. Entretanto, como no existe com-
pilao 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 mui-
tas contribuies que convergiram para a criao de diversos compiladores
importantes. Atualmente possvel encontrar na Internet mais de 300 com-
piladores 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 co-
nectavam 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.
12
RICARDO REIS PEREIRA

O Turbo Pascal e o Delphi Pascal constituem a base de desenvolvi-


mento do compilador Free Pascal abordado neste livro e recomendado aos
leitores (veja www.freePascal.org). Trata-se de um compilador livre, de cres-
cente popularidade e que reconhece cdigos em Pascal puramente estrutu-
Arquitetura do
Processador:
rado (como acontecia no Turbo Pascal), cdigos em Object Pascal (como
Define o leiaute e acontece com o Delphi) ou associao de cdigo (parte estruturada e parte
a capacidade de orientada a objetos)
armazenamento ou
processamento dos
Abordaremos neste livro apenas os elementos estruturados do Free
componentes de uma Pascal (que incluem os fundamentos da linguagem, variveis e constantes,
unidade central de operadores, expresses, controle de fluxo, strings e arrays, tipos de dados
processamento (CPU). personalizados, ponteiros, modularizao e arquivos) que permitiro ao leitor
As arquiteturas mais
populares hoje em dia
posterior extenso ao Object Pascal (que inclui ainda uso de classes e obje-
possuem de um a dois tos, uso de interfaces, programao genrica, sobrecarga de operadores e
ncleos (em ingls, manipulao de excees).
single core e dual core) e
tamanhos de registradores
(memria interna da CPU) 3. Utilizando um Compilador Pascal
de 32 ou 64 bits.
O primeiro passo para se iniciar em programao naturalmente instalar o
Janela de Terminal: compilador (ou o interpretador se for o caso). Para baixar o compilador Free
Uma janela de terminal
a forma mais primitiva que Pascal visite www.freePascal.org/download.var. O site dispe vrias verses
um sistema operacional do compilador listados por arquitetura do processador e por sistema opera-
oferece ao usurio cional. Na sesso binaries (binrios) ficam os instaladores propriamente ditos.
para requisies de Na sesso sources (fontes) o cdigo fonte do compilador (voltado para quem
tarefas. Todas as aes
so repassadas como deseja contribuir com melhorias no Free Pascal). Por fim a sesso documen-
instrues escritas tation (documentao) permite baixar a documentao oficial completa do
denominadas de linhas de compilador em vrios formatos (PDF, HTML, PS, DVI e TXT).
comandos. Para indicar
que novas instrues
Para testar se o compilador instalado est devidamente configurado,
podem ser digitadas, abra um terminal (no Windows isso pode ser feito indo em Iniciar|Executar,
um terminal dispe um digite cmd, depois OK. Em sistemas Unix e relacionados, como Linux, caso o
indicador de entrada sistema j no esteja em modo terminal, h diversos aplicativos de simulao
denominado prompt
seguido de um cursor de terminal em modo X). Quando o prompt do terminal estiver visvel simples-
piscante. Para confirmar mente digite,
entradas o usurio fpc
pressiona ENTER aps
cada linha de comandos e Se o compilador estiver devidamente instalado ser impressa uma lis-
aguarda o processamento tagem das opes bsicas de uso. A seguir mostramos um fragmento que
que normalmente se antecede a listagem propriamente dita e que trs informaes do compilador.
encerra com a reexibio
do prompt aguardando Free Pascal Compiler version 2.2.4-3 [2009/06/04] for i386
novas instrues. Copyright (c) 1993-2008 by Florian Klaempfl

/usr/lib/fpc/2.2.4/ppc386 [options] <inputfile> [options]


13
Linguagem de Programao I

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


(terminal), utilizando o Free Pascal, deve-se primeiramente mudar para a pas-
ta 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 ar-
quivo objeto e representa o programa sem ligaes com o sistema operacio-
nal. 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 pen-
dencias 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:
Um compilador no
./teste pode corrigir os erros
que lista porque, em sua
Quando erros esto presentes no cdigo-fonte o compilador reportar abrangente viso, h
muitas possibilidades de
uma lista de todos eles (neste caso, no prprio terminal) indicando a linha onde
correo de um mesmo
cada um ocorre. Alguns erros so facilmente corrigveis como erros de sintaxe erro. Para ajudar ento no
(algo foi escrito erroneamente). J outros requerem uma anlise mais apurada trabalho do programador
do programador para serem corretamente diagnosticados e corrigidos. o compilador gera o
mximo de documentao
Alm de erros, um compilador pode gerar tambm advertncias. Uma de erro que permite mais
advertncia (Warning) um alerta que o compilador envia para indicar que facilmente a soluo do
algum recurso no est sendo apropriadamente utilizado. Erros impedem que problema. O processo de
resoluo de erros num
o compilador crie o executvel do programa ao contrrio das advertncias.
programa conhecido
Um programa compilado que gera somente advertncias produz um binrio. como depurao (em
Na prtica os efeitos de uma advertncia para o programa que ser executa- ingls, debug).
do pode ser imperceptvel em alguns casos e prejudicial em outros. Consulte
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 desen-
volvimento integrado) um programa utilizado para melhorar a produtividade
de software. Eles constituem em geral de um editor de cdigo-fonte com desta-
camentos 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 desen-
volvimento 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 se-
melhante 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 dis-
so 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.
15
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


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 ocorre-
rem 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 construti-
vos 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 pro-
gramas 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 repre-
sentam 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 com-
pleta dessas palavras, apresentamos na Tabela-1.1 as palavras reservadas
17
Linguagem de Programao I

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
Regras de Escopo:
da linguagem. So regras que definem
Para escrever um identificador em Pascal deve-se seguir as premissas: restries de acessos
entre partes distintas de
O primeiro caractere (obrigatrio) deve ser uma letra (intervalos a..z ou um mesmo programa. Elas
A..Z) ou um underline (_). permitem, por exemplo,
Os demais caracteres (opcionais) podem ser letras, nmeros (0..9) ou a implementao de
programas grandes atravs
undelines. de fragmentos menores
No existe sensibilidade de caixa, ou seja, no h distino entre mais- fceis de gerenciar.
culas 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 edito-
res 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 :
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 reser-


vada 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 dis-
postas em sesses (unidades, tipos, constantes, variveis e mdulos) que so
estudadas ao decorrer do livro.
As respectivas palavras reservadas begin e end, representam os deli-
mitadores do bloco ou corpo principal do programa: todo contedo entre begin
(que significa incio) e end (que significa fim) representa o programa propria-
mente 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.
Comentrios so fragmentos de textos no compilveis escritos con-
juntamente 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).
Sub-rotina:
So trechos de cdigo- Uma sesso de unidades declara bibliotecas conhecidas como unida-
fonte que funcionam como des em Pascal. Unidades contm sub-rotinas desenvolvidas por outros pro-
programas independentes. gramadores que se tornam disponveis nos programas onde so declaradas
Programas e unidades tais unidades (Vrias unidades so distribudas com o compilador Pascal e
em Pascal so de fato
aglomeraes de sub- esto disponveis aps sua instalao).
rotinas. As sub-rotinas so Listagem 1
tambm conhecidas como 01 program primeiro_exemplo;
subprogramas. Adiante
02 uses crt, sysutils, nova_unidade;
veremos que sub-rotinas
em Pascal podem ser 03 begin
procedimentos ou funes 04 modulo1;
e que por essa razo
05 modulo2(34);
utilizamos o termo mdulo
para nos referirmos a 06 modulo3(12, teste);
ambos. 07 end.
19
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 con-
tedo 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 procedimen-
to (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 repas-
sada 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 par-
metro do mdulo. As trs chamadas de mdulos na Listagem 1 possuem res-
pectivamente 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 progra-
mador 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 me-
mria 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).
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 conjun-
to de nomes de variveis que compartilham o mesmo tipo e que so sintatica-
mente 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 ca-


tegorias,
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 basi-
camente pelo nmero de bytes e (consequentemente) pela faixa de valores que
podem ser representados (quanto mais bytes, mais nmeros podem ser repre-
sentados 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 Tamanho (bytes)


Byte 0 .. 255 1
Shortint -128 .. 127 1
Smallint -32768 .. 32767 2
Word 0 .. 65535 2
Integer smallint ou longint 2 ou 4
Cardinal longword 4
Longint -2147483648 .. 2147483647 4
Longword 0 .. 4294967295 4
Int64 -9223372036854775808 .. 9223372036854775807 8
QWord 0 .. 18446744073709551615 8
Tabela 2 - Tipos inteiros da Linguagem Pascal
21
Linguagem de Programao I

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 arquite-
tura de CPU utilizada).

Tipo Faixa Tamanho (bytes)


Real depende da plataforma 4 ou 8
Single 1.5E-45 .. 3.4E38 4
Double 5.0E-324 .. 1.7E308 8
Extended 1.9E-4932 .. 1.1E4932 10
Comp -2E64+1 .. 2E63-1 8
Currency -922337203685477.5808 .. 8
922337203685477.5807
Tabela 3 - Tipos reais da Linguagem Pascal

A sesso a seguir declara algumas variveis reais,


Os tipos integer e real
var variam com a plataforma
utilizada, ou seja,
angulo: real; // grupo de uma varivel real de nome angulo
dependendo da arquitetura
pop, uni: extended; // grupo de duas variveis extended de nomes pop e uni da CPU suas variveis
podem ser mais ou
menos representativas.
Tipos lgicos ou booleanos so utilizados para definir variveis que as- Recomenda-se que no
sumam apenas os valores verdadeiro e falso. Estes valores so represen- caso do desenvolvimento
tados em Pascal respectivamente pelas palavras reservadas True e False. de programas que devam
rodar em mais de uma
Uma varivel lgica teoricamente representada por um nico bit, mas na plataforma, esses tipos
prtica existem quatro tipos booleanos em Pascal com pelo menos 1-byte, sejam evitados.
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.
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 re-
servada 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 strin-
gs, veja Captulo 2.
Para determinar em Pascal o tamanho em bytes utilizado por uma va-
rivel 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 deter-


minao 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 expres-
so (veja prxima sesso) ou vinculada a uma clula de memria indepen-
dente (como nas variveis), mas com suporte apenas a verificao (nunca a
escrita). Nas expresses,
23
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 caracte-
res 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; // constante de tipo inteiro

max = 6.76; // 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;
24
RICARDO REIS PEREIRA

Observe que a tipagem de q no necessrio pois o compilador detec-


taria 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 denomina-
do 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 expres-


ses 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
25
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 num-
ricos 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 ope-
ram 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 aritmti-
cos (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 resol-


ve as sub operaes que constituem uma expresso. Numa expresso aritm-
tica 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 ex-
presso, 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,
26
RICARDO REIS PEREIRA

100 div 3 div 2 div 5

33 div 2 div 5

16 div 5

Para quebrar a ordem de precedncia seguida nas avaliaes de ex-


presses, 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, verda-
deiro 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 respec-
tivos 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 for-
madas 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
27
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 (dis-
posto 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 B A and B A or B A xor B not A
TRUE TRUE TRUE TRUE FALSE FALSE
TRUE FALSE FALSE TRUE TRUE FALSE
FALSE TRUE FALSE TRUE TRUE TRUE
FALSE FALSE FALSE FALSE FALSE TRUE
Tabela 8 - Tabela verdade dos operadores lgicos em Pascal

Em Pascal, expresses booleanas conectadas com operadores lgi-


cos, 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 ava-
liado 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-
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 y menor ou igual a sete
(x>11) and (x<=100) x maior que onze e ao mesmo tempo menor
ou igual a cem
zeta <> mega zeta diferente do em mega
(a<100) or (b>500) 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 in-
terface grfica (uma janela com botes, menus, caixas de rolagem e etc). O
desenvolvimento de interfaces grficas (GUIs) requer mais que a programa-
o 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 es-
tenderemos os mesmos conceitos a arquivos). Um programa executado num
terminal via linha de comando (use o command no Windows ou um interpre-
tador 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 opera-
es 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
29
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 x: integer;
04 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 digi-
tado armazenado na varivel x. importante observar que o comando read
suspende momentaneamente a execuo e aguarda que o usurio digite al-
guma 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!).
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: 2. Valor de x fornecido:


Fornecer valor de x: _ Fornecer valor de x: 32_ <enter>

3. Impresso da resposta: 4. Encerramento:


Fornecer valor de x: 32 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 n-
mero. 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,
31
Linguagem de Programao I

Var. Tipo Valor Exemplo Sada


a integer 81 writeln(tenho,a,anos); tenho81anos
b real 37.92 write(b); 3.79200000000000E+001
x integer 35 write(Carros: , x:6) Carros: 35
y real 6.7541 Writeln(>,y:7:2, gramas); > 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 tre-
cho 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 esco-
lhida 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 en-


to) 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 fun-
damental em Pascal dada por,
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 <blo-
co_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 pos-
suir 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 a string Ola Mundo s impressa se o


write(Ola Mundo!); 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 Se o valor em y for menor ou igual a 80 e ao


readln(beta); 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,
33
Linguagem de Programao I

if x<>100 or y<>67 then Caso o valor em y seja diferente de 100 ou o


write(x+y) em y diferente de 67 ento a soma deles ser
impressa. A impresso da mensagem Oi,
write(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 Se o valor em p for mpar ele ser impresso


writeln(p) integralmente, do contrrio ser impresso
metade de seu valor.
else
writeln(p/2);

Se uma sequncia formada por mais de uma linha de comando pre-


cisa 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 conhe-
cido como aninhamento de decises e teoricamente no possui restries.
Para ilustrar o aninhamento de decises observe o esquema a seguir,
34
RICARDO REIS PEREIRA

1 if <teste1> then
2 if <teste2> then
<bloco1>
2 else
<bloco2>
1 else
3 if <teste3> then
<bloco3>

O if..then..else marcado com 1 bidirecional e aninha, no primeiro blo-


co, 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 possibilida-
des 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 for-
ma 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 co-


roa da estrutura de deciso mltipla que necessariamente deve ser encerrada
em end mais ponto e vrgula. A expresso aritmtica entre case e of deve re-
sultar 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
35
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 writeln('divisao: ', a/b:0:3);
19 else writeln('opcao invalida');
20 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,
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 vari-


vel 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 conta-
dor, 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>
37
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 conta-
dor 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 Os valores de 1 a 100 so impressor


write(i, ); 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 Os valores de 1 a 100 so impressor


write(i, ' '); 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 Os valores de 1 a 100 so impressos
begin separados por espaos em branco e em
ordem decrescente. Como o lao crescente
k := 101 - i;
utilizou-se a varivel k , inteira, para calcular o
write(k, ' '); valor de impresso.
end;
38
RICARDO REIS PEREIRA

possvel acoplar decises a laos fazendo toda estrutura de deci-


so se tornar o bloco da estrutura de repetio. Este mecanismo bastan-
te 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 Imprime inteiros entre 1 e 1000 que so


if (i mod 7 = 0) and divisveis por 7 (o resto da diviso por 7
(i mod 3 <> 0) then zero, ou i mod 7 = 0) e no divisveis por 3
write(i, ' ');
(o resto da diviso por 3 no nulo, ou seja,
i mod 3 <> 0)

Laos podem ser aninhados em Pascal. Aninhar significa construir la-


os dentro de outros. No h restries da quantidade de aninhamentos numa
mesma construo. Cada lao em um aninhamento representa um nvel des-
te 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 ani-
nhado no primeiro. Semanticamente cada iterao do primeiro lao for provo-
ca 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 ani-
nham. 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
39
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 signifi-


ca 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 expres-
so devem ser modificadas dentro do bloco (ou por um agente externo ao pro-
grama), ou do contrrio o lao se tornar infinito (ou nunca ser executado).
No exemplo,

j := 1; os inteiros de 1 a 99 so impressos em
while j < 100 do sada padro.
begin
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 re-
sulta falso: neste ponto o lao encerrado. Assim 99 o ltimo valor impresso.
O lao anterior pode ser facilmente substitudo por um lao de conta-
gem. H situaes entretanto que os laos de contagem no podem resol-
ver, como em,

x := 145; Imprime a representao bin[aria de 145, de trs


while x > 0 do begin para frente, ou seja, 10001001.
write(x mod 2);
x := x div 2;
end;
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 reserva-
das 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 pri-
meira 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 exi-
be 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-
41
Linguagem de Programao I

te anulada fora do lao, Linha-04) conter, no final das iteraes, a so-


matria 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 (veri-
ficao 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 write('media: ', s/n :0:2)
17 else
18 write('nenhum valor fornecido!');
19 end.

4.8.4. Break e Continue


Quebrar um lao significa suspender seu fluxo de execuo e continuar a exe-
cuo do programa a partir da primeira instruo que sucede o corpo estrutu-
ral 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, reescre-
ver o lao da Listagem-1.5 utilizando while..do conforme segue,
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 tes-


te 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 sim-
plesmente 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 ha-


ver 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;
43
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 obri-
gando 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 reco-
mendado sequer existindo em outras linguagens. Pascal constri desvio incon-
dicional 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 vr-
gulas. O local do programa para onde o desvio deve conduzir deve conter o
rtulo ps-fixado de dois pontos (:).
44
RICARDO REIS PEREIRA

Listagem 6
01 program desvio;
02 var
03 n: integer;
04 label
05 rot;
06 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 associa-
o 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 po-
dem 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 dispo-
nveis 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.
45
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 m-
dulo 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 en-
trada. 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 segun-


do. 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 procedu-


re 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.
46
RICARDO REIS PEREIRA

Listagem 7
01 program usando_procedimento;
02 procedure meu_teste;
03 begin
04 writeln('chamada feita com sucesso');
05 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 (argumen-
tos 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>.
47
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 pro-
cedimento 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 princi-
pal 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 ,
48
RICARDO REIS PEREIRA

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 (separa-
das por vrgulas) igual ao nmero de argumentos presentes em seu prottipo.
Essas entradas podem ser valores constantes, variveis, expresses ou mes-
mo chamadas de outros mdulos. Cada entrada resolvida antes da execu-
o 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 segui-


da 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 pro-
cedimentos. 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.
49
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 fato-
rial 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 cha-
madas 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 fa-
torial. 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 ,

Fatorial de 0 = 1

Fatorial de 1 = 1

Fatorial de 2 = 2

Fatorial de 3 = 6

Fatorial de 4 = 24

Fatorial de 5 = 120
50
RICARDO REIS PEREIRA

Listagem 9
01 program teste_de_funcoes; 13 procedure listar(max: integer);
02 var 14 var i: integer;
03 n: integer; 15 begin
04 16 for i := 0 to max do
05 function fat(n: integer): integer; 17 writeln('Fatorial de ', i, ' = ', fat(i));
06 var i: integer; 18 end;
07 begin 19
08 fat := 1; 20 begin
09 for i := 1 to n do 21 readln(n);
10 fat := fat*i; 22 listar(n);
11 end; 23 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 retor-
na 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 argumen-
tos 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 deno-
minadas 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,
51
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 tes-
te_1 no visualiza y, apenas teste_2.
Quando uma varivel local possui o mesmo nome de uma varivel glo-
bal (como n na Listagem 9), o mdulo ignora a varivel global e qualquer ope-
rao afeta apenas a varivel local.
As regras que definem o acesso das variveis num programa, breve-
mente 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
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 C, F: real;
04 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 ex-


presso sem parnteses do lado direito. O primeiro e o terceiro argumento do
writeln, Linha-08, fazem as temperaturas serem escritas com uma casa deci-
mal 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:

p
IMC = 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.
53
Linguagem de Programao I

Listagem 11
01 program Calculo_IMC; 10 write('IMC = ', imc:0:1, '. ');
02 var 11 if (imc<20) then
03 peso, altura, imc: real; 12 writeln('Magro!')
04 begin 13 else
05 write('Fornecer altura em metros: '); 14 if (imc>25) then
06 readln(altura); 15 writeln('Gordo!')
07 write('Fornecer peso em kg: '); 16 else
08 readln(peso); 17 writeln('Normal!');
09 imc := peso/(altura*altura); 18 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 a,b,c: integer; 12 writeln(c)
04 begin 13 else
05 write('Fornecer numeros: '); 14 if b>c then
06 readln(a,b,c); 15 writeln(b)
07 write('Max(',a,',',b,',',c,') = '); 16 else
08 if a>b then 17 writeln(c);
09 if (a>c) then 18 end.
54
RICARDO REIS PEREIRA

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


nmeros inteiros fornecidos. Este programa possui trs processos bidirecio-
nais 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 de-
ciso 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 da-
dos. 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 tro-
ca de valores entre duas variveis envolve necessariamente uma tercei-
ra 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 au-
xiliar. 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 a, b, c, t: integer; 15 c := t;
04 begin 16 end;
05 write('Fornecer numeros: '); 17 if b>c then begin
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 end; 23 end.
12 if a>c then begin
55
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 expli-
cado 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 inter-
medirio 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 pro-
grama 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 program Somatorio_Quadratico;
02 var
03 i, max, S: integer;
04 begin
05 S := 0;
06 write('Fornecer limite superior: ');
07 readln(max);
08 for i := 0 to max do
09 S := S + i*i;
10 writeln('Soma de quadrados entre 0 e ', max, ' = ', S);
11 end.

Na Linha-05 a varivel S, que conter ao final do processamento o so-


matrio desejado, recebe zero marcando o incio do somatrio. O lao da
Linha-08 tem como limite superior a prpria varivel max indicando que o so-
matrio 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).
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 for n := 0 to 500 do
02 var 07 if (n mod 7 = 0) and (n mod 3 <> 0) then
03 n, S: integer; 08 S := S + n;
04 begin 09 writeln('Soma = ', S);
05 S := 0; 10 end.

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


Por essa razo ela previamente configurada como zero (Linha-05) indican-
do 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 re-
presenta 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
57
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 na-
tural n primo, deve-se dividi-lo pelos naturais no intervalo |2;|, onde
2<n. Se todas as divises forem inexatas (no divisibilidade), n ser pri-
mo. Se entretanto, neste processo de divises, uma delas for exata, o res-
tante do intervalo (se ainda houver) dever ser ignorado e n considerado
no primo.
Listagem 16
01 program primos; 16 e_primo := res;
02 17 end;
03 function e_primo(n: integer): boolean; 18
04 var d: integer; 19 var i, cnt: integer;
05 res: boolean; 20 begin
06 begin 21 i := 2;
07 d := 2; 22 cnt := 0;
08 res := true; 23 while cnt < 20 do begin
09 while d*d <= n do begin 24 if e_primo(i) then begin
10 if (n mod d) = 0 then begin 25 write(i, ' ');
11 res := false; 26 cnt := cnt+1;
12 break; 27 end;
13 end; 28 i := i+1;
14 d := d + 1; 29 end;
15 end; 30 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-
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 im-
primir 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 anu-
lado 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 nme-
ro.
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 quanti-
dade em metros quadrados de material necessrio a construo da cai-
xa. 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 retn-
gulo, acutngulo ou obtusngulo; b) valor de sua rea.
9. Faa um programa para calcular o fatorial de um nmero N inteiro dado.
59
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 pro-
grama 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:
Captulo 2
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 se-
quencial (concatenao) de unidades grficas de informao denominadas
caracteres. A presena de recursos de manipulao de strings numa lingua-
gem de programao essencial. Tais recursos so normalmente disponibi-
lizados 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 inde-
pendentes (que no fazem parte de uma string). Assim,
var

ch: char;

declara um caractere em Pascal. Em Pascal os caracteres utilizam


ASCII:
1-byte e seguem a codificao ASCII. Em ASCII os caracteres so repre-
abreviao de American
sentados por sete bits e so baseados no alfabeto ingls (o oitavo bit no Standard Code for
representativo). O total de caracteres 128 sendo 33 no imprimveis (como Information Interchange
o caso dos caracteres de controle utilizados nos bastidores de softwares pro- que significa Cdigo
Padro Americano para o
cessadores de texto).
Intercmbio de Informao.
62
RICARDO REIS PEREIRA

cod ASCII cod ASCII cod ASCII cod ASCII cod ASCII

32 42 * 52 4 62 > 72 H
33 ! 43 0 53 5 63 ? 73 I
34 44 0 54 6 64 @ 74 J
35 # 45 0 55 7 65 A 75 K
36 $ 46 . 56 8 66 B 76 L
37 % 47 / 57 9 67 C 77 M
38 & 48 0 58 : 68 D 78 N
39 49 1 59 ; 69 E 79 O
40 ( 50 2 60 < 70 F 80 P
41 ) 51 3 61 = 71 G 81 Q

cod ASCII cod ASCII cod ASCII cod ASCII cod ASCII

82 R 92 \ 102 f 112 p 122 z


83 S 93 ] 103 g 113 q 123 {
84 T 94 ^ 104 h 114 r 124 |
85 U 95 _ 105 i 115 s 125 }
86 V 96 ` 106 j 116 t 126 ~
87 W 97 a 107 k 117 u
88 X 98 b 108 l 118 v
89 Y 99 c 109 m 119 w
90 Z 100 d 110 n 120 x
91 [ 101 e 111 o 121 y
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 deno-
minado 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
63
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 impri-
mveis. Caracteres no imprimveis causam outros efeitos (no necessaria-
mente na sada padro) que dependero da plataforma utilizada. So exem-
plos 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 sem-
pre um valor inteiro (valor do cdigo ASCII).
Caracteres so dados ordinais dispostos na sequncia de seus respec-
tivos 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
64
RICARDO REIS PEREIRA

(107) e somar resultado ao do cdigo do caractere A (75). Como as letras, tan-


to 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 pr-
prio 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 ); // -32 75-107
05 eles
06 maiuscula := ch;
07 end.

1.2. Strings Curtas e Longas


Uma string uma concatenao de caracteres. Em Pascal a palavra reserva-
da string denota o tipo para declarao de strings. Strings possuem especifica-
o opcional de tamanho, ou seja, no obrigatrio informar quantos caracte-
res 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 ta-


manho,
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 constru-
o classifica as strings declaradas como strings curtas. Tais strings podem
ser alternativamente declaradas pela palavra reservada shortstring (sem espe-
cificao de tamanho). Exemplo,
var sst: shortstring;
65
Linguagem de Programao I

As strings longas em Pascal correspondem s strings sem restries de Diretivas de Pr-


tamanho. Elas permitem a concatenao de qualquer quantidade de caracte- processamento ou
simplesmente Diretivas:
res. So declaradas utilizando-se o tipo ansistring. Exemplo, tratam-se de cdigos
var lst: ansistring; escritos entre chaves, { },
pr-fixados pelo smbolo $
Uma string longa processada mais lentamente que as curtas devido e que servem normalmente
a natureza de sua implementao. Por uma questo de performance, sempre para ligar, desligar ou
que possvel, aconselhvel utilizar strings curtas. modificar recursos do
compilador. Exemplo, {$I+}.
O compilador Pascal poder interpretar uma declarao de string sem
especificao de tamanho como sendo uma string curta ou longa dependen-
do do acionamento da diretiva {$H}. A diretiva {$H-} instrui o compilador a con-
siderar 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 aplica-
do. Logo existe equivalncia tanto entre os quatro cdigos,
program teste; program teste; program teste; program teste;
var {$H-} var var
x: string; var x: x:
string[255]; shortstring;
{} 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.
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 conhe-
cida como inicializao da string.
Variveis de tipo string podem ser atribudas diretamente a outras mes-
mo quando seus comprimentos so distintos. Quando uma string recebe o
contedo de outra string, seu contedo primeiramente eliminado da memria
O tamanho de uma string
equivale ao mximo de
e em seguida sua referncia (o ponto da memria ao qual a string se refere)
caracteres que ela pode mudado para o mesmo da string atribuda. Por exemplo em,
suportar. O comprimento A := minha casa;
de uma string representa B := meu trabalho;
o total de caracteres que B := A;
ela utiliza em determinado
momento. O comprimento faz a string meu trabalho ser eliminada da memria e a string minha casa passar
sempre menor ou igual a ser referenciada tanto por A quanto por B. A priori acredita-se que qualquer
ao tamanho. 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 atri-
buda 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, ocorre-
r um erro em tempo de execuo.
A concatenao ou fuso de strings em Pascal construda com o ope-
rador 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,
67
Linguagem de Programao I

x := 'ola' + ' !'; // ola!


y := x + 'mundo'; // 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 conver-
so 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 conca-
tenao da Linha-11, armazenada na varivel s e impressa na Linha-12.
Listagem 18
01 program usando_str;
02 var
03 s, si, sp: string;
04 idade: integer;
05 peso: real;
06 begin
07 idade := 25;
08 peso := 60.5;
09 str(idade, si);
10 str(peso:0:2, sp);
11 s := 'Ela tem '+si+' anos de idade e pesa '+sp+'
12 quilos';
13 writeln(s);
end.
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 infini-
to (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 utili-
zando 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
69
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 begin
08 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 break;
16 until False; // Lao infinito
17 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 defi-
nido na declarao. Exemplo,
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 carac-
teres 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 comprimen-
to 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 con-
tagem 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 readln(s);
02 var 08 write('Inverso> ');
03 s: string[100]; 09 for i := length(s) downto 1 do
04 i: integer; 10 write( s[i] );
05 begin 11 writeln;
06 write('Entrada> '); 12 end.

O acesso individual a caracteres proporcionado pelo operador de inde-


xao 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] ); // ver Listagem-2.1
writeln(s);
71
Linguagem de Programao I

onde s pode ser uma string curta ou longa. O lao de contagem cres-
cente 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 lexi-
cogrfico. 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 lexicografica-
mente 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 com-


primento e mesma sequencia de caracteres.
Para obter uma substring de uma dada string, utiliza-se o comando Substring:
copy, unidade system, cuja sintaxe bsica , String formada por uma
subsequencia contnua
copy(S, I, cont); dos caracteres de uma
onde S denota uma string, curta ou longa, da qual se deseja obter a outra string. Na string
abcdefghij so exemplos
substring, I denota a posio dentro da string onde deve iniciar a substring e de substrings abc, cdefg
cont a quantidade de caracteres que devem ser extrados. A nova string gerada e ij.
por copy dve ser atribuda a uma varivel string, fazer parte de uma expresso
ou ser repassada a como argumento de um mdulo. Exemplos,
72
RICARDO REIS PEREIRA

s := 'ABCDEFG';

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

writeln( copy(t, 2, 2) ); // DE

s := s + copy(s,4,4); // ABCDEFGDEFG
Quebrar uma string
significa subdividi-la onde s e t so variveis strings. A primeira extrao atribuda a t, a se-
em substrings cuja gunda repassada como parmetro de writeln e a terceira componente
concatenao origina
de uma expresso.
a string original. Por
exemplo, a string abcxyzw Strings podem ser inseridas em outras, ou seja, possvel, utilizando
pode ser quebrada no um nico comando, quebrar uma string W em W1 e W2 e depois fazer W se
conjunto {abc, xyzw} ou
tornar W1 + X + W2 onde X a string inserida. Para inserir uma string em outra,
em {ab, cxy, yz, w}.
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 inser-
o. 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 re-
torno (procedimento) mas modifica a string passada como segundo argumento.
Para remover caracteres de uma string utiliza-se o comando delete, uni-
dade system, de sintaxe bsica,
delete(S, p, cont);

onde S denota a string que sofrer retrao, p a posio onde deve princi-
piar a deleo e cont a quantidade de caracteres que devero ser eliminados.
Internamente delete efetua a quebra da string e concatena as partes que de-
vem 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 carac-


teres. 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.
73
Linguagem de Programao I

2. Arrays
Uma array uma estrutura de dados que permite o armazenamento sequen-
cial de dados de mesmo tipo. Cada unidade constituinte de uma array de-
nominada 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 pre-
sentes em arrays de outros tipos base. Manteremos a conveno distinguindo
strings de arrays. Arrays no podem ser diretamente concatenadas, compara-
das, 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 compri-
mento teto e comprimento utilizado como nas strings. Dessa forma length retor-
na sempre o total de clulas alocadas em memria para a array, independente
do contedo.
Arrays em Pascal podem ser estticas e dinmicas. Uma array est-
tica 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 ar-
rays 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 unidimensio-
nal 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.
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; // i-low(x) inicia sempre
em zero
75
Linguagem de Programao I

A memria ocupada por uma varivel array a somatria das mem-


rias 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 writeln(A[i], ' ', B[i]);
16 end.
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 indi-
vidual 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; // segunda sintaxe

sendo a segunda sintaxe preferencial.


77
Linguagem de Programao I

Cada dimenso de uma array multidimensional esttica em Pascal pos-


sui sua prpria faixa de ndices encapsuladas pela palavra reservada array e
por colchetes individuais (primeira sintaxe) ou separadas por vrgulas e envol-
vidas 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 pre-
vistas 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 ,


Matriz Identidade:
for lin := 1 to 5 do Na matemtica a matriz
quadrada (nmero de
for col := 1 to 5 do
linhas igual ao de colunas)
if col = lin then cujos elementos so todos
mat[lin, col] := 1.0
nulos, exceto aqueles da
diagonal principal (diagonal
else cujo ndice da linha e da
mat[lin, col] := 0.0;
coluna so idnticos), que
valem 1.
onde col e lin so inteiros. O aninhamento dos laos neste exemplo permite var-
rer 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
78
RICARDO REIS PEREIRA

contguas de clulas sendo o aspecto multidimensional um recurso da lingua-


gem 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 unidimensio-
nais, ,
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 cha-
mada 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 se-
tlength. 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
79
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 y[i] := 2*y[i];
14 for i := 0 to max-1 do
15 writeln( x[i], ' ', y[i] );
16 end.
80
RICARDO REIS PEREIRA

A atribuio direta de uma array dinmica a outra no gera uma nova ar-
ray 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 setleng-


th. 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,


81
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 argu-
mento mat[0]. De fato se mat tivesse, por exemplo, cinco dimenses, o com-
primento 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 ele-
mentos 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 entra-
da 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 ra-
zo 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.
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 exata-
mente 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 ima-
gem (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 end;
22 end;
83
Linguagem de Programao I

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 des-
te 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 con-
tedo das posies i e k. O total de trocas realizadas est diretamente ligado
ao esforo de ordenao.
Subarray:
O programa da Listagem 24 implementa a ordenao por seleo em Array obtida a partir de
Pascal. O lao entre as Linhas 10 e 13 carrega (e imprime) a array dat com dez va- uma subsequncia de
clulas continuas de uma
lores aleatrios obtidos com o comando random. O comando random, unidade sys-
array dada.
tem, 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.
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 pri-
meira 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 for i := 1 to n-1 do begin
02 const 15 k := i;
03 n = 10; 16 for j := i+1 to n do
04 var 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];
07 begin 20 dat[k] := x;
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 write( dat[i], #9 );
12 write( dat[i], #9 ); 25 writeln;
13 end; 26 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, atra-
vs da utilizao de arrays, determinar o fatorial de qualquer inteiro.
A tarefa de determinao do fatorial de um inteiro qualquer possui qua-
tro 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 pro-
duto 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.
Para resolver a primeira etapa utilizamos a equao,, que determina a
Varivel Escalar:
So todas as variveis quantidade de dgitos t na base b de um inteiro n. Assim a quantidade de dgi-
que no so arrays nem tos do fatorial de N na base 10 ,
strings nem estruturas t = 1+ log10( N!) (1)
heterogneas (Veja
Captulo-3).
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 0 0 0 0 0 1

A terceira etapa, da multiplicao de um escalar d pela array data, fun-


ciona 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 var-
rendo 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.
85
Linguagem de Programao I

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 se-
guir 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 end;
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); 25 write( data[i] );
12 t := round(s); 26 writeln;
13 setlength(data, t); 27 end.
14 for i := 0 to t-1 do data[i] := 0;

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 con-
tabilizam 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 O logaritmo de um nmero
valor em s (comando round, unidade system), registrado em t, a quantidade a na base b, ou seja, logb
de dgitos procurada. (a) , pode ser reescrito
como a razo In(a)/In(b),
A segunda etapa ocorre entre as Linhas 13 e 15 onde ocorre alocao onde ln o logaritmo
da array data e seu preenchimento apropriado. A terceira etapa, Linhas 17 a natural.
22, est aninhada na quarta etapa (Lao iniciado na Linha-16). Cada valor de
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 res-
ponsveis 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, con-
trole 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 carac-
tere 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.
87
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 posi-
es 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 an-
loga 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 polin-
mio 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 ve-
rificao 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 9 8 7 6 5 4 3 2 pesos
a1 a2 a3 a4 a5 a6 a7 a8 a9
Depois se calcula a soma S1 de todos os nmeros resultantes. O d-
cimo 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
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 deci-
mais 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 ele-
mentos. 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 quadra-
das 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 tra-
jetrias possveis. Construir programa que receba N e retorne o total de
trajetrias numa grade NXN.
89
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/
90
RICARDO REIS PEREIRA
Parte 2
Tipos de Dados Personalizados
Captulo 3
Tipos de Dados
Personalizados
Objetivos:
Esta unidade tem por objetivo introduzir estruturas sofisticadas da lingua-
gem 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 podero-
so 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 inter-
valo de -128 a 127, estar presente em expresses aritmticas em operaes
de soma, subtrao, multiplicao e diviso bem como ser alvo de uma atri-
buio. 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 pri-
mitivos (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 se-
ro 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 pri-
mitivo 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 personaliza-
do 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 com-
pilador emitir uma advertncia, mas no um erro.
O tamanho em bytes de uma varivel de tipo faixa o menor valor in-
teiro 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 normalmen-
te como qualquer outra variveis inteira.
95
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 sequen-


cialmente 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 ar-
ray esttico personalizado. Assim, neste ltimo caso, a atribuio,
x := c;

pode ser utilizada para inicializar x. As dez clulas de c tm o contedo co-


piado 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.
96
RICARDO REIS PEREIRA

Listagem 26
01 program tipo_array_dinamico;
type
02
tdyarr = array of integer;
03 var
x, y: tdyarr;
04 i: integer;
05 begin
setlength(x, 20);
06 for i := low(x) to high(x) do x[i] := i*i;
07 y := x;
for i := low(x) to high(x) do y[i] := y[i]*2;
08 for i := low(x) to high(x) do write(x[i], );
09 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 ar-
rays 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 qua-
drados 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 al-


gum 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);


97
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 identificado-
res 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 enume-
rao 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 an-
tecessores, dependendo do caso. Para modificar o equivalente numrico de
um identificador deve-se atribuir a ele um valor inteiro com o operador de atri-
buio diretamente na definio da enumerao. Na redefinio da enume-
rao 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-
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 com-
paraes 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) );


99
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 pernona-
lizados. 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 estru-
tura 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 blo-
co 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, informa-
es 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
100
RICARDO REIS PEREIRA

idade e media a mdia final. A declarao de variveis de tipo estrutura hete-


rognea 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 aces-
sados diretamente como se fossem variveis independentes. Este acesso
contrudo com o operador ponto (.) posto entre a varivel estrutura heterog-
nea 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 vari-


vel estrutura heterognea podem ser modificados ou lidos independentemen-
te. 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 va-
rivel 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 dispos-
ta entre with e do. Estas palavras reservadas significam com e faa respecti-
vamente. 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.


101
Linguagem de Programao I

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.
Ponto no Plano: Os
Utilizando uma estrutura possvel abstrair uma entidade que facilite o pontos no plano cartesiano
trabalho do programador. Por exemplo, aplicando a ideia de ponto no plano da so representados por
uma coordenada no eixo x
estrutura anterior possvel escrever funes e procedimentos que executem
(abcissas) e outra no eixo
tarefas de geometria analtica plana. Neste contexto uma funo que calcule y (ordenadas).
a distncia entre dois pontos no plano pode ser implementada como segue,
function dist(p, q: ponto) : real;
Geometria Analtica
begin Plana: Parte da
dist := sqrt( sqr(p.x-q.x) + sqr(p.y-q.y) );
matemtica que trata da
resoluo de problemas da
end; geometria plana atravs
onde sqrt e sqr so funes da unidade system que retornam respectivamente do equacionamento de
entidades primitivas como
a raiz quadrada e o quadrado de um nmero. Os argumentos de entrada p e pontos, retas e cnicas.
q, de tipo ponto, permitem uma codificao mais elucidativa sobre o problema A geometria analtica no
da distncia entre dois pontos no plano. depende de desenhos
(apesar de ajudarem)
Um tipo estrutura heterognea pode ser utilizada como sada de uma como a geometria plana
funo para permitir que mais de uma informao possa ser retornada. Por pura.
exemplo, no problema da equao do segundo grau, duas razes precisam
ser devolvidas, quando existirem. Um modelo de estrutura heterognea pro-
posta 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 recebi-
dos 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).
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 comple-
xas) 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 function eq2g(a,b,c: real): root;
var delta: real;
02 begin
03 eq2g.erro := 0;
if abs(a)>1.0e-5 then begin
04 delta := sqr(b) - 4*a*c;
05 if delta>=0 then begin
eq2g.x1 := (-b+sqrt(delta))/(2*a);
06 eq2g.x2 := (-b-sqrt(delta))/(2*a);
end else
07
eq2g.erro := 2;
08 end else
eq2g.erro := 1;
09 end;
10
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.
103
Linguagem de Programao I

Estruturas heterogneas podem agrupar arrays, enumeraes ou mes-


mo 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 hete-


rognea 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,
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 fun-
ciona 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 estru-


turas 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 he-


terognea. 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,
105
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 possibili-
dades. 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 con-
junto 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
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 impor-
tante. 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 al-
guns 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 con-


junto 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 ne-
nhuma estiver presente, nada ocorrer.
A operao de verificao em conjuntos consiste na checagem da pre-
sena de um determinado item. Ao contrrio da atribuio, incluso e remo-
o, a verificao s pode ser executada item a item. A Linguagem Pascal
107
Linguagem de Programao I

possui o operador in exclusivo para verificao de itens em conjuntos. Trata-


se 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, con-


tm 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 con-


junto s.
Para verificar simultaneamente mais de um item deve-se usar operado-
res 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.
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 re-
presente 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 coorde-
nada 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 (mi-
nado, aberto, trancado e detonado) e construa uma funo que simule
uma tentativa de clique.
Captulo 31
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 ins-
tanciada 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 quanti-
dade 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, utili-
zando o endereo de varivel que armazena, l ou modifica o contedo desta
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 solicita-
do. Para cada solicitao o programa dever manter um ponteiro que recebe-
r 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 endere-
os (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 en-
cerre, 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 re-
quer memria em heap.
Na alocao esttica todas as variveis possuem nome e a desaloca-
o 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 di-
nmica 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 ou-
tro 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.
111
Linguagem de Programao I

Uma arquitetura cujos endereos de memria tm n-bits, pode repre-


sentar um total de 2n endereos distintos. Haja vista que cada endereo refe-
re-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 tipa-
dos, 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 declara-
do apontar para uma varivel deste tipo base. O tipo base pode ser um tipo
primitivo como,

var
p: ^integer; Diz-se que p um ponteiro para
inteiro, q para real e pt para
q: ^real;
booleano.
pt: ^boolean;

pode ser um tipo estrutura heterognea,


type

TReg = record

x, y, z: Byte;

end;

var

reg: ^TReg;
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 descon-


textualizado 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 con-
duz 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 quais-
quer ponteiros (tipados ou no), fazem-nos apontar para lugar nenhum. Assim,
p := nil;

faz com que o ponteiro p aponte para parte alguma.


113
Linguagem de Programao I

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 11 end.
06 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
Para acessar uma varivel
vertical que aponta para cima lembrando que se est apontado para outra via ponteiro recorre-se
parte da memria). A Listagem 28 Ilustra o desreferenciamento de ponteiros. inicialmente a clula
Na Linha-08 o valor da varivel apontada por p, ou seja, i, apenas lido da de memria onde est
o endereo, valor o
memria e impresso pelo writeln. Na Linha-09 a varivel apontada, ainda i,
qual conduzir a outra
modificada pela atribuio. Assim a sada deste programa deve ser, clula. O fato de se no
127 231 ir diretamente ao local
final caracteriza uma
A indireo dos ponteiros se mantem em cpias dos ponteiros. Assim, indireo. Vrios nveis de
por exemplo, se no exemplo da Listagem-4.1 houvesse outro ponteiro de intei- indireo surgem quando
ro q ainda seria legal escrever, se operam com ponteiros
de ponteiros.
114
RICARDO REIS PEREIRA

Um modelador um i := 127;
recurso da Linguagem p := @i;
Pascal que obriga um valor
de um tipo a se tornar de q := p; // Cpia de ponteiro
outro tipo. a chamada writeln(q^); // A cpia mantm a indireo
coero de dados. A
sintaxe de uma coero A atribuio q:=p copia o endereo armazenado em p para o ponteiro
tipo(valor) onde tipo denota q. Assim q^ funciona como p^, ou seja, duas referncias varivel i. Se o tipo
o tipo de dados para o qual base do ponteiro q no for o mesmo do ponteiro p a atribuio falhar (ocorre
valor deve ser coagido.
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 PtReal = ^real;
05 var
06 i: integer;
07 p, q: PtInt;
08 r: PtReal;
09 begin
10 i := 127;
11 p := @i;
12 r := PtReal(p); // Coero de ponteiro de inteiro para real
13 q := PtInt(r); // Coero de ponteiro de real para inteiro
14 writeln(q^);
15 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 de-
clar-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
115
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 begin
02 type 09 i := 127;
03 PtInt = ^integer; 10 p := @i;
04 var 11 q := @p;
05 i: integer; 12 writeln(i, ' ', p^, ' ', q^^);
06 p: PtInt; 13 end.
07 q: ^PtInt;

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 pon-
teiro 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 write(pt[i], ' ');
10 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];
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 carac-
teres. 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 begin
06 p := @s[1];
07 write(p);
08 end.

Contador de referncia
uma metodologia Na Listagem 32 o ponteiro p recebe o endereo da cadeia s (Linha-06).
utilizada para otimizar o A impresso (Linha-07) feita diretamente via ponteiro.
gerenciamento de memria
dinmica associado aos
O tipo PChar em Pascal denota ponteiro de caractere (^char) com a
ponteiros. Baseia-se na convenincia de permitir atribuies diretamente. Internamente uma varivel
definio implcita de Pchar aloca e desaloca memria convenientemente utilizando contadores
um contador para cada de referncia de forma a manter strings de tamanho variante.
ponteiro que armazena
o nmero de variveis A Listagem 33 ilustra o uso de Pchar. Nas Linhas 06 e 08 so respecti-
que se referem a ele. vamente inicializadas, com caracteres de constantes strings, as variveis p de
Quando este contador zera tipo PChar e s de tipo string. Quando p recebe o endereo da cadeia apontada
a memria apontada
por s (Linha-09), o contador de referncia de teste de uso de PChar zerado
desalocada. Dessa forma
o programador no precisa e esta string desalocada. A string uma string possui agora contador de refe-
se preocupar em desalocar rncia igual a dois e pode ser tanto acessada por s quanto por p (Linha-10). A
memria dinmica que sada deste programa ,
requisitou pois isso ocorre
automaticamente. teste de uso do PChar

uma string
117
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 co-
mumente 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 esca-
lares ou vetoriais.
Argumentos ponteiros funcionam como quaisquer ponteiros permitindo
aritmtica e desreferenciamento clula de memria endereada. H o incon-
veniente 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 argu-


mentos 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 (argumen-
tos ponteiros agem como sada nos procedimentos).
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 writeln('Raizes: ', x1:0:2, ' e ', x2:0:2)
26 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,
119
Linguagem de Programao I

b , onde
x= = b2 4 a c
2a

desde que a seja no nulo e seja no negativo (se a no nulo e negati-


vo, as razes so complexas).
O programa da Listagem 34 resolve o problema da equao de segun-
do 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 bo-
oleana 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 igno-
rados. 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 pro-
blemticos. 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, re-
gistradas nas clulas apontadas por p e q (Linhas 14 e 15). Antes do encerra-
mento da funo, eq2g (varivel interna) mudada para true (Linha-16) indi-
cando que razes foram calculadas com xito.
A chamada de eq2g no programa principal acontece dentro de uma es-
trutura 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 va-
riveis globais x1 e x2 que ao final portaro as razes, se existirem.
Uma importante habilidade que ponteiros permitem a mdulos o aces-
so 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
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 c-


lula 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 atu-
alizada 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
121
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 i: integer;
18 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 meca-
nismo de alocao dinmica. Estas variveis no possuem nomes e depen-
dem de ponteiros para serem manipuladas. Ponteiros tipados possuem em
Pascal duas abordagens de alocao, a escalar e a vetorial, que so estuda-
das nas Sesses 5.1 e 5.2 . A alocao com ponteiros no tipados estudada
Sesso 5.3 .
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 dispo-
se 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 ar-
gumento 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 argumen-


to, libera a memria alocada por new.
Listagem - 37
01 program Alocacao_dinamica_2; 08 begin
02 type 09 new(q);
03 ponto = record 10 q^.x := 3.0;
04 x,y,z: real; 11 q^.y := 1.0;
05 end; 12 q^.z := 0.5;
06 var 13 dispose(q);
07 q: ^ponto; 14 end.
123
Linguagem de Programao I

As mesmas regras se mantm para variveis de tipo estrutura hetero-


gnea. 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 re-
cord precisa de seu prprio desreferenciamento (Linhas 10, 11 e 12).

5.2. Alocao Dinmica Vetorial


Na abordagem vetorial com ponteiros tipados a memria alocada repre-
sentada 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 co-
mando 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 coman-
do 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 en-
dereo.
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 program Alocacao_Dinamica_3; 14 q^ := i;
02 var 15 q := q + sizeof(integer);
03 i, j, n: integer; 16 inc(j);
04 p, q: ^integer; 17 end;
05 begin 18 inc(i);
06 write('Total: '); 19 end;
07 read(n); 20 for i := n-1 downto 0 do begin
08 i := 0; 21 q := p + i * sizeof(integer);
09 j := 0; 22 write(q^, ' ');
10 getmem(p, sizeof(integer)*n); 23 end;
11 q := p; 24 freemem(p);
12 while j<n do begin 25 end.
13 if (i mod 3 = 0) and (i mod 7 <> 0) then begin
124
RICARDO REIS PEREIRA

O programa da Listagem 38 ilustra o uso de getmem e freemem. O pro-


grama 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 blo-
co, 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.
Na Linha-15 o valor do endereo em q incrementado de sizeof(integer)
Os comandos inc e
em cada iterao do lao da Linha-12 cujo teste da Linha-13 obtm sucesso.
dec, unidade system,
fazem respectivamente Haja vista que o valor inicial de q o mesmo de p (Linha-11), ento q passa por
a incrementao e cada clula da array dinmica (ver Figura - 9). Assim as atribuies da Linha-14
decrementao numrica armazenam os valores encontrados em suas posies apropriadas na array.
de variveis ordinais
J na Linha-21 as posies apropriadas so calculadas diretamente por uma
(inteiros, caracteres e
enumeraes). Estes expresso completa causando o mesmo efeito de acesso.
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) Figura 9
fazem x mudar para 4 e
2 e as chamadas inc(x,3)
O operador de indexao, [], pode ser usado com ponteiros tipados que
e dec(x,2) para 6 e 1
respectivamente. 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.


125
Linguagem de Programao I

Listagem 39
01 program Alocacao_Dinamica_4; 11 while j<n do begin
02 var 12 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 begin 15 end;
06 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 mem-
ria 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.


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 desrefe-
renciamento zera-se o contedo ali (Linha-07). O nmero de passos do lao
o total de bytes da estrutura.
127
Linguagem de Programao I

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 procedi-


mento 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 pomei-
ros no tipados. A memria alocada com ponteiros no tipados pode ser ma-
nipulada utilizando aritmtica de ponteiros. Por exemplo, para criar um bloco
Aritmtica de Ponteiros:
de memria que armazene 25 valores reais de 4-bytes utiliza-se, termo utilizado para se
getmem(p, 100); // 25x4 = 100-bytes referir s operaes
de soma e subtrao
onde p no tipado. Para aplicar a aritmtica deve-se utilizar um ponteiro de ponteiros com
auxiliar de real conforme expresso, deslocamentos de
q := p + i*4;
memria (medidos em
bytes). Esta aritmtica
onde q de tipo ^real e i inteiro. Variando i entre 0 a 24 faz-se q referir-se a no prev operaes
cada uma das 25 posies de clulas dentro do bloco alocado. Para acessar entre ponteiros por ser
cada clula deve-se desreferenciar q logo aps receber o resultado na ex- incoerente. Seu grande
objetivo referenciar
presso. No exemplo, corretamente clulas de
for i := 0 to 24 do begin memria vizinhas a uma
clula dada.
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.
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 mem-
ria 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.
129
Linguagem de Programao I

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.

Lista Encadeada
Figura 10 Elementar: uma lista
de objetos, denominados
nodos, cujo tipo
Um exemplo crtico de vazamento de memria, conhecido como ladro corresponde a um tipo
de memria, usa um lao infinito para gerar incontveis blocos perdidos em estruturado heterogneo
contendo um campo da
heap. Em Pascal implementa-se, chave e outro de ponteiro
while true do new(p); do prprio tipo estrutura
heterognea em questo.
No recomendada a execuo do ladro de memria. Isso permite que o primeiro
nodo da lista contenha
uma chave e o endereo
7. Estudo de Caso: Lista Escadeada Elementar para o segundo nodo que
contm outra chave e o
O primeiro passo para implementar uma lista encadeada elementar em endereo para o terceiro
Pascal a definio de uma estrutura heterognea para os nodos da lista. nodo e assim por diante.
Considerando uma lista de valores inteiros ento o tipo nodo proposto , 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 an-


tes 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 pno-
do. 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 procedi-
mento,
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,
131
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 repassa-
da 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; // (i)
06 p^.prox := Q^.raiz; // (ii)
07 Q^.raiz := p; // (iii)
08 inc(Q^.total); // (iv)
09 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 ini-
cializado 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 propo-
mos 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
132
RICARDO REIS PEREIRA

processo e os passos so marcados como comentrios. A Linha-09 adicional-


mente 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 end;
09 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 apre-
sentadas 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 enca-
deada elementar.
133
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 cl-
culo 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 des-
vio 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 dina-
micamente. 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 mante-
nha 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 soma-
tria 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).
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 3
Modularizao
Captulo 5
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 passa-
gem de argumentos introduzido no Captulo-1. O captulo ainda cobre
outros importantes conceitos relacionados como a recursividade e o ani-
nhamento modular. O Captulo-2 finaliza a unidade apresentado os recur-
sos 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 pou-
cos 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
O Compartilhamento de
que sejam resolvidas uma a uma pela primeira CPU livre. Tempo ou Time Sharing
As solicitaes entram na fila conforme o momento que so invocadas um recurso das CPUs
modernas que surgiu pela
de forma que pendncias de diversos programas podem estar presentes. A
necessidade de execuo
alta velocidade de processamento faz os usurios no sentirem a permutao concorrente de vrias
de atendimento de solicitaes entre programas. O multiprocessamento se aplicaes. Sistemas
resume ento no compartilhamento do tempo de trabalho das CPUs entre que tiram proveiro deste
recurso so denominados
fragmentos de tarefas nos quais os processos so quebrados.
Sistemas Multitarefas
138
RICARDO REIS PEREIRA

O compartilhamento de tempo entre processos ocorre de forma simi-


lar dentro de cada processo onde tarefas internas competem pelo tempo
de CPU(s) da aplicao. Estes subprocessos competindo entre si so de-
nominados 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 pos-
suir 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.
O controle de uma funo ou procedimento pode foradamente ser de-
Os comandos round, trunc, volvido ao seu chamador, ou seja, antes do trmino da execuo completa de
frac e int, unidade system, seu cdigo. O comando exit, unidade system, efetua esta tarefa. Por exemplo,
so comandos utilizados
no procedimento,
para operar nmeros
procedure print(n: integer);
reais. Todos possuem
apenas um argumento de begin
entrada. Round e trunc if n<0 then exit;
retornam respectivamente while n>0 do begin
o arrendondamento e o write(n);
piso do valor de entrada, n = n div 3;
ambos inteiros. Frac end;
retorna a parte fracionria end;
da entrada, tambm real e
Int retorna uma verso real quando valores negativos so repassados o procedimento chama exit devol-
da parte inteira da entrada. vendo imediatamente o controle ao chamador. Do contrrio uma sequencia
Os exemplos round(4.8), de valores impressa por ao da execuo do lao while.
trunc(4.8), Frac(4.8)
e Int(4.8) devolvem Como visto anteriormente, funes possuem uma varivel interna com
respectivamente 5, 4, 0.8 mesmo nome da funo e cujo valor antes da devoluo de controle ao cha-
e 4.0. mador 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,
139
Linguagem de Programao I

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 imediata-
O piso de um valor real x
mente ao chamador com retorno zero. Para implementar esse comportamento o maior inteiro menor ou
associou-se uma estrutura de deciso (que verifica a possvel negatividade de igual a x. Representa-se
n), uma atribuio direta do valor 0 a fnc (varivel interna) e uma chamada a exit. por.O teto de um valor real
x o menor inteiro maior
Um programa tambm pode devolver diretamente o controle ao sistema ou igual a x. Representa-se
operacional independendo do mdulo que esteja executando. Isso representa por.
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 mdu-
los construtivos de um programa. De fato estes devem trabalhar como subpro-
gramas cujas entradas so os parmetros e a sada o retorno (para o caso
de funes). Se um dado mdulo possui argumentos, eles devem ser forne-
cidos 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);
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 trans-
formado 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 for-
mais 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 estreita-


mento, 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,
141
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 pro-


cedimento 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, en-
to 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 in-
teiro) 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 refe-
rir a arrays (em aplicaes que lidam com arrays muito grandes seria problemti-
ca a passagem de argumentos por valor pois demandaria muito tempo em cpia
de dados alm do desperdcio de memria). Uma funo, por exemplo, para pro-
curar 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,
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 for-


necer 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 din-
mica 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 if data[k] > max then max := data[k];
09 end;
10
11 const
12 arr: array[1..10] of integer = (23,41,64,11,9,2,29,88,76,52);
13 begin
14 writeln( max(arr) ); // 88
15 end.

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


Pascal utilizando referncias. Uma referncia nada mais que um pontei-
ro camuflado. Elas permitem que um argumento formal se torne um apelido
143
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 alte-
rando o argumento real. Esta estrada de duas vias obriga ento que argumen-
tos 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 pa-


rmetro 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 argu-


mento 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 argu-
mentos por valor (coeficientes de um polinmio de segundo grau) e gera trs
sadas: duas atravs dos argumentos (referncias) x1 e x2 (razes do polin-
mio) e uma terceira sada natural da funo (booleano). Semanticamente a
funo tenta calcular as razes e coloc-las em x1 e x2.
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 deci-
so (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 writeln('Polinomio invalido ou raizes complexas!');
26 end.
145
Linguagem de Programao I

4. Recursividade
A recursividade um recurso de linguagem que permite um mdulo, seja
Alm da palavra reservada
ele funo ou procedimento, fazer uma chamada de si mesmo, ou seja, var, as sesses de
dentro do corpo de cdigo do mdulo possvel fazer uma ou mais cha- argumentos formais em
madas daquele mdulo. A recursividade permite implementaes mais mdulos contam com a
palavra reservada out
claras de diversos algoritmos e por essa razo um recurso nativo do
para definir referncias.
Pascal. Para calcular, por exemplo, o fatorial de um inteiro pode-se usar Out ajuda, pelo menos em
a seguinte funo, ingls, a lembrar que o
argumento deve funcionar
function fat(n: integer): integer;
como sada.
begin

if n<2 then

fat := 1

else

fat := n * fat(n-1);

end;

Nesta funo o identificador fat, sem qualquer cdigo ps-fixado, repre-


senta 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), pos-
sui 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 ver-
so 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 condi-
o 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, nenhu-
ma 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,
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

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.
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 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
147
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 quan-
do 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 pen-
dncias), 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 hanoi(3, 'A', 'B', 'C');
13 end.
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 mo-
dular 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 an-
terior, 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 deter-
minar 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, sig-
nifica 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.
149
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 end;
17 begin
18 busca_bin := rbusca( 0, length(L)-1 );
19 end;
20
21 const
22 M: array[0..11] of integer = (2,3,6,11,21,24,38,39,44,50,70,78);
23 var
24 x: integer;
25 begin
26 x := busca_bin(M, 11);
27 if x > 0 then
28 writeln(x)
29 else
30 writeln('nao encontrado');
31 end.

Na Listagem 49 a funo busca_bin implementa a busca binria em


Pascal. A array de busca e a chave procurada so recebidos respectivamen-
te atravs dos argumentos L e x (Linha-03). Internamente busca_bin aninha
a funo recursiva rbusca que efetua a busca propriamente dita. Os argu-
mentos de rbusca (min e max na Linha-04) representam respectivamente os
ndices em L (mdulos internos tem acesso a todos os recursos locais do
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 re-
torno imediato quando o ndice inferior (min) extrapola o superior (max). Na
Linha-09, med utilizada para calcular a posio mediana da subarray inves-
tigada (). 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 presen-
tes, 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 se-
guinte,
unit <nome_da_unidade>;

<recursos>

interface

<interfaces>

implementation

<implementaes>

end.
151
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 iden-
tificador 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 essen-
cialmente 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, ma-
nipulao de arquivos, programao web e etc).
Entretanto nem tudo que fica nessa sesso deve ser acessado por usu-
rios da unidade (imagine, por exemplo, uma funo que deva ser utilizada por ou-
tras 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.
152
RICARDO REIS PEREIRA

existem dois procedimentos implementados, mas apenas um deles est ata-


lhado 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 diret-
rio (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 progra-
mas. Exemplo,
$ fpc teste.pas

A compilao de um arquivo fonte de unidade tem como sada dois ar-


quivos 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 di-
retrio 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 pre-
cisa 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.
153
Linguagem de Programao I

A Listagem 50 mostra a implementao da unidade ncomplex que per-


mite representar e operar nmeros complexos (soma, subtrao, multiplica-
o 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.
Quando uma raiz de
nmero negativo surge
Listagem 50 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,

Ainda na Listagem 50, o procedimento init inicializa um nmero com-


plexo, que recebe por referncia no primeiro argumento, com os valores
de seus dois ltimos argumentos. As funes soma, subt, mult e quoc re-
tornam um novo complexo respectivamente igual a soma, subtrao, mul-
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 im-
plementao 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 print( quoc(a,b) );
05 init(a, 3, 2); 11 end.
06 init(b, -2, 6);

O programa da Listagem 51 ilustra o uso da unidade ncomplex impri-


mindo 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 modi-
fic-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 uti-
lizando 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.
155
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 rece-
bidos 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 calcu-
lado por mmc (a,b)= ab . 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 mdu-
los 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
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 bus-
cadas rapidamente as instrues. a chamada memria principal. A perfor-
mance 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, de-
vido 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 ope-
racional 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 me-
mria secundria toda informao visualizvel em forma de uma rvore de
diretrios e arquivos.
Um arquivo tecnicamente uma sequencia de bytes com nome pr-
prio, tamanho definido e endereo exclusivo (veja Figura - 10). Um diretrio ou
pasta um continer de arquivos e tambm de outras pastas (por isso a hie-
rarquia de dados em memria secundria anloga a uma rvore). A primeira
158
RICARDO REIS PEREIRA

Partio Lgica pasta, aquela que contm todas as demais, chamada de raiz e o conjunto
possvel aos sistemas de todas as pastas e seus respectivos arquivos, de sistema de arquivos. H
operacionais atuais definir
que parte, por exemplo,
regras para montar um sistema de arquivos e elas mudam conforme o sistema
de um disco ser utilizada. operacional e o dispositivo utilizados.
Na prtica, uma vez O mesmo dispositivo de memria secundria, como por exemplo discos
estabelecido isso, todas
as operaes de leitura
rgidos, pode inclusive possuir mais de um sistema de arquivo com mesmas
e gravao de arquivos regras ou regras diferentes. Cada fatia lgica em memria secundria, que
ocorrero nessa parte. No mantm um sistema de arquivos, denominada de partio. Usualmente as re-
existe uma barreira fsica gras de montagem de um sistema de arquivos so referenciadas simplesmente
de acesso ao restante do
disco e por essa razo diz-
como sistema de arquivos. Assim so exemplos de sistemas de arquivos o FAT
se que o particionamento e o NTFS da Microsoft, o ext3, ext4 e reiserFS do Linux e o HPFS da IBM.
lgico. Discos rgidos representam a mais comum forma de memria secund-
ria que permite o armazenamento macio de informao. Internamente eles
Para acessar informaes so formados por discos magnticos rgidos (da a origem do nome) fixos a
num dispositivo de um eixo central que gira em uma alta velocidade sobre um mancal de preci-
armazenamento primrio so. Um brao mecnico, com liberdade angular de movimentao, mantm
ou secundrio necessrio
inicialmente deslocar-
diversas extenses com agulhas magnetizadas que interagem com a superf-
se at o endereo onde cie de cada uma das faces dos discos rgidos efetuando operaes de leitura
fica o dado pretendido e gravao.
e s ento efetuar a
leitura e/ou gravao.
Essa parafernlia justifica a lentido das operaes em discos rgidos,
Em alguns hardwares pelo menos quando comparadas quelas em memria principal (que devido
esse deslocamento a volatilidade, dispensa partes mecnicas). Apesar disso ainda representam
instantneo, mas em a melhor opo para armazenamento macio no voltil no que diz respeito
outros toma um tempo
considervel. Essa
a anlise custo versus quantidade de memria versus velocidade de acesso.
disparidade ocorre devido
a presena de partes Tamanho do Arquivo
mveis no segundo caso
(inrcia de dispositivo).
Assim os dispositivos do
Memria Arquivo
primeiro caso esto haptos
Endereo do incio do arquivo
ao acesso aleatrio, ou
seja, acesso a qualquer
parte do disco em qualquer
tempo enquanto os da H dispositivos de memria secundria de acesso aleatrio e de aces-
segunda categoria so so sequencial. Nos dispositivos de acesso aleatrio, como os discos rgidos, o
melhores aproveitados tempo de acesso a blocos fundamentais de bytes ocorre num tempo aproxima-
no acesso sequencial, ou damente constante definido pelo fabricante, mas que ir variar de modelo para
seja, ao invs de saltar
entre dados distantes modelo. Nos dispositivos de acesso sequencial, como as fitas magnticas, o
mais interessante efetuar tempo de acesso a blocos fundamentais de bytes muda consideravelmente.
acessos seguidos a clulas Nestes dispositivos uma agulha magnetizada de leitura fica fixa enquan-
sequenciais minimizando o
efeito do deslocamento.
to 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
159
Linguagem de Programao I

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


tornam mais interessantes para operaes de gravao sequencial de gran-
des quantidades de dados como em backups (cpias de segurana).
Um sistema de manipulao de arquivos, em uma linguagem de pro-
gramao, um conjunto de recursos que permite criar, modificar ou excluir
arquivos de um sistema de arquivos. Tais sistemas devem manter uma cama-
da 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 pro-
priamente 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 pou-
cos 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
Salvar um documento,
Pascal possui mais de um sistema de manipulao de arquivos. O mais uma imagem, uma
comumente abordado aquele mantido pela unidade system e que ser estu- planinha, um desenho
e etc, utilizando uma
dado neste captulo. A unidade sysutils possui um sistema de manipulao de
aplicao especializada,
arquivos alternativo semelhante ao da linguagem C. constitui uma tarefa de
descarregamento forado
da memria principal para
2. Fluxos a secundria.

Em Pascal os arquivos so classificados em binrios e de texto. Um arquivo


binrio aquele gerado pela concatenao de dados provenientes diretamen-
te 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 neces-
sariamente de mesmo tipo ou tamanho. Um arquivo texto aquele constitudo
exclusivamente por caracteres visveis (da tabela ASCII) e comummente re-
presentam algum tipo de documentao. Eles requerem processamento adi-
cional para serem gerados, ou seja, os dados em memria, que precisam ser
gravados num arquivo texto, precisam ser primeiramente transformados do
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 mani-
pulador. 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,
var
Na maioria dos sistemas
<manipulador>: text;
um nome de arquivo
construdo pela sequncia onde text uma palavra reservada que significa texto. No exemplo,
das pastas que se
var
sucedem hierarquicamente
desde a raiz at o nome T: text;
propriamente dito do
T define um manipulador para um fluxo de arquivo texto.
arquivo. No Linux, e
demais sistemas baseados Um fluxo, depois de definido, precisa ser vinculado a um arquivo (que
no Unix, estas pastas so necessariamente no precisa existir ainda) em um dispositivo real (como um
separadas pelo caractere
disco). Esta vinculao realizada pelo comando assign cuja sintaxe ,
barra comum, /, como no
exemplo /temp/data/teste. assign(<fluxo>, <nome_do_arquivo_no_dispositivo_real>);
dat. No Windows a raiz
O primeiro argumento uma referncia a um fluxo que deve ser vincula-
de cada partio recebe
uma letra e utiliza-se barra do a um arquivo cujo nome o segundo argumento. Um nome de arquivo em
invertida, \ para separar geral segue as regras de endereamento de arquivos do sistema operacional
as pastas. Um exemplo onde o programa compilado. Se o arquivo aberto ou criado na mesma pas-
equivalente ao anterior
ta do binrio executvel, no necessrio detalhar o endereo com hierarquia
c:\temp\data\teste.dat.
de pastas, como em,
161
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 Incio do Arquivo


(Posio zero)

Posio dois
000110010111101111001000000011100011011101010100

Posio trs
000110010111101111001000000011100011011101010100

Final do Arquivo
000110010111101111001000000011100011011101010100

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 arqui-
vo. O modo de um arquivo define basicamente o suporte s operaes de
leitura (verificao dos dados que ele contm) e escrita (adio de novos da-
dos 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
162
RICARDO REIS PEREIRA

No modo de escrita, para fluxos de texto, ser permitida apenas a gra-


vao 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 arqui-
vos 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 no-
vas operaes agreguem novos dados e no sobrescrevam os que j exis-
tem. 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.


163
Linguagem de Programao I

Nem sempre possvel abrir um arquivo. Quando este for o caso en-
to 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 desa-
bilitao a necessidade de checar manualmente se ocorreu silenciosamen-
te 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 arqui-
vos. 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 imple-
mentadas na expresso booleana da Linha-08 cujo valor atribudo a varivel
interna existe (retorno da funo).
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 me-


mria 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 aber-
to. No exemplo,
165
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 pa-
dro 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 deve-
ro ser copiados, sem processamento adicional, para o arquivo vinculado ao
fluxo no primeiro argumento. Detalhes de formatao, como espaos, tabula-
es, novas linhas ou controle de casas decimais no possuem funcionalida-
de 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, escre-
ver continuamente dados para o final do arquivo mantm a posio corrente
sempre no final. No programa da Listagem 53 100 valores inteiros so gera-
dos 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 itera-
o no haver sobreposio, mas sim concatenao do novo inteiro.
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.

Para verificar ou modificar manualmente a posio corrente de um ar-


Os comandos ramdomize
e random, unidade system, quivo, a unidade system dispe os comandos a seguir,
so utilizados para gerar
nmeros pseudo aleatrios
eof Abreviao de end of file (fim de arquivo). Recebe um fluxo como
em Pascal. ramdomize argumento e retorna verdadeiro se a posio corrente atingiu o
um procedimento sem final do arquivo vinculado. Do contrrio retorna falso.
argumentos que deve ser filepos Recebe um fluxo e retorna o valor da posio corrente (int64) do
chamado uma nica vez arquivo vinculado.
antes de chamadas futuras seek Modifica a posio corrente do arquivo cujo fluxo passado como
a random para possibilitar primeiro argumento. A nova posio (int64) dada como segundo
argumento.
o mximo de aleatoriedade
possvel. As chamadas
a random requerem um
ou nenhum argumento e Para ler o contedo do arquivo gerado pelo programa da Listagem-6.2,
retornam nmeros pseudo construiu-se o programa da Listagem 54. Neste novo programa reset, na
aleatrios. Quando no h Linha-07, acessa o arquivo em disco e define a posio corrente para o incio
argumento o valor pseudo
do arquivo. O lao while da Linha-08 utiliza eof para examinar sucessivamente
aleatrio gerado real e
est entre 0.0 e 1.0. Se o se a posio corrente de f j atingiu o fim do arquivo. As chamadas a read,
argumento existe, ele deve Linha-09, fazem tanto a varivel i assumir em cada iterao do lao cada um
ser um inteiro n e a sada dos inteiros armazenados no arquivo quanto avanar automaticamente a po-
gerada um inteiro entre 0
sio corrente. Cada valor de inteiro lido atravs de i impresso pelo lao em
e n-1.
sada padro (Linha-10).
167
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);
03 f: file of integer; 10 write(i, ' ');
04 i: integer; 11 end;
05 begin 12 close(f);
06 assign(f, 'teste.dat'); 13 end.
07 reset(f);

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 ar-
quivo 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 ar-
quivo 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 quadra-
gsima posio do arquivo com fluxo F. O tamanho do arquivo no modifi-
cado e a posio corrente final a quadragsima primeira.
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 tmp, a: integer;
04 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 compor-


tamento 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
169
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 re-
gistro 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 vincula-
do 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 vin-


culado 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
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 mes-
mo 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 a, b: integer; 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 end;
171
Linguagem de Programao I

O procedimento da Listagem 56 implementa a movimentao com remo-


o 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 en-
tre 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);
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 arqui-
vo texto efetua em bastidores uma converso de dados para o formato texto
(string) antes da impresso propriamente dita. A gravao feita pelos co-
mandos 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|
173
Linguagem de Programao I

Observe que o ponto (.) tambm entra na contagem do total de ca-


racteres 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.
Este programa gera um arquivo de texto chamado saida.txt cujo contedo ,
123 0.27200 Ola mundo!!

writeln insere adicionalmente um caractere de nova linha. Assim uma anexa-


o 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);
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 writeln(F, nome:25, idade:3, media:5:1);
16 end;
17
18 var s: string;
19 i: byte;
20 m: real;
21 ch: char;
22 begin
23 repeat
24 write('Nome> '); readln(s);
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 until (ch='n') or (ch='N');
31 end.
175
Linguagem de Programao I

O programa da Listagem 57 ilustra a insero de dados num arqui-


vo texto chamado aluno.txt. Cada linha do arquivo deve conter sequen-
cialmente 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 fno-
me), 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 ar-
quivo base (Linhas 06 a 09). Caso ele exista, aberto em modo de
anexao (Linha-11) seno ele criado (Linha-13). A insero de da-
dos 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 con-
tinuar dependendo do valor que fornecer a ch (Linhas 29 e 30). Um as-
pecto 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 bin-
rios (a sintaxe equivalente). No exemplo,
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 nme-
ros. Para trazer dados de volta a formatos como real ou integer o pro-
gramador 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.
177
Linguagem de Programao I

Sntese da Parte 3
No Captulo 1 foi estudada a modularizao que incluiu noes so-
bre controle de execuo em um processo monothread, aspectos so-
bre a passagem de argumentos em procedimentos e funes, noes
sobre uso e aplicaes da recursividade, a importncia do aninha-
mento modular e por fim a compilao de mdulos afins numa uni-
dade Pascal. No Captulo 2 foi estudado o sistema padro de ma-
nipulao de arquivos da Linguagem Pascal incluindo a noo de
fluxo de informaes entre memria principal e secundria. Os prin-
cipais comandos desde sistema foram apresentados convenientemen-
te 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 proble-
ma-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 da-
dos, 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 re-
gistro para o fim do arquivo e depois elimin-lo por truncamento.
Reconstruir o procedimento de forma que seja possvel movimentar
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 regis-
tro (remover um aluno).

Referncias
CANNEYT , Michal Van, Reference guide for Free Pascal, Document
version 2.4 , March 2010
http://www.freepascal.org/docs-html/
179
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 discipli-
nas 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.
Computao

Linguagem de Programao I
iel a sua misso de interiorizar o ensino superior no estado Cear, a UECE,
como uma instituio que participa do Sistema Universidade Aberta do

Computao
Brasil, vem ampliando a oferta de cursos de graduao e ps-graduao
na modalidade de educao a distncia, e gerando experincias e possibili-
dades inovadoras com uso das novas plataformas tecnolgicas decorren-
tes da popularizao da internet, funcionamento do cinturo digital e
massificao dos computadores pessoais.

Linguagem de Programao I
Comprometida com a formao de professores em todos os nveis e
a qualificao dos servidores pblicos para bem servir ao Estado,
os cursos da UAB/UECE atendem aos padres de qualidade
estabelecidos pelos normativos legais do Governo Fede-
ral e se articulam com as demandas de desenvolvi-
mento das regies do Cear.

Ricardo Reis Pereira

Universidade Estadual do Cear - Universidade Aberta do Brasil


Geografia

12

Histria

Educao
Fsica

Cincias Artes
Qumica Biolgicas Plsticas Computao Fsica Matemtica Pedagogia