Vous êtes sur la page 1sur 168

Sum rio a

1 Introducao a Computacao ` 1.1 1.2 1.3 1.4 1.5 Organizac ao do Computador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alguns Termos T cnicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Bits e Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Base Bin ria, Base Decimal, ... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a Algebra Booleana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 2 4 5 7 9 11 12 13 15 17 19 20 22 23 25 25 25 26 27 29 31 31 34 36 39 40 40 42 47 49 50 53

2 Primeiros Programas em Pascal 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 Coment rios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a Identicadores e Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vari veis e Tipos B sicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a a Comando de Atribuicao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Algumas Funcoes Pr -Denidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Comandos de Escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comandos de Leitura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tipos Escalares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Estrutura Condicional 3.1 3.2 3.3 3.4 3.5 Estrutura Condicional Simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Estrutura Condicional Composta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bloco de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comando Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Estruturas de Repeticao 4.1 4.2 4.3 4.4 Comando For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comando While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comando Repeat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 Desenvolvendo Programas 5.1 5.2 5.3 5.4 5.5 5.6 Programacao por Etapas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simulacao de programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alinhamento de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Desenvolvimento de Algoritmos Ecientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Precis o Num rica e Erros de Precis o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a e a Tipos denidos pelo programador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

6 Vari veis Compostas Homog neas a e 6.1 6.2 6.3 Vetores Unidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vetores Multidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55 55 63 64 66 66 67 71 73 76 77 80 82 83 84 87 89 91 91 94 97 98 100

7 Procedimentos e Funcoes 7.1 7.2 7.3 7.4 7.5 7.6 Procedimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passagem de Par metros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a Funcoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Escopo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cuidados na Modularizac ao de Programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 Processamento de Cadeias de Caracteres 8.1 8.2 8.3 8.4 8.5 Letras com Ac ntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Transformac ao entre Mai sculas e Min sculas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u u Casamento de Padr es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o Criptograa por Substituic oes - Cifra de C sar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9 Vari veis Compostas Heterog neas - Registros a e 9.1 9.2 9.3 9.4 Registros Fixos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Registros Variantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comando With . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10 Recursividade

10.1 Projeto por Inducao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 10.2 Garantindo n mero nito de chamadas recursivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 u 10.3 Torres de Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 10.4 Quando n o usar recurs o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 a a 10.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 11 Algoritmos de Ordenacao 110

11.1 Algoritmo InsertionSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 11.2 Algoritmo MergeSort e Projeto por Divis o e Conquista . . . . . . . . . . . . . . . . . . . . . . . . . 111 a 11.3 Algoritmo QuickSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 11.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 12 Passagem de funcoes e procedimentos como par metros a 118

12.1 Diferencas entre Borland/Turbo Pascal e Extended Pascal . . . . . . . . . . . . . . . . . . . . . . . . 118 iv

12.2 M todo de bissec ao para encontrar razes de funcoes . . . . . . . . . . . . . . . . . . . . . . . . . . 120 e 12.3 Ordenacao usando funcoes de comparacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 12.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 13 Arquivos 126

13.1 Arquivos Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 13.2 Arquivos Bin rios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 a 13.3 Outras funcoes e procedimentos para manipulac ao de arquivos . . . . . . . . . . . . . . . . . . . . . 136 13.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14 Figuras e Gr cos a 139

14.1 Usando o formato PPM Portable PixMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.2 Retas e Crculos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 14.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 15 Ponteiros 146

15.1 Alocacao Din mica de Mem ria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 a o 15.2 Listas Ligadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 15.3 Recursividade e Tipos Recursivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 15.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 16 Usando e Construindo Biblioteca de Rotinas 157

16.1 Estrutura de uma unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 16.2 Usando Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 16.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Indice Remissivo 162

vi

1 Introducao a Computacao `
1.1 Organizacao do Computador
Um computador e uma colecao de componentes que realizam operacoes l gicas e aritm ticas sobre um grande volume o e de dados. Na gura 1 apresentamos uma organizac ao b sica em um computador seq encial. a u

Unidade Central de Processamento


Memria RAM Unidades de Entrada Memria ROM

Unidade de Controle
Memrias Secundrias Memria Cache Registradores

Unidades de Sada

Unidade Lgica e Aritmtica

Figura 1: Organizacao B sica de um Computador Seq encial. a u A seguir descreveremos cada uma destas partes. Unidade de Entrada S o os componentes que permitem a entrada de informacoes exteriores para serem processadas a pelo computador. Exemplo: teclado, mouse, c mera de vdeo, etc. a Unidade de Sada S o os componentes que permitem a apresentac oes de informacoes processadas para o meio exter a no. Exemplo: monitor, impressora, etc. Unidade Central de Processamento Tamb m conhecida como CPU (Central Processing Unit). E respons vel pela e a capaz de fazer contas maexecucao dos programas e pelo comportamento das outras unidades no sistema. E tem ticas e fazer decis es simples. As principais partes da CPU s o: a Unidade L gica e Aritm tica, Unidade a o a o e de Controle e Mem rias (Registradores, Mem ria Principal (ou Mem ria RAM), Mem ria ROM e Cache). o o o o Unidade L gica e Aritm tica Parte da CPU que realiza operacoes aritm ticas (soma, subtrac ao, multiplicac ao, dio e e vis o, resto, troca de sinal, etc) e operacoes l gicas (and, or, not, xor, etc). a o Mem ria Principal E usado na CPU para manter instrucoes e dados. Tamb m conhecido como Mem ria RAM o e o (Random Access Memory). A recuperac ao dos dados e feita atrav s de circuitos l gicos e por isso e r pida. N o e o a a e t o grande, j que depende muito da tecnologia de integrac ao destes circuitos. E uma mem ria vol til, i.e., a a o a quando o computador e desligado, todos os dados nesta mem ria se perdem. o Mem ria ROM ROM (Read Only Memory) e uma mem ria que cont m dados e c digos de execucao que n o podem o o e o a ser alterados. Uma das aplicac oes desta mem ria e manter c digo de execucao para a leitura e execucao de um o o sistema operacional. Mem ria Cache Mem ria r pida projetada para guardar dados que foram recentemente acessados. Para buscar um o o a certo dado na mem ria RAM, e considerado se este pode estar na mem ria cache, e em caso positivo a busca na o o mem ria RAM e interrompido e este e recuperado diretamente da mem ria cache. Tem tempo de acesso mais o o r pido que a mem ria RAM. a o Registradores Mem rias de alta velocidade ligada a operacoes de c lculos l gicos e aritm ticos. Em geral em quano a o e tidade e tamanhos pequenos. Unidade de Controle Parte da CPU que busca na mem ria a pr xima instrucao e a decodica para ser executada. o o Dependendo da instrucao, pode-se ter uma transfer ncia do controle para a unidade l gica e aritm tica ou o e o e envio de dados para os componentes externos a CPU. ` 1

Mem ria Secund ria Mem ria para armazenamento a longo prazo. Os dados armazenados nesta mem ria n o s o o a o o a a perdidos quando se desliga o computador. Em geral de dimens es maiores que a Mem ria RAM mas de acesso o o mais lento, j que envolvem o uso de dispositivos mec nicos. Ex. Discos rgidos, disquetes, tas magn ticas, a a e etc. Podemos ver que h diversos tipos de mem rias em um computador. Cada uma destas mem rias usa tecnologia que a o o reete no custo, na velocidade de acesso e na quantidade de armazenamento. A seguinte ordem apresenta algumas mem rias ordenadas, de maneira crescente, pela quantidade de armazenamento: o Registrador Mem ria Cache Mem ria RAM Discos Rgidos. o o Esta mesma ordem apresenta o custo relativo e a velocidade de maneira decrescente.

1.2 Alguns Termos T cnicos e


Hardware Componentes mec nicos e eletro- eletr nicos que comp em o computador. Parte dura do computador. a o o Software Seq encia de instrucoes e comandos que fazem o computador realizar determinada tarefa., tamb m chamau e dos de programas de computador. Devem estar armazenados em algum tipo de mem ria. o Perif rico E qualquer componente do computador (hardware) que n o seja a CPU. Exemplos: leitoras de disquete, e a monitores, teclados, vdeo, impressoras, etc. Sistema Operacional Colecao de programas que gerencia e aloca recursos de hardware e software. Exemplos de tarefas que um sistema operacional realiza s o: leitura de dados pelo teclado, impress o de informac oes no a a vdeo, gerenciamento da execucao de v rios programas pela CPU, gerenciamento da mem ria principal e da a o mem ria secund ria para uso dos programas em execucao, etc. Exemplos: Linux, Unix, Windows98, OS2, o a MS-DOS, etc. Linguagem de M quina Conjunto de instruc oes que podem ser interpretados e executados diretamente pela CPU de a um dado computador. E especca para cada computador. Linguagem Assembler (Linguagem de Baixo Nvel) Representac ao da linguagem de m guina atrav s de c digos a e o mnem nicos. Tamb m e especca de cada m quina. o e a Linguagem de alto nvel Linguagem que independe do conjunto de instruc oes da linguagem de m quina do compu a tador. Cada instrucao de alto nvel equivale a v rias instrucoes da linguagem de m quina, sendo assim mais a a produtiva. Ex.: Pascal, C, Algol, BASIC, Lisp, Prolog, etc. Compilador Tradutor de programas escritos em uma linguagem de programacao para programas em linguagem de m quina. Uma vez que o programa foi convertido para c digo de m quina, este pode ser executado independente a o a do compilador e do programa original. Veja a gura 2.

Programa Fonte

Compilador

Programa Executvel

Programa Executvel

Sistema Operacional

CPU

Sistema Operacional

CPU

(a) Gerao do Programa Executvel

(b) Execuo do Programa

Figura 2: Etapas para execucao de um programa compilado. Interpretador E um programa que executa outros programas escritos em alguma linguagem de programac ao. A execucao de um programa interpretado e em geral mais lenta que o programa compilado. Por outro lado, o uso de programas interpretados permite que trechos de c digos possam ser trocados por novos facilmente, fazendo com o 2

que o programa fonte possa mudar durante sua execucao. Este e um dos grandes motivos de se usar programas interpretados em sistemas especialistas. Duas linguagens para as quais podemos encontrar interpretadores s o a Lisp e Prolog. Veja a gura 3.

Programa Fonte

Interpretador

Sistema Operacional

CPU

Execuo de programa interpretado


Figura 3: Execucao de um programa interpretado. Algoritmo E a descric ao de uma seq encia de acoes para realizar alguma tarefa. Em geral, estaremos interessados u em algoritmos computacionais, que descrevem uma seq encia de acoes que podem ser traduzidos para alguma u linguagem de programac ao. Uma maneira para calcular o MDC (M ximo Divisor Comum) de dois n meros inteiros positivos a u do Algoritmo de Euclides apresentado no quadro seguinte.

e e atrav s e

Passo 1: Passo 2: Passo 3: Passo 4:

Adote e ; Adote (resto de dividido por ); e ; Adote novos valores Se e diferente de , volte ao passo 2; sen o pare com a resposta . a

Algoritmo de Euclides O seguinte programa apresenta uma vers o mais estilizada: a Passo1: Passo2: Passo3: Passo4: Passo4.1: Passo4.2: Passo4.3: Passo4.4: Passo5:

. .
Repita

Dados:

e .

; ; ; At que . e Imprima o resultado .


Algoritmo de Euclides Estilizado.

O seguinte programa apresenta uma vers o na linguagem Pascal: a

Program Euclides; integer; var begin Readln(m,n); ; ; repeat

; until writeln( );

; ;

end. Implementacao do Algoritmo de Euclides em Pascal

1.3 Bits e Bytes


A menor unidade de informacao usada pelo computador e o bit. Este tem atribuic oes l gicas 0 ou 1. Cada um destes o estados pode, internamente, ser representado por meios eletro-magn ticos (negativo/positivo, ligado/desligado, etc). e E por isso que e mais f cil para armazenar dados em formato bin rio. Assim, todos os dados do computador s o a a a representados de forma bin ria. Mesmo os n meros s o comumente representados na base 2, em vez da base 10, e a u a suas operacoes s o feitas na base 2. a Um conjunto de 8 bits e chamado de byte. Um byte pode ter at e conguracoes diferentes. O princi pal padr o usado para representar caracteres (a,b,c,...,A,B,C,...,!,@,#,$,...) e o padr o ASCII (American a a Standard Code for Information Interchange), usada na maioria dos computadores. Cada um destes caracteres e repre sentado por um byte. A tabela 1 apresenta o c digo de alguns caracteres no c digo ASCII: Observe que: o o 1. As codicacoes para letras em mai sculas e min sculas s o diferentes. u u a 2. A codicacao de B e a codicacao de A somado de 1; a codicacao de C e a codicacao de B somado de 1; assim por diante. Esta codicacao permite poder comparar facilmente se um caracter vem antes do outro ou n o. Internamente, vericar se o caracter a vem antes do b, e vericar se o n mero bin rio correspondente a a u a a e menor que o n mero bin rio correspondente a b. u a 3. As letras mai sculas vem antes das min sculas. u u As seguintes denominac oes s o comumente usadas na area de inform tica a a nome bit byte kilobyte (kbyte) megabyte gigabyte mem ria o

8 bits bytes (pouco mais de mil bytes ( )) bytes (pouco mais de um milh o de bytes) a bytes (pouco mais de um bilh o de bytes) a

Atualmente, congurac oes de computador com 64 megabytes de mem ria RAM, 4,2 gigabytes de disco rgido, o disco exivel de 1,44 megabytes s o muito comuns no mercado. Certamente esta conguracao j ser considerada a a a pequena dentro de um ou dois anos, devido ao contnuo avanco da tecnologia nesta area. Vejamos alguns exemplos de quanto e esta mem ria. Uma p gina de um livro, armazenada em formato ASCII, o a tem em torno de 50 linhas e 80 caracteres por linha. Assim, um livro de 1000 p ginas teria algo em torno de 4.000.000 a de caracteres, que poderiam ser guardados em 4 megabytes. Assim, um disco rgido de 4,2 gigabytes poderia guardar 4

Caracter Representac ao em ASCII Valor na base decimal . . . . . . . . .


. . .


. . .


. . . . . . . . . . . .

. . .

. . .

. . .

. . .

. . .

. . .

Tabela 1: em torno de 1.000 livros deste tipo. Isto aparenta uma quantidade bastante grande de dados. Por outro lado, a maioria das aplicacoes atuais est fazendo uso cada vez maior de imagens, gr cos e sons. Estas aplicac oes demandam muita a a mem ria. Por exemplo, se voc quiser representar uma imagem de tamanho 1000 1000 pontos ( pontos), cada o e ponto com uma cor entre 65000 cores possveis (dois bytes por ponto), gastaremos algo como 2 megabytes para armazenar apenas uma imagem deste tipo. A quantidade de mem ria aumenta quando armazenamos lmes, que o usam em torno de 30 imagens por segundo. Apesar do uso de m todos de compress o sobre estes tipos de dados a e a necessidade de grande quantidade de mem ria ainda e crucial para muitas aplicacoes. o

1.4 Base Bin ria, Base Decimal, ... a


Como vimos, e muito mais f cil armazenar os dados na base bin ria que na base decimal. Assim, muitas das operac oes a a usadas no computador s o feitas na base bin ria. a a Muito provavelmente, n s usamos a base decimal porque temos 10 dedos nas duas m os. E se tiv ssemos 8 dedos o a e em vez de 10 ? Neste caso, provavelmente estaramos usando a base octal. Bom, agora imagine que voc tem apenas e dois dedos. Neste raciocnio, usaremos o sistema bin rio !! a Primeiro, vamos lembrar o que representa o n mero 4027 na base decimal. u

Agora um n mero bin rio tem apenas os dgitos 0 e 1. O n mero no sistema bin rio representa o n mero: u a u a u

Isto nos d o n mero a u

Assim o n mero no sistema bin rio e igual ao n mero 38 no sistema decimal. u a u As operacoes aritm ticas tamb m podem ser feitas em bin rio. Por exemplo: Vamos somar o n mero acima e e a u ( ) com ( ).

Agora vamos conferir o resultado: est correto. Em decimal seria a

. E

. De fato, este n mero u

Exerccio 1.1 Dado um n mero no sistema decimal, encontre uma maneira de escrev -lo no sistema bin rio. u e a Exerccio 1.2 Como seria a multiplicacao de dois n meros no sistema bin rio ? u a Assim, em um byte (8 bits), e possvel representar os n meros de at u e bin rio a (

).


. . .

decimal


. . .

Da mesma forma, em dois bytes (16 bits) e possvel representar os n meros de at u e

Muitas vezes um compilador (ou mesmo o pr prio computador) tem uma estrutura para denir sinais (se negativo o ou positivo). Um exemplo disso e usar um bit para representar o sinal do n mero. Por exemplo, um n mero de 16 bits pode ter u u a representac ao interna com um bit para sinal e os outros 15 bits para o n mero propriamente dito. Neste exemplo, u poderamos representar n meros de u at (i.e., de at ). Note que neste exemplo o e e n mero e representado duas vezes ( e ). Na pr tica, as representac oes internas levam isto em considerac ao de u a at . e forma que cada n mero e representado apenas uma vez, neste caso podendo ir de u

E interessante observar que n meros positivos n o nulos que s o pot ncia de 2 s o n meros que t m todos os bits u a a e a u e iguais a 0, exceto um bit. Assim, a multiplicac ao de um n mero inteiro por um inteiro positivo n o nulo que e u a pot ncia de 2 faz apenas um deslocamento dos bits de de algumas casas. Por exemplo, a multiplicac ao de por 8 e ( ) faz o deslocamento dos bits de de 3 casas para a esquerda.

Assim, muitos compiladores, ao encontrar a multiplicac ao de um inteiro por uma pot ncia de 2, trocam esta e multiplicac ao por um deslocamento de bits. Quando a operacao e para obter a parte inteira da divis o de um inteiro por uma pot ncia de dois, digamos , a e basta deslocar os bits de de casas para a direita, perdendo bits que est o mais a direita. a

Tamb m e sabido que a multiplicac ao de inteiros em geral leva mais tempo que somas e deslocamento de bits. Ase sim, uma possvel otimizacao feita por compiladores e trocar a multiplicac ao de um inteiro por somas e deslocamento 6

de bits. Por exemplo, digamos que desejamos obter . O inteiro 10 n o e pot ncia de 2, mas em vez de fazermos a e . I.e., podemos fazer . a multiplicac ao por 10, podemos reescrever esta multiplicac ao por Desta maneira trocamos uma multiplicac ao de um inteiro por dois deslocamentos e uma soma, o que em muitos com putadores e feito de forma mais r pida que uma multiplicac ao direta. Obs.: E possvel mostrar que podemos fazer a a multiplicac ao , onde e inteiro e e uma constante inteira aplicando este m todo fazendo no m ximo e a somas, onde e a constante inteira a multiplicar.

Outro sistema muito usado na literatura e a base (hexadecimal). Neste sistema temos 16 dgitos usados na seguinte ordem: 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , A , B , C , D , E , F . Assim, o n mero (F+1) e igual a 10 (10 em hexadecimal e igual a 16 no sistema decimal). u Exerccio 1.3 Quanto e A9B em decimal ?

1.5 Algebra Booleana


Alguns comandos de programac ao est o estreitamente relacionados com um sistema de algebra, chamado algebra a de boole, desenvolvido por George Boole. Neste tipo de algebra podemos operar sobre proposic oes que podem ser verdadeiras ou falsas, resultando em um resultado que tamb m e verdadeiro ou falso. Em 1930, Turing mostrou que e tr s funcoes l gicas (e (and), ou (or) e n o (not)) s o sucientes para representar estas proposic oes l gicas. Uma das e o a a o principais vantagens deste tipo de algebra e que ela pode ser implementada ecientemente atrav s de componentes e eletr nicos. o Usando as letras F como falso e V como verdadeiro, apresentamos na tabela 2 os valores para as funcoes (and), or e not.

and

or

not

Tabela 2: Funcoes booleanas and, or e not. Com estas tr s funcoes podemos construir funcoes mais complexas. Por exemplo, considere vari veis booleanas e a e , e uma funcao booleana que assume os valores conforme a tabela a seguir.

Para construir a funcao , podemos considerar a tabela acima, com todas as entradas possveis de e , e construir como uma seq encia de cl usulas ligadas pela funcao or. Cada cl usula corresponde a uma entrada u a a verdadeira para a funcao , feita com as funcoes and e not. No exemplo acima, a funcao pode ser escrita como:

Exerccio 1.4 Construa uma f rmula booleana para a seguinte funcao o


x y

dada pela seguinte tabela:

Exerccio 1.5 Um aluno do curso de Algoritmos e Programacao de Computadores vai de sua casa para a escola a p . e Considere , , e sentencas booleanas representando as condicoes em um dia que ele vai para a aula e uma f rmula booleana representando a chegada do aluno a aula sem problemas. o `

(Est chovendo); a (Tenho guarda-chuva); (Tenho carona); (Estou atrasado); (Vou para a aula sem problemas).
Construa uma f rmula booleana adequada para o com os valores da f rmula o .

e construa a tabela com os valores possveis de , , e

2 Primeiros Programas em Pascal


Apesar da metodologia de uxogramas ser antiga, ela ainda e muito usada para explicar o seq encia de instruc oes u em programas e algoritmos. H v rios smbolos que fazem parte de um uxograma. Para n s, este tipo de estrutura a a o ser importante apenas para representar a estrutura seq encial dos algoritmos e programas de computador. Em um a u uxograma, um passo ou m dulo e representado por um ret ngulo. As setas indicam o pr ximo comando a ser o a o executado. Um losango indica uma condicao e conforme a condic ao seja satisfeita ou n o, este pode levar a um de a dois outros comandos. Na gura 4 apresentamos alguns diagramas usados em uxogramas.

ESTRUTURA DE CONTROLE SEQENCIAL

ESTRUTURA DE CONTROLE CONDICIONAL

ESTRUTURA DE CONTROLE REPETITIVA

Figura 4: Exemplo de estruturas de controle usadas em programacao estruturada. Suponha que exista um curso cuja avaliacao seja feita atrav s de duas provas e um exame, sendo que o resultado e nal seja dado pela seguintes regras: A primeira prova tem peso 2 e a segunda prova tem peso 3. Seja a m dia e ponderada destas duas provas. Caso seja pelo menos 5.0, a nota nal do aluno, , e igual a . Caso contr rio, o a e e aluno deve fazer o exame, digamos com nota , e sua nota nal, e a m dia aritm tica entre e . Por m, caso a nota nal do aluno seja pelo menos , o aluno est aprovado, caso contr rio, o aluno est reprovado. A gura 5 apresenta a a a um exemplo de uxograma para se avaliar um aluno de tal curso.

No incio dos tempos da programac ao de computadores, viu-se que programas que continham quaisquer desvios, de um comando para outro, eram muito mais difceis de se entender. Os programas mais f ceis de entender eram aqueles a onde o uxograma n o tinha setas se cruzando. Provavelmente e esta liberdade que faz com que o uxograma deva a ser considerado com muito cuidado e por isso mesmo esteja em desuso. Um algoritmo descrito como um uxograma pode ter setas levando para qualquer lugar do programa, podendo o tornar muito confuso e sem nenhuma organizac ao. As linguagens estruturadas fornecem um n mero limitado de estruturas de controle. Tais estruturas de controle u foram desenvolvidas de tal forma que o uxo de execucao n o possa ser de qualquer maneira, mas sim de forma a bem organizada. Uma representac ao de um programa que usa estas estruturas de controle permite uma traducao para uxogramas sem que haja linhas se cruzando. Desta forma a manutenc ao de um programa ca menos difcil, mesmo que isso seja feito por outra pessoa que n o aquela que o implementou inicialmente. A linguagem Pascal e uma a linguagem de alto nvel onde as t cnicas de programac ao estruturadas s o estimuladas atrav s de seus comandos. e a e Um programa em Pascal tem o seguinte formato: program nome; declaracoes Area de Declaracoes begin Comandos Corpo de Execucao do Programa Principal end. As palavras program, begin e end s o palavras-chave da linguagem Pascal. S o palavras reservadas que fazem a a parte da sintaxe da linguagem e n o podem ser usadas para declarar os objetos denidos pelo programador. As palavras a begin e end servem para denir um bloco de instruc oes, no caso, denem o corpo de execucao do programa principal. Na area de declarac oes, s o denidos os objetos que iremos usar no programa, que inclui objetos que representam a outros trechos de c digo. o

INICIO CURSO

N1

Fazer prova 1 Nota da Prova

N2

Fazer prova 2 Nota da Prova

2.N1 + 3.N2 5

N Maior que 5.0 ? S F N

N E

Fazer Exame Nota do Exame

N+E 2

F Maior que 5.0 ? S APROVOU-SE NO CURSO

REPROVOU-SE NO CURSO

Figura 5: Fluxograma de avaliac ao de um curso. Na gura 6 apresentamos um programa bem simples com apenas um comando de execucao. program BomDia; begin writeln(Bom Dia!); end. Figura 6: O Comando writeln na gura 6 escreve o texto Bom Dia! no dispositivo de sada. Depois de escrever o texto, o programa ainda pula uma linha. Existe tamb m um outro comando, write, para imprimir um texto sem pular linha. Assim, um programa equivae lente ao programa BomDia pode ser dado na gura 7: program BomDia2; begin write(Bom ); writeln(Dia!) end. Figura 7: Note que h um espaco em branco depois de Bom, pois caso n o tivesse, as palavras Bom e Dia seriam impressas a a juntas (BomDia). 10

program BomDia1; begin write ( Bom ) ; writeln ( Dia!); end. Figura 8: Programa desorganizado Observacoes 1. O ; (ponto e vrgula) serve para separar comandos. Obs.: Dois ponto e vrgula seguidos separam um comando vazio. 2. A execucao do programa est denida pelos comandos entre begin e end. Note que logo ap s a palavra end a o segue um . (ponto nal). 3. Comandos que s o separados por espacos em branco n o fazem diferenc a. Na verdade, cada item do programa a a pode ser separado: Assim, o programa BomDia poderia ter sido escrito como dado na gura 8. E claro que o programa ca bem mais legvel na primeira forma.

2.1 Coment rios a


Dentro de um programa, descrito em Pascal podemos ter textos que n o s o considerados para a geracao do c digo de a a o m quina e servem para ajudar a compreens o do programa ou apenas como coment rios. a a a Coment rios em Pascal podem ser inseridos colocando-os entre (* e *) ou colocando-os entre e . a Assim, o programa BomDia2 (gura 9) abaixo e equivalente aos dois programas acima. Programa: BomDia.Pas Aluno: Fulano de Tal RA: 999999 Curso: MC102 Data: 01/01/01 Descricao: Programa para Imprimir Bom Dia! program BomDia2; Programa para Imprimir Bom Dia! begin write(Bom ); Eu sou um coment rio a writeln(Dia!); (* Eu tamb m sou um coment rio *) e a end. Figura 9: A seguir apresentamos o uxograma do programa BomDia2.

11

INICIO

WRITE(Bom );

WRITELN(Dia!);

FIM

Figura 10: Fluxograma do programa hello3.

2.2 Identicadores e Constantes


No programa BomDia imprimimos textos usando os comandos write e writeln. Al m disso, estes comandos tamb m e e podem ser usados para imprimir express es com tipos b sicos do pascal. Considere o seguinte programa na gura 11: o a program idade1; begin writeln(Paulo tem ,5, anos); writeln(Pedro tem ,8, anos); writeln(A soma das idades de Paulo e Pedro e:,5+8); writeln(A media das idades de Paulo e Pedro e:,(5+8)/2); end. Figura 11: O programa acima deve imprimir as linhas: Paulo tem 5 anos Pedro tem 8 anos A soma das idades de Paulo e Pedro e: 13 A media das idades de Paulo e Pedro e: 6.5 Observe que o comando writeln pode manipular tanto n meros inteiros como n meros reais. Note tamb m que se u u e a idade de Pedro passar de 8 para 9 anos, ent o todos os lugares onde aparece o n mero 8, correspondente a idade de a u ` Pedro, devemos alter -lo para 9. a Para facilitar este tipo de mudanca podemos fazer uso de um identicador associado a idade de Pedro, igual a 8 ` anos. Assim, sempre que precisamos referenciar sua idade referenciamos este identicador em vez do valor 8. Isto facilita a atualizac ao da idade de Pedro, que se formos mudar de 8 anos para 9 anos, atualizamos apenas na denicao do valor do identicador associado a idade de Pedro. Desta maneira, n o precisaremos nos preocupar em procurar ` a todas as ocorr ncias do n mero 8, al m de vericar se tal 8 e correspondente a idade de Pedro. e u e ` Identicadores s o nomes simb licos para os objetos referenciados nos programas em Pascal. Identicadores a o podem ser formados por uma letra ou caracter sublinhado seguido por qualquer combinacao de letras, dgitos ou sublinhados. Na tabela a seguir, damos alguns exemplos de identicadores v lidos e inv lidos. a a Identicadores v lidos a Media Meu Primeiro Programa Idade Paulo RA 999999 Nota MC102 Identicadores inv lidos a 2X A:B:C 1*5 X(9) Nota(102)

12

Na linguagem Pascal, n o h diferencas com as letras mai sculas e min sculas usadas no identicador. Assim, as a a u u seguintes seq encias de caracteres representam o mesmo identicador: u Nota MC102 NOTA MC102 nota mc102 noTA mC102

Obs.: Em algumas linguagens, como a linguagem C, h distinc ao entre mai sculas e min sculas usadas em identicaa u u dores. Constantes s o objetos cujos valores n o mudam durante a execucao do programa. A denicao das constantes a a deve ser feita na area de declarac oes, usando a palavra reservada const seguida das denicoes de cada constante. Cada constante e denida como: IdenticadorDeConstante constante No programa da gura 12, apresentamos o programa da gura 11 declarando as idades de Paulo e Pedro por constantes. program idade2; const Idade Paulo = 5; Idade Pedro = 9; begin writeln(Paulo tem ,Idade Paulo, anos); write(Pedro tem ,Idade Pedro, anos); writeln(A soma das idades de Paulo e Pedro e:,Idade Paulo+Idade Pedro); writeln(A media das idades de Paulo e Pedro e:,(Idade Paulo+Idade Pedro)/2); end. Figura 12:

Outros exemplos de declarac ao de constantes: program constantes; const Min = 100; Max = 999; Versao = 5.2.3; LetraPrincipal = X; Aniversario = 01/01/2000; . . . begin writeln(Min,...,Max); Imprime: 100...999 writeln(Vers o do Programa e ,Versao); Imprime: Vers o do Programa e 5.2.3 a a . . . end. Figura 13:

2.3 Vari veis e Tipos B sicos a a


O uso de constantes permite que possamos trabalhar com valores previamente xados e seu uso e feito atrav s de e um identicador que est associado aquela constante. Agora se quisermos que um determinado identicador esteja a ` associado a diferentes valores durante a execucao do programa, devemos usar o conceito de vari vel. ` a

13

Vari veis s o objetos que podem ter diferentes valores durante a execucao do programa. Cada vari vel corresponde a a a a uma posicao de mem ria. Embora uma vari vel possa assumir diferentes valores, ela s pode armazenar apenas um o a o valor a cada instante. Cada vari vel e identicada por um identicador e cont m valores de apenas um tipo. a e Os tipos b sicos em Pascal s o: char, integer, boolean, real, string. A tabela a seguir apresenta exemplos de cada a a um destes tipos. Objeto 1 -2488 1.0 -13.6 0.653 -1.23456789E+12 Algoritmos e Programacao de Computadores 123456 true false A B 6 $ Vamos ver mais sobre cada um destes tipos: integer: Representa um subconjunto dos n meros inteiros. O tipo integer no padr o Turbo Pascal representa os u a inteiros de a . J no Padr o Gnu Pascal (GPC), o tipo integer representa inteiros de a a a . real: Em geral, um n mero real e representado por duas partes: a mantissa e o expoente. A precis o dos n meros reais u a u e determinada pela quantidade de bits usada em cada uma destas partes. Exemplo: o n mero u pode ser representado por . O n mero pode ser representado por u . Este tipo n o a permite representar todos os n meros reais, mesmo que este n mero seja pequeno. Um exemplo simples disso e u u o n mero , que certamente deve ter sua precis o computada corretamente at um certo n mero u a e u de casas decimais. char: Representa um caracter. Ex.: A,B,$, (espaco em branco),... string: E uma seq encia de caracteres. Uma string pode ser dada por uma seq encia de caracteres entre ap strofos. u u o Ex: Joao Paulo. A maioria dos compiladores tem a restricao que uma string pode ter at 255 caracteres. e Atualmente h compiladores que admitem strings com n mero bem maior de caracteres. A quantidade de a u caracteres (bytes) usados pela string e denido com um n mero entre colchetes logo ap s a palavra string. Ex.: u o string[50]; O tipo acima corresponde a uma cadeia de caracteres com capacidade m xima de caracteres. Obs.: uma a cadeia de caracteres a ser armazenada neste tipo de string n o necessariamente precisa ter 50 caracteres. Para a saber mais sobre este tipo, veja a secao 8. boolean: Uma vari vel do tipo boolean pode ter dois valores. True (verdadeiro) ou False (falso). a tipo de dado integer integer real real real real expresso em notacao exponencial string string boolean boolean char char char char

Al m destes tipos, vamos considerar como tipo b sico o tipo byte, que usa apenas um byte de mem ria e pode e a o armazenar um n mero de a . u A declarac ao de vari veis e feita usando se a seguinte sintaxe: a var ListaDeIdenticadoresDoTipo1 : Tipo1; ListaDeIdenticadoresDoTipo2 : Tipo2; . . . ListaDeIdenticadoresDoTipoN : TipoN;

14

A palavra var e uma palavra reservada da linguagem Pascal que indica que vai comecar uma declarac ao de va ri veis. a Exemplo 2.1 No quadro seguinte apresentamos a declaracao de algumas vari veis. a var : real; Nome, Sobrenome: string[50]; : integer; Sexo: char;

2.4 Comando de Atribuicao


O comando de atribuic ao := atribui um valor que est a direita de :=, que pode ser uma express o, para uma vari vel a a a ( nica) que est na parte esquerda do comando, representada pelo seu identicador. u a Sempre que houver um comando de atribuic ao devemos observar os seguintes itens:

Primeiro e avaliada a parte direita, obtendo-se um valor unico. A parte da direita do comando de atribuicao pode ser uma express o bem complicada. a O valor obtido da expressao da parte direita e atribudo a` variavel ( nica) que esta na parte esquerda. u O tipo do valor avaliado da expressao na parte direita deve ser compatvel com o tipo da variavel que esta na parte esquerda. Obs.: um n mero inteiro tamb m pode ser visto como um n mero real. u e u Se um valor e armazenado em uma variavel, o valor anterior que estava nesta variavel e perdido.
Exemplo 2.2 Considere a declaracao das vari veis a e dadas a seguir: var nome: string[50]; : integer; : real; , : char; Na tabela seguinte apresentamos alguns exemplos de atribuicoes v lidas e inv lidas para estas vari veis. a a a

Atribuicoes v lidas a

nome:=Carlos


nome:=100;

Atribuicoes inv lidas a

Para esclarecer melhor estes conceitos, suponha que voc tenha uma vari vel, chamada idade, denida como sendo e a inteira: var idade: integer; No momento da execucao, o programa deve denir uma certa porcao da mem ria, em bytes, para esta vari vel. A o a maioria das linguagens n o inicializa as vari veis logo ap s a denicao de sua mem ria em bytes. Assim, vamos a a o o considerar que o valor inicial em uma vari vel e sempre um valor desconhecido e portanto iremos consider -lo como a a um lixo.
MEMRIA PRINCIPAL

Lixo
IDADE

Ap s o comando o Idade:=10; a congurac ao da mem ria deve car da seguinte forma o


MEMRIA PRINCIPAL 10 IDADE

15

Se depois deste comando for dado o comando: Idade:= 20; Ent o a programa toma a valor 20 (parte direita) e o armazena na vari vel idade (parte esquerda), e a vari vel idade a a a perde o valor anterior. Neste momento a mem ria ca com a seguinte congurac ao: o
MEMRIA PRINCIPAL 20 IDADE

Se depois deste comando for dado o seguinte comando: Idade:=Idade + 15; O programa deve avaliar primeiro o valor da parte direita, depois atribui para a vari vel (que est na parte esquerda). a a Assim, analisando a parte direita, temos 20+15=35; ent o o valor 35 e atribudo para a vari vel Idade (parte esquerda). a a Assim, a congurac ao da mem ria deve car da seguinte forma o
MEMRIA PRINCIPAL 35 IDADE

Exemplo 2.3 Considere o seguinte programa program Soma 3 20 100; var Soma: integer; begin Soma:=3; Soma:=Soma+20; Soma:=Soma+100; writeln(O valor contido em Soma e: ,Soma); end. 1. No primeiro comando de atribuicao, a vari vel Soma deve receber o valor 3. a 2. Para executar o segundo comando de atribuicao, primeiro e avaliado o lado direito do comando: (Soma+20). Note que neste exato momento, a vari vel Soma cont m o valor 3. Este e somado a 20, resultando em um valor a e unico do lado direito igual a 23. Em seguida, este valor e armazenado na vari vel que est no lado esquerdo. a a Assim o valor 23 e armazenado na vari vel Soma. a 3. No terceiro comando de atribuicao, primeiro e avaliado o valor da express o do lado direito do comando, a resultando em e este e atribudo a vari vel Soma. a ` 4. No quarto comando, de impress o, deve ser impresso o seguinte texto: a O valor contido em Soma e: 123

16

Exerccio 2.1 Considere o seguinte programa: program Produtos; var Produto : integer; begin Produto:=2; Produto:=Produto*Produto; Produto:=Produto*Produto; Produto:=Produto*Produto; writeln(O valor contido em Produto e: ,Produto); end. O que o programa imprime ? Obs.: Muitas das linguagens de programacao n o inicializam automaticamente as vari veis. Assim, e importante a a inicializar as vari veis em algum momento, antes de referenciar seus valores em express es. a o

2.5 Operadores
Operadores Aritm ticos e A seguir, apresentamos alguns operadores aritm ticos presentes na linguagem Pascal. e

+,-,*,/ (adicao, subtracao, multiplicacao e divisao de n meros, resp.). u mod (Operador de inteiros: resto de divisao inteira). div (Operador de inteiros: parte inteira da divisao).
Operandos dos tipos integer e real podem ser combinados. O tipo do valor resultante de uma operacao aritm tica e depender da operac ao e dos tipos de seus operadores. A tabela a seguir apresenta as operacoes v lidas para tipos de a a operandos e seus respectivos resultados. Operandos integer e integer integer e integer real e integer real e real

Operador

Tipo de resultado integer real real real

Exemplo 2.4 Exemplos de operacoes aritm ticas: e program OpAritmetico; var :integer; :real; begin resultado da operacao e inteiro e igual a resultado da operacao e real e igual a ; end.

17

Operadores L gicos o A linguagem Pascal oferece os seguintes operadores l gicos: o

not (inverte o valor booleano) and (e verdadeiro se ambos os operandos sao verdadeiros) or (e verdadeiro se um dos operandos for verdadeiro)
Exemplo 2.5 Exemplos de operacoes l gicas: o program OpLogico; var , , : boolean; begin

;
writeln(c); end.

True (verdadeiro)

Exerccio 2.2 Algumas implementacoes da Linguagem Pascal apresentam o operador l gico xor, sendo que este o operador resulta verdadeiro se exatamente um dos operandos for verdadeiro. Implemente este operador usando os operadores and, or e not. Operadores Relacionais Os operadores relacionais podem ser usados para os tipos real, integer, string, char e byte. Naturalmente os dois operandos devem ser de tipos compatveis. O resultado de uma operac ao relacional e sempre l gico (boolean), retornando ou true ou false. o No caso do operador = (igual), tamb m e possvel se comparar valores booleanos. Na comparac ao de strings, os carace teres s o comparados dois a dois caracteres nas mesmas posicoes, at que um caracter seja menor que outro ou at que a e e uma string termine antes que outra. Assim, Ave Maria e maior que Ave Cesar. Pois o primeiro caracter a diferir nas duas strings e o quinto caracter. Na codicacao ASCII, M e maior que C. Portanto o resultado da relacao

Ave Maria AAA


e false (falso). Exemplo 2.6 Exemplos de operacoes relacionais: program OpRelacionais; var , , : boolean; , : real; begin ; ;

Ave Cesar aaa

e true (verdadeiro). Como a codicacao de A em ASCII e menor que a, ent o o resultado da relacao a

writeln( ); writeln( ); end.

resultado e falso, j que p P a

18

Operadores em Strings O unico operador para seq encia de caracteres e o operador de concatenac ao de strings, +, que concatena duas strings. u Exemplo 2.7 Exemplo da operacao de concatenacao de strings: program OpConcatenaString; var : string[50]; begin Algoritmos; e; Programacao; de; Computadores; writeln(a); Deve imprimir: AlgoritmoseProgramacaodeComputadores end.

Preced ncia e Ao se avaliar uma express o, os operadores seguem uma ordem de preced ncia. Estas regras de preced ncia s o a e e a familiares as usadas em operadores alg bricos. Se dois operadores possuem o mesmo nvel de preced ncia, ent o a ` e e a express o e avaliada da esquerda para a direita. Parte de express es que est o contidas entre par nteses s o avaliadas a o a e a antes da express o que a engloba. A seguinte tabela apresenta a ordem de prioridade dos operadores (primeiro os de a maior preced ncia) na linguagem Pascal. e Express es dentro de par nteses o e Operador un rio (positivo ou negativo) a Operador not Operadores multiplicativos: Operadores aditivos: Operadores relacionais:

Sempre que quisermos quebrar a ordem natural das operacoes, podemos usar par nteses para especicar a nova e ordem. Assim, uma atribuic ao como , pode ter a seguinte ordem de operacoes

2.6 Algumas Funcoes Pr -Denidas e


A maioria das linguagens de programacao j nos oferece um subconjunto de funcoes b sicas que podemos usar para a a construir express es mais complexas. A tabela a seguir apresenta algumas destas funcoes. o

19

Funcao ArcTan Cos Sin Abs Abs Exp Frac Int Ln Random Random Round Sqr Sqr Sqrt Trunc Chr Ord Length

Tipo do par metro a real real real integer real real real real real : integer sem par metro a real integer real real real integer tipo escalar, exceto reais string

Tipo do Resultado real real real integer real real real real real integer real integer integer real real integer char integer integer

Resultado arco tangente cosseno Seno valor absoluto valor absoluto exponencial parte fracion ria a parte inteira Logaritmo Natural N mero pseudo aleat rio em u o N mero pseudo aleat rio em u o Arredondamento quadrado quadrado raiz quadrado Truncamento ordinal para caracter n mero ordinal do tipo escalar u Quantidade de caracteres da string

Exemplo 2.8 Uma maneira muito comum de se fazer a pot ncia de um n mero , e u e atrav s das funcoes Exp e Ln, usando a seguinte f rmula: e o n meros, e , e imprime . u program Expoente; var x,y,z : real; begin write(Entre com o valor de x: ); readln(x); write(Entre com o valor de y: ); readln(y); z: Exp(y ln(x)); writeln(O valor de ,x, elevado a ,y, igual a ,z); e end.

, elevado a outro n mero , u . O programa a seguir l dois e

Al m destas funcoes, existem alguns comandos uteis para atualizar o valor de algumas vari veis. Algumas destas e a s o: a Comando Inc Dec Tipo da vari vel de par metro a a inteiro inteiro Resultado Incrementa o valor da vari vel de 1. a Decrementa o valor da vari vel de 1. a

2.7 Comandos de Escrita


Como vimos, podemos escrever os dados na tela atrav s do comando writeln. Este comando tem como par metros e a uma lista de objetos de tipos b sicos. Os par metros devem ser separados por vrgulas. Cada par metro e impresso a a a logo ap s a impress o do par metro anterior. A linguagem Pascal tem dois comandos b sicos para escrita: o comando o a a a write e o comando writeln (de write+line). Ambos imprimem os valores de seus respectivos argumentos, com a diferenc a que o comando write mant m a posicao da pr xima impress o/leitura logo ap s a impress o de seu ultimo e o a o a par metro e o comando writeln atualiza a posicao da pr xima impress o/leitura para o incio da pr xima linha. O a o a o comando writeln sem argumentos apenas atualiza a posicao da pr xima impress o/leitura para o incio da pr xima o a o linha.

20

Exemplo 2.9 Considere o programa a seguir: program ComandosDeEscrita; var : boolean; : integer; : string[50]; begin ; ; Exemplo; writeln(Valor de a = ,a,. Vai para a pr xima linha); o writeln(Valor de b = ,b,. Vai para a pr xima linha); o writeln(Valor de c = ,c,. Vai para a pr xima linha); o write(Valor de a = ,a,. ); write(Valor de b = ,b,. ); write(Valor de c = ,c,.); writeln; writeln(Fim das impress es); o end.

O programa acima imprime as seguintes linhas: Valor de a = True. Vai para a pr xima linha o Valor de b = 9. Vai para a pr xima linha o Valor de c = Exemplo. Vai para a pr xima linha o Valor de a = true. Valor de b = 9. Valor de c = Exemplo. Fim das impress es. o Muitas vezes queremos formatar melhor a forma de impress o dos dados no comando write e writeln. Uma maneira a simples de denir a quantidade de caracteres, que uma express o ser impressa, e colocar a express o a ser impressa a a a seguida de : (dois pontos) e a quantidade de caracteres desejado. Isto far com que a express o seja impressa com a a a quantidade de caracteres especicada. Caso o dado a ser impresso e um n mero real, podemos complementar esta u formatacao adicionando : (dois pontos) e a quantidade de casas decimais depois do ponto decimal. No exemplo a seguir apresentamos um programa com algumas formatacoes de impress es e sua respectiva tela de execucao. o Exemplo 2.10 Considere o programa a seguir: program ComandosDeEscrita; var : boolean; : integer; : string[50]; : real; begin ; ; Exemplo; ; writeln(Valor de a = [,a:1,]); writeln(Valor de b = [,b:7,]); writeln(Valor de c = [,c:4,]); writeln(Valor de d = [,d:9:2,]); end. O programa acima imprime as seguintes linhas:

21

Valor de a = [T] Valor de b = [ 4321] Valor de c = [Exem] Valor de d = [ 1234.57] Obs.: Na formatacao de valores reais, pode haver perda ou arredondamentos em algumas casas decimais.

2.8 Comandos de Leitura


H dois comandos b sicos de leitura: o comando read e o comando readln. Ambos os comandos tem como par metros a a a vari veis, de tipos b sicos diferentes de boolean, e permite ler do teclado os novos valores a serem atribudos as a a ` vari veis. O comando read, ap s sua execucao, mant m a posicao da pr xima impress o/leitura logo ap s a leitura a o e o a o das vari veis. O comando readln (de read line) atualiza a posicao da pr xima impress o/leitura para o incio da a o a pr xima linha. o Exemplo 2.11 Considere o programa a seguir:

program ComandosDeLeitura; var idade: integer; nome: string[50]; begin write(Entre com sua idade: ); readln(idade); write(Entre com seu nome: ); readln(nome); writeln(O Sr. ,nome, tem ,idade, anos.) end. Caso o usu rio entre com os dados 29 e Fulano de Tal , o programa deve car com a seguinte congurac o na tela: a a Entre com sua idade: 29 Entre com seu nome: Fulano de Tal O Sr. Fulano de Tal tem 29 anos. Exerccio 2.3 Faca um programa que l 7 n meros e imprima a m dia destes n meros. Obs.: Use no m ximo duas e u e u a vari veis num ricas. a e Exerccio 2.4 Sabendo que o valor num rico de uma letra na codicacao ASCII e dada pela funcao ord, faca um e programa que leia uma letra e escreva a codicacao em bin rio desta letra. a Exemplo: Suponha que a letra a ser lida e a letra a. A funcao ord(a) retorna o valor e o programa deve imprimir: 01100001. Note que .

Exerccio 2.5 Faca uma programa que l dois pontos e dois pontos, cujo valor e impresso no programa principal. Obs.:

e ; e devolve a dist ncia entre estes a .

Exerccio 2.6 Faca um programa que l uma temperatura em graus Fahrenheit e retorne a temperatura em graus e Centgrados. Obs.: .

Exerccio 2.7 Faca um programa que l uma temperatura em graus Centgrados e retorne a temperatura em graus e Fahrenheit.

22

2.9 Tipos Escalares


Os tipos escalares integer, byte e char s o tipos que representam conjuntos ordenados com valores distintos. A a linguagem Pascal tamb m permite que possamos denir nossos pr prios tipos de dados escalares ordenados. Isto pode e o ser feito denindo o conjunto ordenado especicando cada elemento do conjunto ou aproveitando os elementos de conjunto de dados j denidos anteriormente. A seguir apresentamos estas duas maneiras de se denir tipos escalares a ordenados. Com este tipo de dados, por serem ordenados, podemos fazer comparacoes do tipo: igualdade (=), menor ( ), ), maior ( ), maior ou igual ( ) e diferenc a ( ). menor ou igual (

Especicando todos os elementos


Para denir um tipo escalar ordenado especicando todos os elementos, escrevemos seus elementos (como identicadores) entre par nteses e separados por vrgula. e Obs.: estes tipos n o podem ser impressos diretamente com uso do comando write ou writeln. a (Lista de identicadores) Como j vimos, a funcao ord sobre um caracter devolve o c digo ASCII do mesmo. A funcao ord tamb m pode ser a o e usada para encontrar a posicao de outros elemento denidos por conjuntos escalares ordenados especicados elemento a elemento. A funcao ord retorna 0 caso seja o primeiro elemento, 1 se for o segundo elemento, 2 se for o terceiro elemento, assim por diante. Exemplo 2.12 A seguir apresentamos alguns exemplos de declaracoes e atribuicoes usando os conjuntos ordenados especicados elemento a elemento. type TipoSexo = (Masculino,Feminino); TipoCor = (Vermelho,Verde,Azul); TipoMes = (Janeiro,Fevereiro,Marco,Abril,Maio,Junho,Julho, Agosto,Setembro,Outubro,Novembro,Dezembro); TipoEstadoSul = (RS,SC,PR); var Sexo: TipoSexo; Estado: TipoEstadoSul; Cor: TipoCor; Categoria: (Aluno,Funcionario,Professor); Mes: TipoMes; begin Sexo := Masculino; Estado := PR; Categoria := Funcionario; Mes := Abril; writeln(Ord(Mes)); Deve imprimir 3 end. Muitos compiladores fazem uma otimizac ao de maneira que se o tipo de conjunto ordenado tiver at 256 elementos, e ent o este tipo usa apenas um byte de mem ria. a o

Especicando uma faixa de elementos


Um tipo faixa e um tipo de dado escalar que dene uma faixa de elementos. Esta faixa e especicada pelo primeiro elemento e o ultimo elemento. Os elementos de um tipo de dado faixa devem fazer parte de um conjunto ordenado escalar. Para isso e possvel usar tanto os tipos escalares j denidos (como os tipos integer e char) como tamb m a e os novos tipos escalares ordenados como denidos elemento a elemento. Um tipo faixa e denido especicando o 23

primeiro e o ultimo elemento na seguinte sintaxe: Primeiro Elemento..Ultimo Elemento Isto signica que uma vari vel deste tipo poder receber qualquer valor que esteja no intervalo Primeiro Elemento..Ultimo Eleme a a Se uma vari vel e denida como sendo de um tipo faixa onde os extremos foram tomados a partir de um conjunto ora denado especicado elemento a elemento, ent o os elementos que s o passveis de serem atribudos a esta vari vel a a a cam restritos ao intervalo denido no conjunto ordenado tamb m. e Um tipo faixa tamb m pode ser usado para especicar os ndices de vetores, mesmo que n o sejam n meros e a u inteiros. Obs.: Um tipo escalar s poder ser impresso pelo comando write ou writeln se este for do tipo char ou integer. o a Exemplo 2.13 A seguir apresentamos alguns exemplos de declaracoes e atribuicoes usando uma faixa de elementos. type TipoMaiuscula = A..Z; TipoMinuscula = a..z; TipoDigitoCaracter = 0..9; TipoDigito = TipoDigitoCaracter; TipoDigitoNumero = 0..9; TipoMes = (Janeiro,Fevereiro,Marco,Abril,Maio,Junho,Julho, Agosto,Setembro,Outubro,Novembro,Dezembro); TipoMesPrimeiroSemestre = Janeiro..Junho; Supondo a declaracao de TipoMes do exemplo anterior TipoString = string[100]; Tipo auxiliar var DigC: TipoDigito; DigN: TipoDigitoNumero; IdadeAdolecencia: 12..18 ; Letra: TipoMaiuscula ; MesEstagio: TipoMesPrimeiroSemestre ; begin DigC := 5; DigN := 5; Letra := X; MesEstagio := Abril; end.

24

3 Estrutura Condicional
A estrutura condicional permite a execucao de instrucoes quando uma condicao representada por uma express o l gica a o e satisfeita.

3.1 Estrutura Condicional Simples


if (condicao) then Comando; A seguir, exemplicamos o uso da estrutura condicional simples. program maximo1; var , : integer; begin write(Entre com o primeiro n mero: ); u readln ; write(Entre com o segundo n mero: ); u readln ; if then writeln(O maior valor e , ); if then writeln(O maior valor e , ) end.

3.2 Estrutura Condicional Composta


Note que no exemplo do algoritmo maximo1, exatamente um dos dois comandos ifs e executado, i.e., ou . Podemos considerar ambos os casos atrav s de uma unica condicao: e if (condicao) then Comando1 ou Bloco de Comandos1 else Comando2 ou Bloco de Comandos2;

ou

true

false

If (C) Then Comando1 ou Bloco de Comandos1 Else Comando2 ou Bloco de Comandos2

Comando1 ou Bloco de Comandos1

Comando2 ou Bloco de Comandos2

Figura 14: Fluxograma do comando If-Then-Else Note que depois do Comando1 ou Bloco de Comandos1 n o h ; (ponto e vrgula). Caso tivesse um ponto e a a vrgula, este estaria separando o comando if de outro comando e portanto a palavra else n o seria continuac ao deste a 25

comando if. Na gura 14 apresentamos o uxograma do comando if, e no programa seguinte exemplicamos o uso da estrutura condicional composta. program maximo2; var , : integer; begin write(Entre com o primeiro n mero: ); readln( ); u write(Entre com o segundo n mero: ); readln( ); u if then writeln(O maior e ,a) else writeln(O maior e ,b) end.

3.3 Bloco de Comandos


Um bloco de comandos e um conjunto de instrucoes que vai ser considerado como sendo um comando unico. Desta forma, e possvel compor estruturas, como no caso do comando if, envolvendo mais comandos. Um bloco de comandos e denido pelas palavras begin e end. begin Comando1; Comando2; Comando3; . . . end; Aqui parece ser o momento para apresentar mais uma pr tica de programac ao estruturada. Sempre que um coa mando atuar sobre um bloco de comandos, dispomos este bloco de comandos deslocados mais a direita. Os comandos dentro de um bloco, entre begin e end estar o alinhados e tamb m estar o deslocados mais a direita. Isto facilita muito a e a a visualizac ao da atuacao de cada comando. Exemplo 3.1 No programa a seguir, exemplicamos o uso dos blocos de comandos.

program maximo3; var , : integer; begin write(Entre com o primeiro n mero: ); readln( ); u write(Entre com o segundo n mero: ); readln( ); u if then begin writeln(O maior est na vari vel a); a a writeln(O maior e ,a) end else begin writeln(O maior esta na vari vel b); a writeln(O maior e ,b) end end.

26

Exemplo 3.2 No exemplo seguinte apresentamos um programa que l os coecientes de uma equacao de segundo e ), e imprime as raizes desta equacao (se existir). grau, , e (equacao

program equacaosegundograu; var , , : real; var , , delta: real; begin writeln(Programa para resolver uma equacao de segundo grau.); writeln(Equacao na forma: a*x*x + b*x+c = 0); write(Entre com o valor de a (diferente de zero): ); readln ; write(Entre com o valor de b: ); readln ; write(Entre com o valor de c: ); readln ; ; if then begin ; ; writeln(O valor de x1 = , , e o valor de x2 = , ); end else writeln(n o e possvel calcular raizes reais para esta equacao); a end.

3.4 Comando Case


O comando case e um comando que permite selecionar um conjunto de operac oes conforme uma express o com a resultado escalar. Neste comando o valor escalar e comparado com v rios outros valores que dividem as opcoes de a execucao em casos (vamos chamar estes de valores de caso). No m ximo um caso pode ser verdadeiro. Os valores a de caso podem ser tanto valores escalares como faixas de valores de escalares. Al m disso, todos os valores de caso e devem ser disjuntos (sem intersec oes). Se o valor escalar e igual ao valor (ou est dentro de uma faixa) de um caso a ent o os comandos associados a este caso s o executados. a a As sintaxes do Extended Pascal e Borland Pascal diferem levemente. Assim, daremos a sintaxe do Borland Pascal e posteriormente explicitaremos a diferenc a com a sintaxe do Extended Pascal. H duas formas para a sintaxe do comando case: a A seguir apresentamos a sintaxe do caso onde n o denimos comandos para o caso de n o haver correspond ncia a a e com os valores escalares de cada caso. case (Express o Escalar) of a Lista Constantes Escalares1: Comando ou Bloco de Comandos1; Lista Constantes Escalares2: Comando ou Bloco de Comandos2; . . . Lista Constantes EscalaresK: Comando ou Bloco de ComandosK; end A sintaxe para a situacao onde denimos comandos para o caso onde n o h correspond ncia com os valores a a e escalares de cada caso e apresentada a seguir:

27

case (Express o Escalar) of a Lista Constantes Escalares1: Comando ou Bloco de Comandos1; Lista Constantes Escalares2: Comando ou Bloco de Comandos2; . . . Lista Constantes EscalaresK: Comando ou Bloco de ComandosK; else ComandoE1; ComandoE2; . . . ComandoEE; end Cada Lista Constantes Escalares pode ser uma seq encia de escalares ou faixas de escalares separados por vrgula. u A diferenc a com a sintaxe do padr o Extended Pascal e que em vez da palavra else na sintaxe anterior, e usada a a palavra otherwise. No decorrer deste texto, usaremos a sintaxe do padr o Borland Pascal. a Exemplo 3.3 O seguinte programa mostra um exemplo de uso do comando case. program exemplo; var c: char; begin write(Entre com um caracter: ); readln(c); case c of A..Z,a..z: writeln(Caracter lido e letra.); 0..9: begin writeln(Caracter lido e dgito.); writeln(i.e., um caracter em [0,9].); end; +,-,*,/: writeln(Caracter e um operador matem tico.); a $: writeln(Caracter e o smbolo $.); else writeln(O caracter lido n o e letra, nem digito.); a writeln(nem operador matem tico e nem e o smbolo $.); a end; end.

28

Exemplo 3.4 O seguinte programa mostra um exemplo de menu implementado com o comando case. Program ExemploMenu; var Opcao : char; begin repeat Escolha de uma opcao do Menu writeln(Entre com uma opco do menu abaixo: ); a writeln([1] - Inserir dados de aluno novo no cadastro.); writeln([2] - Remover aluno do cadastro.); writeln([3] - Alterar os dados de um aluno.); writeln([4] - Sair do sistema de cadastro.); write(Opcao: ); readln(Opcao); writeln; case Opcao of 1 : begin writeln(Inserir Funcionrio.); a writeln(Opco no implementada.); a a end; 2 : begin writeln(Remover Funcionrio.); a writeln(Opco no implementada.); a a end; 3 : begin writeln(Alterar Funcionrio.); a writeln(Opco no implementada.); a a end; 4 : writeln(Fim da execuco do sistema.); a else writeln(Opco invlida.); a a end; case writeln; until (Opcao 4); end.

3.5 Exerccios
1. Escreva um programa que determina a data cronologicamente maior de duas datas fornecidas pelo usu rio. Cada a data deve ser fornecida por tr s valores inteiros onde o primeiro representa um dia, o segundo um m s e o terceiro e e um ano. 2. Faca um programa que l uma medida em metros e escreve esta medida em polegadas, p s, jardas e milhas. e e Obs.: 1 polegada 1 p e 1 jarda 1 milha 25.3995 milmetros 12 polegadas 3 p s e 1760 jardas

3. Sabendo que o valor num rico de uma letra na codicacao ASCII e dada pela funcao ord, e (a) faca um programa que leia uma letra e escreva a codicacao em bin rio desta letra. a Exemplo: Suponha que a letra a ser lida e a letra a. A funcao ord(a) retorna o valor deve imprimir: 01100001. Note que . e o programa

29

(b) faca um programa que leia uma letra e escreva a codicacao em hexadecimal desta letra. Exemplo: Suponha que a letra a ser lida e a letra m. A funcao ord(m) retorna o valor e o programa deve imprimir: 6D. Note que , onde em hexadecimal e igual a em decimal. Obs.: a funcao ord sobre um caracter devolve um n mero entre e u bin rios ou 2 dgitos hexadecimais). a

(que pode ser representado em 8 dgitos

30

4 Estruturas de Repeticao
A estrutura de repeticao permite que um comando (ou bloco de comandos) seja executado repetidamente at que uma e determinada condicao de interrupc ao seja satisfeita.

4.1 Comando For


O comando For permite que um comando ou bloco de comandos seja repetido um n mero especco de vezes. Neste u comando uma vari vel de controle e incrementada ou decrementada de um valor inicial em cada iteracao at um valor a e nal. A sintaxe do comando for que incrementa a vari vel de controle e dada como: a for vari vel de controle := express o 1 to express o 2 do Comando ou bloco de comandos; a a a Para a forma que decrementa a vari vel de controle, temos a seguinte sintaxe: a for vari vel de controle := express o 1 downto express o 2 do Comando ou bloco de comandos; a a a Na gura 15 apresentamos o uxograma de uma das formas do comando for.

VC:=VI; Condio
VC>VF

true

For VC := VI to VF do Comando ou Bloco de Comandos

false Comando ou Bloco de Comandos

VC := VC + 1; {OBS:} {VC = Varivel de Controle} {VI = Valor Inicial} {VF = Valor Final}

Figura 15: Fluxograma e sintaxe de uma forma do comando for.

Exemplo 4.1 Faca um programa para calcular o fatorial de um determinado n mero u program fat; var n,i,fatorial :integer; begin write(Entre com um nmero: ); u readln(n); fatorial : 1; for i: 2 to n do fatorial: fatorial i; writeln(O fatorial de ,n, igual a ,fatorial); e end.

lido.

31

Exemplo 4.2 Faca um programa que l um valor inteiro positivo e O programa deve imprimir o maior valor real da seq encia. u program Maximo; var n,i : integer; x : real; maximo : real; begin ReadLn(n); Sup e todos os dados n o negativos. o a maximo : 0.0 for i: 1 to n do begin ReadLn(x); if x maximo then maximo : x end; WriteLn(maximo) end.

e em seguida l uma seq encia de valores reais. e u

Exemplo 4.3 (Tabuada) Faca um programa que imprima uma tabela, com 9 linhas e 9 colunas. Na intersec o da a linha com a coluna deve conter um valor que e a multiplicacao do com . Isto e, o programa deve imprimir uma tabela da seguinte forma: 1 2 3 4 5 6 7 8 9 program ProgramaTabuada; var i,j : integer; begin for i: 1 to 9 do begin for j: 1 to 9 do write(i j:3); writeln; end; end. 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81

Exerccio 4.1 (Tabela de pot ncias) Faca um programa que l dois inteiros positivos e e tamanho onde a posicao da tabela cont m o n mero . e u

e imprime uma tabela de


1 2 3 4 5 6 1 4 9 16 25 36

1 8 27 64 125 216

1 16 81 256 625 1296

1 32 243 1024 3125 7776

32

Exemplo 4.4 (Tri ngulo de Floyd) O seguinte tri ngulo formado por linhas de n meros consecutivos, cada linha a a u contendo um n mero a mais que na linha anterior, e chamado de Tri ngulo de Floyd. u a 1 2 4 7 11 16

3 5 8 12 17

6 9 13 18

10 14 19

15 20

21

Faca um programa que imprime o Tri ngulo de Floyd com a program Floyd; var i : integer; ndice da linha j : integer; ndice da coluna k : integer; pr ximo n mero o u m : integer; n mero de linhas u begin ReadLn(m); k : 0; for i: 1 to m do begin for j: 1 to i do begin k : k1; Write(k:3) end; WriteLn end end.

linhas (o valor de e lido).

Exerccio 4.2 Faca um programa que l um inteiro positivo e seguinte formato. 6 5 4 3 2 1 No caso a tabela foi impressa com valor de 5 4 3 2 1 4 3 2 1

e imprime um tri ngulo constitudo por n meros com o a u


3 2 1 2 1 1

igual a 6.

33

4.2 Comando While


O comando while e uma estrutura de repetic ao onde a condic ao de interrupc ao e testada antes de se executar os comandos a serem repetidos. Na gura 16, apresentamos o uxograma e a sintaxe do comando While.

Condio C true

false

While (C) do Comando ou Bloco de Comandos

Comando ou Bloco de Comandos

Figura 16: Fluxograma e sintaxe da rotina While.

Exemplo 4.5 (Validacao de entrada) Em determinado momento, um programa deve ler a partir do teclado um n mero u que deve estar necessariamente no intervalo . Faca um programa que que lendo n meros do teclado e pare u quando o usu rio entrar com o primeiro n mero entre . a u program Validacao; var n:integer; begin write(Entre com um nmero no intervalo [10,50]: ); readln(n); u while ((n 10) or (n 50)) do begin writeln(ERRO: Nmero invlido.); u a write(Entre com um nmero no intervalo [10,50]: ); readln(n); u end; writeln(O nmero positivo lido foi: ,n); u end. Exemplo 4.6 (Seq encia de n meros positivos) Faca um programa que l uma seq encia de n meros positivos (pode u u e u u ser vazia) e seguida pela leitura de um n mero negativo. O programa deve parar de ler n meros quando o usu rio u u a entrar com o n mero negativo. O programa deve imprimir a soma, m dia e quantidade dos n meros n o negativos. u e u a program SequenciaPositivos; var x,soma : real; nelementos : integer; begin write(Entre com um nmero: ); readln(x); u soma : 0; nelementos : 0; 0) do begin while (x soma : soma x; nelementos : nelementos 1; write(Entre com um nmero: ); readln(x); u end; if (nelementos 0) then begin writeln(A soma dos elementos : ,soma); e writeln(A media dos elementos : ,soma/nelementos); e writeln(A quantidade de elementos : ,nelementos); e end else writeln(No foi lido nenhum elemento positivo.); a end. 34

Exemplo 4.7 Faca um programa que leia uma quantidade , (vamos supor que a e ler idades inteiras e ent o deve imprimir a m dia das idades lidas.

) e em seguida o programa deve

program MediaIdades; var x,soma,lidos,n : integer; begin write(Entre com a quantidade de idades a ler: ); readln(n); lidos: 0; soma : 0; while (lidos n) do begin write(Entre com uma idade: ); readln(x); soma : soma x; lidos : lidos 1; end; if (lidos 0) then writeln(A mdia das idades ,soma/lidos) e e else writeln(No foi lido nenhuma idade.); a end. Exemplo 4.8 O c lculo da raiz quadrada de um n mero positivo a u

pode ser aproximado usando se a seguinte s rie: e

a o Se e um quadrado perfeito, ent o podemos calcular a raiz usando-se o seguinte c digo: ... readln(n); soma : 0; i : 1; raiz : 0; n do while soma begin soma : somai; i : i2; raiz : raiz1 end; writeln(raiz); ... a quadrado perfeito podemos considerando . n oaseja um Fazendo duas obter umaoaproximacao acima: a parte inteira da raiz. Seja Ent o modicac es no trecho Caso

... readln(n); soma : 0; i : 1; raiz : while soma n do begin soma : somai; i : i2; raiz : raiz1; end; raiz : raiz 1; writeln(raiz); ...

0;

Note que a atribuicao raiz:=raiz-1; foi feita para voltar o valor da raiz de uma unidade, uma vez que a condic o a de parada do comando while e soma n; . Uma vers o que atualiza a vari vel soma com atraso e apresentada a a a 35

seguir: ... readln(n); soma : 0; i : 1; raiz : while soma n do begin soma : somai; i : i2; raiz : raiz1; end; writeln(raiz); ...

1;

atraso na soma

Exerccio 4.3 Faca um programa para calcular a raiz aproximada, como no exemplo 4.8, mas usando o comando repeat em vez do comando while. Exerccio 4.4 Para calcular a raiz quadrada de com uma casa decimal basta calcular a raiz de exemplo 4.8, e dividir o resultado por 10. Faca um programa que calcula a raiz de um valor do exemplo 4.8, com casas decimais, ( e s o lidos). a

como no pelo metodo

4.3 Comando Repeat


O comando repeat e uma estrutura de repetic ao onde a condic ao de interrupc ao da estrutura de repetic ao e testada no m do bloco de repeticao. Note que neste comando n o e preciso usar begin e end para especicar os v rios comandos a a a serem repetidos. Na gura 17, apresentamos o uxograma e a sintaxe do comando Repeat.

Comando1 Comando2

Repeat Comando1 Comando2

Comandok false Comandok Until (C);

C true

Condio

Figura 17: Fluxograma e sintaxe do comando Repeat.

36

Exemplo 4.9 (Validacao de entrada) Em determinado momento, um programa deve ler a partir do teclado um n mero u u que deve estar necessariamente no intervalo . Faca um programa que que lendo n meros do teclado e pare quando o usu rio entrar com o primeiro n mero entre . a u program Validacao; var n:integer; begin repeat write(Entre com um nmero no intervalo [10,50]: ); readln(n); u if ((n 10) or (n 50)) then writeln(ERRO: Nmero invlido.); u a until (n 10) and (n 50); writeln(O nmero positivo lido foi: ,n); u end. Exemplo 4.10 A seguir apresentamos a implementacao do Algoritmo de Euclides usando o comando repeat. program Euclides; var x,y,r,m,n : integer; begin Readln(m,n); x : m; y : n; repeat r : x mod y; x : y; y : r until r 0; Writeln(x) end. Exemplo 4.11 (Seq encia de n meros positivos) Faca um programa para ler uma seq encia de n meros positivos u u u u (pode ser vazia) e seguido pela leitura de um n mero negativo. O programa deve parar de ler n meros quando o u u usu rio entrar com o n mero negativo. O programa deve imprimir a soma, m dia e quantidade dos n meros n o a u e u a negativos. program SequenciaPositivos2; var x,soma : real; nelementos : integer; begin soma : 0; nelementos : 0; repeat write(Entre com um nmero: ); readln(x); u if (x 0) then begin soma : soma x; nelementos : nelementos 1; end; until (x 0); if (nelementos 0) then begin writeln(A soma dos elementos : ,soma); e writeln(A media dos elementos : ,soma/nelementos); e writeln(A quantidade de elementos : ,nelementos); e end else writeln(No foi lido nenhum elemento positivo.); a end.

37

Exemplo 4.12 A raiz quadrada de um n mero positivo u s o tais que a sucessivas de Newton. As aproximacoes

pode ser calculada pelo m todo de aproximacoes e , onde


se caso contr rio a

Faca um programa que calcula a raiz de um n mero calculando o valor da raiz pelo m todo de aproximacoes su u e cessivas de Newton parando as iteracoes quando a diferenc a entre o valor calculado em uma iteracao com o valor calculado na iteracao anterior seja menor que . program raizquadrada; var i : integer; n,raiz,raizanterior : real; begin write(Entre com um nmero: ); u readln(n); raiz : n/2; repeat raizanterior : raiz; raiz : (raiz raiz n)/(2 raiz); until (abs(raiz raizanterior) 0.000001); writeln(A raiz de ,n:20:10, ,raiz:20:10); e end.

Exemplo 4.13 Faca um programa que escreve individualmente os dgitos de um n mero inteiro positivo da direita u para a esquerda. program Digitos1; var n,d : Integer; begin write(Entre com um nmero inteiro positivo: ); u Readln(n); repeat d : n mod 10; n : n div 10; Write(d:2) until n 0; writeln; end. Exerccio 4.5 Faca um programa que escreve individualmente os dgitos de um n mero inteiro positivo da esquerda u para a direita. Exemplo 4.14 O valor pode ser calculado atrav s da s rie e e . Cada termo desta s rie e tem um formato , . A medida que cresce, o termo vai se tornando cada vez menor, e sua e e contribuicao para o valor de se torna menor. Faca um programa que calcula o valor de atrav s da s rie acima, somando termo a termo, parando quando a diferenca absoluta entre o valor de calculado em uma iterac o e o valor a de calculado na iteracao anterior for menor que .

38

program pi; var pi,piant,termo,sinal : real ; i : integer; begin pi : 0; i : 1; sinal : 1; termo : 4; repeat piant : pi; pi : pi termo; i : i2; termo : sinal 4/i; sinal : sinal ( 1); until abs(pi piant) 0.00001; writeln(pi = ,pi); end.

Exerccio 4.6 Um programa deve ler um inteiro positivo e em seguida ler mais valores reais sendo que o programa deve imprimir a soma, a m dia, o menor valor e o maior valor dos valores reais lidos. Faca tr s vers es deste e e o programa, usando os comandos while, repeat e for.

4.4 Exerccios
1. Faca um programa que descubra um n mero entre e imaginado pelo usu rio. O programa deve fazer u a iteracoes com o usu rio. A cada iteracao, o programa deve tomar um n mero e perguntar para o usu rio se a u a este n mero e igual, menor ou maior do que o valor imaginado. O usu rio deve responder de forma correta. u a A execucao do programa deve terminar assim que o programa adivinharo valor imaginado pelo usu rio. O a programa deve imprimir o n mero imaginado e o n mero de perguntas feitas pelo programa. Seu programa n o u u a pode fazer mais que 10 perguntas. 2. Faca um programa que leia uma seq encia de n meros inteiros positivos e termine com um n mero negativo u u u (este ultimo n o deve ser considerado, serve apenas para nalizar a seq encia). O programa deve vericar se os a u n meros positivos: u (a) (b) (c) (d) Est o em ordem crescente. a Est o em ordem decrescente. a Se a seq encia e uma progress o aritm tica, neste caso dizer a raz o. u a e a Se a seq encia e uma progress o geom trica, neste caso dizer a raz o. u a e a

3. O desvio padr o dp e a vari ncia var dos n meros a a u

Faca um programa que l o valor e a seq encia dos n meros reais e depois imprime a m dia, o desvio padr o e u u e a e a vari ncia dos n meros lidos. a u Obs.: O desvio padr o tamb m pode ser obtido atrav s da f rmula a e e o , onde e a m dia dos n meros e u . Mas note que o c lculo do desvio padr o, atrav s desta f rmula, a a e o

o podem ser calculadosusando as seguintes f rmulas


exige o c lculo pr vio da m dia e portanto os n meros devem estar todos disponveis ao mesmo tempo, na a e e u mem ria do computador, para o c lculo do desvio padr o. o a a

4. Um banco faz empr stimos com uma taxa de juros mensal igual a , e quanto uma pessoa que toma emprestado reais car devendo ap s a o

. Faca um programa que imprime meses. Os valores de , e s o lidos. a

39

5 Desenvolvendo Programas
5.1 Programacao por Etapas
Quando um programa comeca a car maior ou mais complicado, e comum se fazer primeiro um esboco, contendo operacoes em alto nvel, mesmo que sejam complexas. Nos passos seguintes este esboco e detalhado em operac oes mais especcas at que se chegue na codicac ao do programa na linguagem de programac ao. e Exemplo 5.1 Faca um programa que l tr s n meros , e e verica se estes n meros formam os lados de um e e u u tri ngulo. Em caso armativo, o programa verica se o tri ngulo formado e equil tero (tr s lados iguais), is celes a a a e o (dois lados iguais) ou escaleno (tr s lados diferentes). e Vamos desenvolver este programa por etapas. Podemos considerar os seguintes passos principais: Passo 1: Leia , e . n o formam um tri ngulo ent o a a a Passo 2: Se Passo 3: Passo 5: Passo 6: Passo 7: Passo 8: Passo 9: Escreva: Os valores lidos n o formam um tri ngulo. a a Passo 4: Sen o se a

formam um tri ngulo equil tero a a

ent o a ent o a

Escreva: Os valores lidos formam um tri ngulo equil tero. a a Sen o se a

formam um tri ngulo is celes a o

Escreva: Os valores lidos formam um tri ngulo is celes. a o Sen o a Escreva: Os valores lidos formam um tri ngulo escaleno. a

Esta estrutura descreve uma estrat gia para resolver o problema, sem se preocupar com cada um dos testes mais come plicados (condicoes que est o destacadas). A traducao dos comandos n o destacados para a linguagem Pascal e a a praticamente direta. Assim, vamos nos preocupar com cada um dos testes destacados. 1. No passo 2, temos de vericar quando tr s n meros n o formam os lados de um tri ngulo. Isto pode ser feito e u a a vericando se um dos valores e maior que a soma dos outros dois valores. Assim, podemos trocar a condicao do passo 2 por: ou ou 2. No passo 4 devemos testar se os valores , e formam um tri ngulo equil tero. Isto e verdadeiro se os tr s a a e valores s o iguais e pode ser feito usando duas relacoes de igualdade. a e 3. No passo 6 devemos testar se os valores , e formam um tri ngulo is celes. Neste caso devemos vericar se a o qualquer dois dos tr s valores s o iguais. e a ou ou Substituindo estas condicoes no algoritmo acima e traduzindo para a Linguagem Pascal, temos:

40

program triangulo; var a,b,c: real; begin write(Entre com o primeiro lado: ); readln(a); write(Entre com o segundo lado: ); readln(b); write(Entre com o terceiro lado: ); readln(c); if then n o existe tri ngulo a a writeln(Os n meros n o formam um tri ngulo.) u a a else if then e tri ngulo equil tero a a writeln(O tri ngulo e equil tero) a a else if o then e tri ngulo is celes a writeln(O tri ngulo e is celes) a o else e tri ngulo escaleno a writeln(O tri ngulo e escaleno) a end. Exemplo 5.2 Programa para ler 3 n meros u decrescente de valor.

, e e imprimir de maneira a carem em ordem n o a

Um primeiro esboco, que apresenta uma estrat gia para se resolver o problema, e dada a seguir: e 1. Ler os tr s n meros nas vari veis . e u a e 2. Trocar os valores das vari veis , de forma que cont m um maior valor entre a momento, cont m um valor correto. e 3. Trocar os valores das vari veis , de forma que cont m um maior valor entre . a e 4. Imprimir .

Neste

Em um segundo passo, podemos descrever a estrat gia acima de forma mais detalhada, omitindo alguns passos e ainda desconhecidos. program ordena3; var : real; begin write(Entre com o primeiro n mero: ); readln ; u write(Entre com o segundo n mero: ); readln ; u write(Entre com o terceiro n mero: ); readln ; u if then troca valores de e if then troca valores de e Neste ponto, cont m um maior valor dos tr s valores lidos. e e if then troca valores de e Neste ponto, cont m um segundo maior valor dos tr s valores lidos. e e Ap s acertar os valores em e , observe que cont m um menor valor dos tr s lidos. o e e writeln ; end.

41

Agora considere o problema de se trocar os valores contidos em apenas duas vari veis. Digamos que voc queira a e a a trocar os valores das vari veis e . N o e possvel passar o valor de para diretamente, j que isto faria a com que perd ssemos o valor original de . Da mesma forma, tamb m n o e possvel passar o valor de para e e a diretamente, sem perda do valor original de . Isto nos induz a usar uma outra vari vel auxiliar, AUX, para primeiro a guardar o valor de , em seguida passar o valor de para , e depois passar o valor de AUX para . Isto nos d a a seguinte seq encia de operacoes: u ; ; ; Substituindo este processo de troca dos valores em vari veis no pseudo programa acima, obtemos o seguinte a programa nal: program ordena3; var n1,n2,n3, AUX: real; begin write(Entre com o primeiro nmero: ); readln(n1); u write(Entre com o segundo nmero: ); readln(n2); u write(Entre com o terceiro nmero: ); readln(n3); u if (n3 n1) then begin AUX: n3; n3: n1; n1: AUX; end; if (n3 n2) then begin AUX: n3; n3: n2; n2: AUX; end; if (n2 n1) then begin AUX: n2; n2: n1; n1: AUX; end; writeln(n1,n2,n3); end. Exerccio 5.1 Descreva um programa usando a mesma estrat gia do exemplo 5.2 para ordenar quatro n meros nas e u vari veis , , e . a

Exerccio 5.2 A estrat gia do exemplo 5.2 foi a de colocar o maior dos valores lidos na vari vel correta (acertar o e a valor em ) e em seguida aplicar o mesmo m todo para acertar as vari veis restantes (vari veis e ). Faca um e a a programa para ordenar tr s n meros como no exemplo 5.2, mas usando a estrat gia de colocar o menor dos valores e u e lidos na vari vel correta (vari vel ) e reaplicar o mesmo m todo para as demais vari veis (vari veis e ). a a e a a

5.2 Simulacao de programas


Uma simulacao de um programa nada mais e que simular o comportamento de um programa em um computador. As simulacoes que faremos tem por objetivo vericar se o programa est realmente correto ou encontrar o erro de um a programa incorreto. E aconselh vel que se faca sempre uma simulacao do programa antes de implement -lo no computador. Isto a a permitir que o programador possa tratar possveis erros no momento em que estiver projetando o programa e saber a como consert -lo mais facilmente uma vez que as id ias e estrat gias usadas no desenvolvimento do programa estar o a e e a mais frescas em sua mem ria. o Muitos compiladores que integram ambientes de editoracao possibilitam a execucao de um programa passo a passo e a observac ao de todo o processamento dos dados existentes na mem ria. Com isso, as simulacoes podem ser feitas o diretamente neste software integrado. Outros compiladores podem inserir informacoes dentro do c digo execut vel do o a programa contendo as informac oes necess rias para se fazer uma execucao passo a passo no programa fonte. a Para fazer uma simulacao em papel, precisamos ter o programa e uma mem ria em papel. Nesta simulacao voc o e estar simulando o computador acompanhando o programa e processando os dados que est o na mem ria de papel. a a o Isto e, voc far o trabalho da CPU. A seguir iremos descrever como fazer esta simulacao. e a 42

Primeiramente, descreva uma tabela, colocando na primeira linha os nomes de todas as vari veis declaradas no a programa, como apresentado abaixo. Caso seja uma funcao ou procedimento (veja secao 7) n o esqueca de colocar a tamb m os par metros declarados nestas rotinas. e a Vari vel-1 a Vari vel-2 a

Vari vel-K a

Par metro-1 a

Par metro-M a

Em seguida coloque os valores iniciais destas vari veis e par metros. Caso n o tenha sido atribudo nenhum valor a a a a elas, coloque a palavra lixo (j que e um valor que voc desconhece). No caso de par metros, coloque os valores que a e a foram passados como par metros (alguns podem ser lixo tamb m). Qualquer operacao que utilize o valor lixo tamb m a e e resulta em lixo. Vari vel-1 a lixo Vari vel-2 a lixo Vari vel-3 a lixo Par metro-1 a valor-param1 Par metro-2 a lixo

Vamos fazer a simulacao de um programa para ler uma seq encia de n meros inteiros n o negativos terminada com u u a um n mero inteiro negativo. O programa deve imprimir a soma e quantidade dos n meros n o negativos. u u a

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.

program Sequencia; var x,soma,n : integer; begin write(Entre com um nmero: ); u readln(x); soma : 0; n : 0; while (x 0) do begin soma : soma x; n : n 1; write(Entre com um nmero: ); u readln(x); end; writeln(Soma=,soma, Quantidade=,n); end.

43

Marcaremos o comando que acabou de ser executado com uma marca (inicialmente marcado no begin do bloco de comandos do programa principal). Vamos supor que a entrada e a seq encia: 1,2,3,-1. u
1. program Sequencia; 2. var x,soma,n : integer; begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 0) do begin 8. while (x 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo

Soma lixo

n lixo Incio da Simulacao Seq encia a testar: u 1,2,3,-1

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u readln(x); 6. soma : 0; 7. n : 0; 8. while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1

Soma lixo

n lixo Execucao dos passos 4 e 5. Leitura do valor 1.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; n : 0; 8. while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1

Soma lixo 0

n lixo 0 Execucao dos passos 6 e 7. Inicializac ao de Soma e n.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1

Soma lixo 0

n lixo 0

Teste da condicao do while. Elemento lido e ? ? Sim. Entrar no loop.

44

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 0) do begin 8. while (x 9. soma : soma x; n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1

Soma lixo 0 1

n lixo 0 1

Execucao dos passos 9 e 10. Acumular valor em Soma. Incrementar .

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 0) do begin 8. while (x 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2

Soma lixo 0 1

n lixo 0 1

Execucao dos passos 11 e 12. Leitura do valor 2.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2

Soma lixo 0 1

n lixo 0 1

Teste da condicao do while. Elemento lido e ? ? Sim. Entrar no loop.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 8. while (x 0) do begin 9. soma : soma x; n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2

Soma lixo 0 1 3

n lixo 0 1 2

Execucao dos passos 9 e 10. Acumular valor em Soma. Incrementar .

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 8. while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3

Soma lixo 0 1 3

n lixo 0 1 2

Execucao dos passos 11 e 12. Leitura do valor 3.

45

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3

Soma lixo 0 1 3

n lixo 0 1 2

Teste da condicao do while. Elemento lido e ? ? Sim. Entrar no loop.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 0) do begin 8. while (x 9. soma : soma x; n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3

Soma lixo 0 1 3 6

n lixo 0 1 2 3

Execucao dos passos 9 e 10. Acumular valor em Soma. Incrementar .

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 8. while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3 -1

Soma lixo 0 1 3 6

n lixo 0 1 2 3

Execucao dos passos 11 e 12. Leitura do valor -1.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; 14. writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3 -1

Soma lixo 0 1 3 6

n lixo 0 1 2 3

Teste da condicao do while. Elemento lido e ? ? N o. Ir para o pr ximo a o comando depois do loop.

1. program Sequencia; 2. var x,soma,n : integer; 3. begin 4. write(Entre com um nmero: ); u 5. readln(x); 6. soma : 0; 7. n : 0; 8. while (x 0) do begin 9. soma : soma x; 10. n : n 1; 11. write(Entre com um nmero: ); u 12. readln(x); 13. end; writeln(Soma=,soma, Quantidade=,n); 15. end.

x lixo 1 2 3 -1

Soma lixo 0 1 3 6

n lixo 0 1 2 3

Impress o de Soma e . a Soma = 6 n =3

46

if (Condicao) then begin . Nesta secao apresentamos algumas formas de alinhamen . . to que visam a melhor visualizac ao dos comandos (ou declarac oes) que est o sob atuacao de outros. Estas per- end else begin a mitem que programas quem melhor apresentados e mais f ceis de se entender. A id ia e fazer com que os comana e . . . dos que est o sob atuacao de outros estejam alinhados e a deslocados alguns espacos a direita. end; A seguir apresentamos algumas exemplos de alinhamento para alguns comandos. O leitor n o necessariamena te precisa seguir esta regra, mas e importante que se use - Comando for alguma regra razo vel de alinhamento dos comandos. a for i:=(Express o) to (Express o) do a a Obs.: As barras verticais s o apenas para visualizar o alia nhamento dos comandos.

5.3 Alinhamento de Comandos

- Declaracoes: const, type e var. const

type

var

for i:=(Express o) to (Express o) do begin a a . . .

end;

- Comando while while (Condicao) do

- Bloco de Comandos: begin

end;

while (Condicao) do begin . . .

. . .

end;

- Comando repeat repeat

- Comando if-then, if-then-else. if (Condicao) then

. . . until (Condicao);

if (Condicao) then begin . . .

end;

47

Alinhamento de comandos encaixados Quando um comando e colocado internamente a outro comando, o comando interno e todos sobre sua atuacao s o a deslocados adicionalmente ao alinhamento do comando externo. Exemplo 5.3 No exemplo a seguir apresentamos o esboco de um programa com alguns comandos encaixados em outros e o alinhamento em cada um deles. program EsbocoAlinhamento; var

begin

if (Condicao) then begin for i:=(Express o) to (Express o) do begin a a ... (Condicao) then begin for i:=(Express o) to (Express o) do begin a a . .. while (Express o) do begin a if (Condicao) then begin ... end else begin ... ... .. . until (Condicao)

48

5.4 Desenvolvimento de Algoritmos Ecientes


Em geral teremos in meros algoritmos para se resolver o mesmo problema. Alguns deles podem ser r pidos, enquanto u a outros podem exigir mais processamento e conseq entemente podem resultar em programas lentos ou at mesmo u e invi veis de serem executados. Outros algoritmos podem ser r pidos mas podem consumir muita mem ria, deixando a a o o programa igualmente invi vel. a Ao desenvolver um algoritmo, precisamos considerar os prop sitos do algoritmo juntamente com os recursos como putacionais usados por ele. Dois dos principais recursos computacionais s o o tempo de processamento e a mem ria. a o Outra considerac ao importante e o grau de facilidade de desenvolvimento e manutenc ao do programa. Progra mas escritos de maneira simples s o em geral mais f ceis de se dar manutencao do que aqueles que usam estruturas a a complexas e c digos otimizados. o No exemplo seguinte consideramos algumas vers es de algoritmos para o problema de se vericar se um n mero o u e primo ou n o. a Exemplo 5.4 Faca um programa para vericar se um n mero positivo, lido pelo programa, e primo ou n o. Obs.: u a Um n mero positivo maior que 1 e primo se e divisvel somente por ele mesmo e pela unidade. u Program Primo1; var i,n : integer; EhPrimo : Boolean; begin writeln(Programa para verificar se um nmero positivo primo ou no.); u e a write(Entre com o nmero a testar: ); u readln(n); EhPrimo: True; for i: 2 to n 1 do if (n mod i 0) then EhPrimo : false; if (EhPrimo) and (n 1) then writeln(O nmero ,n, primo.) u e else writeln(O nmero ,n, no primo.) u a e end.

a O programa acima e bem simples e compacto. E f cil ver que ele est correto, observando apenas a denicao de a n mero primo, n o ser divisvel por nenhum n mero entre u a u , e do comando de repeticao que percorre estes n meros testando se e divisvel por um deles. Al m disso, este programa usa pouca mem ria, uma vez que u e o usamos um pequeno n mero de vari veis. Por outro lado, se e um n mero grande, a quantidade de iteracoes e no u a u pior casos igual a .

Um outro extremo e quando temos j armazenados todos os n meros represent veis de nosso interesse (por exema u a plo: os n meros que podem ser armazenados em um tipo inteiro de 2 bytes), dizendo se cada um primo ou n o. Note u e a que isto j exigiu um grande pr -processamento para todos os n meros, mas uma vez feito isso, todas as consultas a e u a poder o ser feitas em tempo constante e portanto extremamente r pido. E f cil ver que este tipo de solucao pode ser a a invi vel devido a grande mem ria usada para armazenar todos estes n meros. Uma solucao menos dr stica seria a o u a armazenar todos os primos represent veis (em vez de todos os n meros). Mas mesmo com esta reducao a quantidade a u de primos existentes e grande, al m disso agora n o podemos mais fazer o teste em tempo constante ( possvel fazer e a e em tempo proporcional a , onde e a quantidade de primos).

Outra estrat gia interessante e testar primeiro para um subconjunto xo de primos (quantidade constante). Por e exemplo, vamos testar inicialmente se e divisvel por (i.e., e par); em caso positivo, n o e primo, caso contr rio a a . Isto j nos d um algoritmo que faz, no a a testamos apenas para os elementos mpares dos n meros em u pior caso, em torno da metade do processamento do primeiro algoritmo.

Uma estrat gia interessante e estudarmos mais sobre as caractersticas do problema para se tentar otimizar o e programa. Note que se um n mero n o e primo, ent o deve ser possvel escrever como u a a . Sem perda de generalidade, considere . Para vericar se n o e primo, basta achar um dos divisores. Ent o se encontramos a a , n o e mais necess rio testar para os outros n meros maiores que . Al m disso, podemos usar o fato de ser a a u e

49

e bem menor que , o que reduz limitado por . Este fato e importante uma vez que para valores grandes de , bastante a quantidade de testes feito pelo programa. O seguinte programa apresenta a implementac o desta id ia. a e Program Primo2; var i,n : integer; Max : real; EhPrimo : Boolean; begin writeln(Programa para verificar se um nmero positivo primo ou no.); u e a write(Entre com o nmero a testar: ); u readln(n); if (n 2) then EhPrimo : true else if (n mod 2 0) or (n 1) then EhPrimo: False else begin EhPrimo: True; i: 3; Max : sqrt(n); while (i Max) and (n mod i 0) do i : i2; if (i Max) and (n mod i 0) then EhPrimo : false; end; if EhPrimo then writeln(O nmero ,n, primo.) u e else writeln(O nmero ,n, no primo.); u a e end. Note que se ( e primo), o primeiro programa faz 1029 iteracoes, no comando de repeticao, e o programa acima, que tamb m faz uso de uma quantidade constante de mem ria, faz apenas 15 iteracoes. e o Exerccio 5.3 Faca um programa que verica se um n mero e primo, como no programa Primo2, mas al m de pular u e os m ltiplos de 2, tamb m pula os m ltiplos de 3. u e u

5.5 Precis o Num rica e Erros de Precis o a e a


A linguagem Pascal nos oferece o tipo real para trabalharmos com n meros. Em geral este tipo e implementado u internamente com uma quantidade xa de bytes, o que torna impossvel a representac ao exata de todos os n meros. u Isto e razo vel uma vez que h innitos n meros reais, mesmo em intervalos pequenos como . a a u Apesar disso, a maioria das implementac oes representa o n mero internamente com uma boa quantidade de u casas decimais corretas. Por exemplo, se for representado como teremos o valor correto at a casa decimal. Na maioria das aplicac oes este erro na precis o pode ser desprezvel. Um dos principais e a problemas com erros de precis o e o c lculo entre valores que j cont m erros de precis o, que podem gerar resultados a a a e a com erros maiores. O seguinte programa mostra como o erro de precis o em apenas uma conta faz com que tenhamos a um resultado totalmente inesperado. program Terco; var i : integer; terco : real; begin terco : 1/3; for i: 1 to 30 do begin terco : 4 terco 1; writeln(Iteraco: ,i:2,, Terco = ,terco:20:18); a end; end.

Se n o houvesse erros de precis o, a vari vel Terco comecaria com o valor e em cada iteracao o valor de Terco e a a a 50

atualizado como . Se Terco tivesse o valor , o novo valor de Terco seria e, em cada iteracao Terco recebe novamente o valor .

que e igual a

Isto

No entanto, a maioria dos programas execut veis construdos a partir deste programa fonte deve imprimir, na a ultima iteracao, um valor que e totalmente diferente de . Vamos analisar este programa com mais detalhes. Note que n o deve ser armazenado de forma exata, sendo a armazenado correto at certa casa decimal. Portanto, h um pequeno erro de precis o na primeira atribuic ao de Terco. e a a Vamos supor que o valor realmente atribudo seja igual a , onde e este pequeno erro de precis o. A seguir, a vamos computar os valores de Terco em cada iteracao:

Iteracao Incio 1

Terco

. . . 30

. . .

Note que e um n mero muito grande, e mesmo que seja bem pequeno, o valor chega a ser maior que , u e uma funcao exponencial e tem um crescimento resultando em um valor negativo para Terco. A funcao extremamente r pido. A medida que cresce a funcao a e dominada pelo termo . Assim, o valor rapidamente se torna negativo.

51

A seguinte tabela apresenta a impress o gerada pela execucao deste programa (o programa execut vel foi gerado a a em um computador Sun-Sparc 4 com o compilador gpc Gnu Pascal Compiler). Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: Iteracao: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, Terco = 0,33333333333333325931847 Terco = 0,33333333333333303727386 Terco = 0,33333333333333214909544 Terco = 0,33333333333332859638176 Terco = 0,33333333333331438552705 Terco = 0,33333333333325754210819 Terco = 0,33333333333303016843274 Terco = 0,33333333333212067373097 Terco = 0,33333333332848269492388 Terco = 0,33333333331393077969551 Terco = 0,33333333325572311878204 Terco = 0,33333333302289247512817 Terco = 0,33333333209156990051270 Terco = 0,33333332836627960205078 Terco = 0,33333331346511840820312 Terco = 0,33333325386047363281250 Terco = 0,33333301544189453125000 Terco = 0,33333206176757812500000 Terco = 0,33332824707031250000000 Terco = 0,33331298828125000000000 Terco = 0,33325195312500000000000 Terco = 0,33300781250000000000000 Terco = 0,33203125000000000000000 Terco = 0,32812500000000000000000 Terco = 0,31250000000000000000000 Terco = 0,25000000000000000000000 Terco = 0,00000000000000000000000 Terco = -1,00000000000000000000000 Terco = -5,00000000000000000000000 Terco = -21,00000000000000000000000

Observacoes: 1. Caso a primeira atribuicao de Terco seja algo como , , na ultima iteracao teramos algo como , que igualmente daria um valor inesperado para Terco, mas desta vez positivo. 2. Note que o unico lugar onde consideramos um erro de precis o foi na primeira atribuic ao de Terco e todas as a outras atribuic oes envolveram c lculos exatos. a

52

5.6 Tipos denidos pelo programador


Al m dos tipos j denidos na linguagem Pascal, e possvel se construir novos tipos associados a apenas um identicae a dor. Assim, poderemos declarar tipos complicados e associar este tipo com um identicador. A denicao destes novos tipos deve ser feita na area de declaracoes, usando a palavra reservada type seguida das denicoes de cada tipo. Cada tipo novo e denido como: IdenticadorDeTipo = especicacao do tipo; Exemplo 5.5 Declare tipos chamados MeuInteiro, TipoNome e TipoNumero, onde MeuInteiro e igual ao tipo integer, TipoNome e igual ao tipo string[50] e TipoNumero e igual ao real. type MeuInteiro = integer; TipoNome = string[50]; TipoNumero = real; Exemplo 5.6 Os seguintes programas s o equivalentes: a

program ExemploTipos; type TipoNome string[50]; MeuInteiro integer; var Idade : MeuInteiro; Nome : TipoNome; begin write(Entre com seu nome: ); readln(Nome); write(Entre com sua idade: ); readln(Idade); writeln(Nome, tem ,idade, anos.); end.

program ExemploTipos; var Idade : integer; Nome : string[50]; begin write(Entre com seu nome: ); readln(Nome); write(Entre com sua idade: ); readln(Idade); writeln(Nome, tem ,idade, anos.); end.

Exemplo 5.7 Outros exemplos de declaracoes de tipos e vari veis. a program Exemplo; type TipoNome string[50]; TipoRG string[15]; TipoIdade integer; TipoSalario real; var NomePedro,NomePaulo : TipoNome; IdadePedro,IdadePaulo : TipoIdade; RgPedro,RgPaulo : TipoRG; SalarioPedro,SalarioPaulo : TipoSalario; Algumas vantagens e necessidades de se usar tipos:

Basta se lembrar do nome do tipo, sem precisarmos escrever toda a especicacao de um novo objeto a ser

declarado. Um exemplo disto e o caso do TipoRG usado no exemplo acima, a cada vez que formos declarar um RG, n o precisaremos nos lembrar se um RG e declarado com 15 ou 16 ou mais caracteres; esta preocupac ao j a a foi considerada no momento da especicac ao do tipo TipoRG.

53

As re-especicacoes de tipos cam mais faceis. Usando string[15] em todos os lugares onde declaramos um

RG e se quisermos mudar para string[20], devemos percorrer todo o programa procurando pelas declarac oes de RGs e fazendo as devidas modicacoes (note que isto n o pode ser feito de qualquer forma, j que nem a a todo lugar onde aparece string[15] e uma declaracao de RG. Usando tipos, basta mudar apenas uma vez, i.e., na especicac ao de TipoRG. Al m disso h tipos de objetos da linguagem Pascal que n o admitem declaracoes usando mais que uma palavra. e a a Alguns tipos de objetos deste caso s o os par metros e as funcoes, que veremos na pr xima secao. a a o

54

6 Vari veis Compostas Homog neas a e


6.1 Vetores Unidimensionais
At agora, vimos que uma vari vel est associada a uma posicao de mem ria e qualquer refer ncia a ela signica um e a a o e acesso ao conte do de um pedaco de mem ria cujo tamanho depende de seu tipo. Nesta secao, iremos ver um dos u o tipos mais simples de estrutura de dados que nos possibilitar associar um identicador a um conjunto de elementos a de um mesmo tipo. Naturalmente precisaremos de uma sintaxe apropriada para acessar cada elemento deste conjunto de forma precisa. Antes de apresentar este tipo de estrutura de dados, considere o seguinte exemplo: Exemplo 6.1 L r 10 notas de alunos, calcular a m dia destas notas e imprimir as notas acima da m dia. e e e Note que neste exemplo as notas devem ser lidas primeiro para depois se calcular a m dia das notas. Logo em e seguida, cada nota deve ser comparada com a m dia, sendo que as maiores que a m dia s o impressas. e e a Portanto, um programa para isso deveria conter pelo menos 10 vari veis apenas para guardar cada nota. O programa a relativo a este exemplo se encontra na gura 18 program notas; var nota1,nota2,nota3,nota4,nota5, nota6,nota7,nota8,nota9,nota10 : real; media : real; begin write(Entre com a nota 1: ); readln(nota1); write(Entre com a nota 2: ); readln(nota2); write(Entre com a nota 3: ); readln(nota3); write(Entre com a nota 4: ); readln(nota4); write(Entre com a nota 5: ); readln(nota5); write(Entre com a nota 6: ); readln(nota6); write(Entre com a nota 7: ); readln(nota7); write(Entre com a nota 8: ); readln(nota8); write(Entre com a nota 9: ); readln(nota9); write(Entre com a nota 10: ); readln(nota10); media : (nota1nota2nota3nota4nota5nota6nota7nota8nota9nota10)/10; writeln(A mdia das notas ,media); e e if (nota1 media) then writeln(nota1); if (nota2 media) then writeln(nota2); if (nota3 media) then writeln(nota3); if (nota4 media) then writeln(nota4); if (nota5 media) then writeln(nota5); if (nota6 media) then writeln(nota6); if (nota7 media) then writeln(nota7); if (nota8 media) then writeln(nota8); if (nota9 media) then writeln(nota9); if (nota10 media) then writeln(nota10); end. Figura 18: Leitura de 10 notas, c lculo da m dia e impress o das maiores notas, usando vari veis simples. a e a a Note que o programa da gura 18 est cheio de duplicac oes e c lculos id nticos para cada nota. Agora imagine a a e este programa feito para uma turma de 100 alunos. Certamente n o seria nada agrad vel ler, escrever ou programar a a desta maneira. 55

Vari veis compostas homog neas correspondem a posicoes de mem ria, identicadas por um mesmo nome, india e o vidualizadas por ndices e cujo conte do e de mesmo tipo. u Assim, o conjunto de 10 notas pode ser associado a apenas um identicador, digamos NOTA, que passar a identia car n o apenas uma unica posicao de mem ria, mas 10. A refer ncia ao conte do do - simo elemento do conjunto a o e u e e a ser indicada pela notacao NOTA , onde e um valor inteiro (tamb m podendo ser uma express o cujo resultado e a inteiro).

85
1

100
2

50
3

40
4

70
5

80
6

95
7

65
8

75
9

90
10

Figura 19: Vetor de 10 notas representado pelo identicador NOTA. Na gura 19, a nota de valor 70, que est na quinta posicao da seq encia de notas e obtida como NOTA a u A declarac ao de um vetor e feita usando a seguinte sintaxe: Identicador : array Faixa Escalar of Tipo de Cada Elemento; .

Onde Faixa Escalar indica uma faixa de valores escalares. Naturalmente, se desejamos trabalhar com elementos, ent o o vetor deve ser declarado com pelo menos a posicoes na faixa. Os elementos do vetor devem ser referenciados com valores de ndice que pertencem a faixa de valores escalares usada na declaracao do vetor.

Exemplo 6.2 Exemplo de declaracao de vetores: V : array of integer; VetReais : array of real; VetIndLetras : array of real;

A declarac ao do vetor NOTA, no exemplo acima, e feita da seguinte forma. NOTA : array of real; Na gura 20, apresentamos o programa alternativo ao da gura 19, agora usando vetor. program notas2; const quant 10; var nota : array[1..quant] of real; soma, media : real; i : integer; begin soma: 0; for i: 1 to quant do begin write(Entre com a nota ,i,: ); readln(nota[i]); soma : somanota[i]; end; media : soma/quant; writeln(A mdia das notas ,media); e e for i: 1 to quant do if (nota[i] media) then writeln(nota[i]); end. Figura 20: Leitura de 10 notas, c lculo da m dia e impress o das maiores notas. Vers o usando vetores. a e a a Note que agora e f cil fazer uma mudanca no programa da gura 20 para que o programa faca o mesmo proces a samento para 100 alunos em vez de 10. Basta mudar a quantidade de alunos denida na constante quant de 10 para 100. Outra alternativa e declarar o vetor com quantidade sucientemente grande de elementos, usar uma vari vel para a armazenar a quantidade de alunos e ler pelo teclado esta quantidade. 56

Exemplo 6.3 O seguinte programa l um n mero positivo e valores reais em um vetor. O programa imprime os e u elementos do vetor que est o acima da m dia. Vamos projetar nosso programa por etapas, usando a seq encia dos a e u seguintes passos: 1. Leia ,

. 2. Leia os valores reais no vetor. 3. Calcule a m dia . e

4. Imprima os valores maiores que

program LeImprimeVetorReal; const MAX 100; type TipoVetorReal array[1..MAX] of real; var n,i : integer; v : TipoVetorReal; M,Soma : real; begin Passo 1: Leitura do valor n write(Entre com a quantidade de elementos a ler: ); readln(n); while (n 1) or (n MAX) do begin writeln(Quantidade fora dos limites possveis [1,,MAX,].); readln(n); end; Passo 2: Leitura dos n valores reais no vetor for i: 1 to n do begin write(Entre com o ,i,-esimo elemento: ); readln(v[i]); end; Passo 3: C lculo da M dia dos n valores lidos a e Soma : 0; for i: 1 to n do Soma : Soma v[i]; M : Soma/n; Passo 4: Impress o dos valores maiores que M a writeln(Valores maiores que a mdia ,M,:); e for i: 1 to n do if (v[i] M) then writeln(v[i]); end. Exemplo 6.4 Faca um programa para imprimir uma seq encia de n meros lidos em ordem inversa. u u program Inverte; const TamMax 100; var i,n : Integer; v : array [1..TamMax] of Integer; begin Readln(n); 0 n TamMax for i: 1 to n do Read(v[i]); for i: n downto 1 do Writeln(v[i]); end. Exemplo 6.5 O seguinte programa imprime o ndice do maior elemento de um vetor lido. Neste exemplo, guardamos o ndice onde aparece o maior elemento, inicialmente atribudo com 1. Em seguida, percorremos os demais elementos,

57

atualizando o valor deste ndice sempre que encontramos um elemento maior. program maximo; const MAX 100; type TipoVetorReal array[1..MAX] of real; var i, n, Ind : integer; V : TipoVetorReal; begin Leitura dos elementos do vetor write(Entre com a quantidade de elementos a ler: ); readln(n); for i: 1 to n do begin write(Entre com o ,i,-simo elemento: ); readln(V[i]); e end; Busca da posicao do maior elemento no vetor, guardando na vari vel Ind a if (n 0) then begin Ind : 1; for i: 2 to n do if V[Ind] V[i] then Ind: i; Ao encontrar um valor maior, atualiza Ind end; Impress o do maior valor e seu ndice. a if (n 0) then writeln(No h elementos no vetor.) a a else writeln(O maior valor do vetor ,V[Ind]:7:2, e aparece no ndice ,ind); e end. Exemplo 6.6 O seguinte programa l um vetor contendo e tos. Obs.:

n meros reais imprime o desvio padr o, , dos elemenu a

program ProgramaDesvioPadrao; const MAX 100; type TipoVetorReal array[1..MAX] of real; var i,n : integer; Soma,SomaQuadrado,DesvioPadrao : real; v : TipoVetorReal; begin Leitura do vetor write(Entre com a quantidade de elementos a ler: ); readln(n); for i: 1 to n do begin write(Entre com o ,i,-simo elemento: ); readln(V[i]); e end; C lculo do desvio padr o a a if (n 1) then DesvioPadrao : 0 else begin Soma : 0.0; SomaQuadrado : 0.0; for i: 1 to n do begin Soma : Soma v[i]; SomaQuadrado : SomaQuadrado Sqr(v[i]); end; DesvioPadrao : Sqrt( (1/(n 1)) (SomaQuadrado (1/n) Sqr(Soma))); end; Impress o do desvio padr o a a writeln(O desvio padro dos nmeros lidos : ,DesvioPadrao); a u e end.

Exemplo 6.7 (Busca Seq encial) O seguinte programa l o nome e a idade de v rios alunos (no m ximo 100). E em u e a a seguida o programa l repetidamente um nome de aluno e imprime a idade deste aluno. O programa deve parar de ler e 58

quando for dado o nome m, que n o deve ter idade lida. a program LeImprimeVetorReal; const MAX 100; type TipoNome string[100]; TipoVetorIdade array[1..MAX] of integer; TipoVetorNome array[1..MAX] of TipoNome; var Vnome : TipoVetorNome; Vidade : TipoVetorIdade; n,i : integer; Nome : TipoNome; Achou : boolean; begin Leitura dos nomes e idades dos alunos n: 0; writeln(Leitura dos nomes e idades dos alunos : ); write(Entre com o nome de um aluno: ); readln(nome); while (nome fim) and (n MAX) do begin n: n1; Vnome[n] : nome; write( Entre com a idade do aluno ,nome,: ); readln(Vidade[n]); write(Entre com o nome de um aluno: ); readln(nome); end; Leitura de nome e pesquisa (busca seq encial) da sua idade u writeln(Pesquisa das idades dos alunos : ); write(Entre com o nome de um aluno para pesquisar: ); readln(nome); while (nome fim) do begin i: 1; Achou : false; n) do while (not achou) and (i if (Vnome[i] nome) then Achou: true else i: i1; if (Achou) then writeln(A idade do aluno ,nome, : ,Vidade[i]) e else writeln(O nome do aluno no foi encontrado); a write(Entre com o nome de um para pesquisar aluno: ); readln(nome); end; end. Exemplo 6.8 A matriz abaixo representa o Tri ngulo de Pascal de ordem 6 (6 linhas). a 1 1 1 1 1 1

1 2 3 4 5

1 3 6 10

1 4 10

1 5

Os elementos extremos de cada linha s o iguais a 1. Os outros elementos s o obtidos somando-se os dois elementos a a que aparecem imediatamente acima e a esquerda na linha anterior (i.e., 10=4+6). O seguinte programa l um inteiro e ` positivo e imprime as linhas do tri ngulo de Pascal. a

59

program Pascal; const TamMax 100; var n,i,j : Integer; prev,corr : array[0..TamMax] of Integer; begin Readln(n); 0 n TamMax prev[0] : 1; corr[0] : 1; for i: 1 to n do prev[i] : 0; truque para evitar caso especial na diagonal for i: 1 to n do begin for j: 1 to i do corr[j] : prev[j 1]prev[j]; for j: 0 to i do begin Writeln(corr[j]); prev[j] : corr[j]; end end end. Obs.: Poderamos usar prev:=corr, mas seriam copiados todos os valores, mesmo os que n o s o usados. a a

Exemplo 6.9 (Ordenacao por Selecao) O seguinte programa l um vetor de reais n meros reais e o imprime em e u ordem n o decrescente (menores primeiro). A estrat gia usada e a mesma do algoritmo ordena3 apresentado no a e exemplo 7.4 na p gina 69. Neste caso, o algoritmo realiza a iteracoes. Na primeira iteracao, o programa en contra um maior elemento do vetor, e troca este elemento com o elemento que est na - sima posicao. Na segunda a e iteracao, o algoritmo encontra um segundo maior elemento (tirando o maior elemento, o segundo maior um maior e entre os demais) e troca com o elemento que est na a - sima posicao. Este processo se repete at que se tenha e e colocado o segundo elemento na posicao correta. Naturalmente ap s estas o iteracoes, um menor elemento deve estar necessariamente na primeira posicao. Para encontrar um maior elemento, podemos usar a estrat gia de busca e apresentada no exemplo 6.5 (pg. 57). program SelectionSort; 100; const MAX type TipoVetorReal array[1..MAX] of real; var n,m,i,imax : integer; v : TipoVetorReal; aux : real; begin Passo 1: Leitura do valor n write(Entre com a quantidade de elementos a ler: ); readln(n); Passo 2: Leitura dos n valores reais no vetor for i: 1 to n do begin write(Entre com o ,i,-esimo elemento: ); readln(v[i]); end; Passo 3: Ordenacao do vetor for m: n downto 2 do begin Encontra o m esimo maior elemento imax : 1; for i: 2 to m do if (v[i] v[imax]) then imax: i; Coloca o m esimo maior elemento na posicao m, trocando valores de v[m] e v[imax] aux : v[m]; v[m] : v[imax]; v[imax] : aux; end; Passo 4: Impress o do vetor ordenado a for i: 1 to n do writeln(v[i]:10:3); end.

Uma das vantagens de se usar este m todo e que ele faz no m ximo e a trocas entre elementos. Isto e vantajoso quando o tamanho de cada elemento (mem ria usada pelo elemento) e grande. o 60

Exemplo 6.10 (Intercalacao de vetores) Faca um programa que l dois vetores ordenados, e , com e elementos, respectivamente e intercala os dois vetores gerando um terceiro vetor ordenado , com elementos da intercalacao de e . program Intercala; const TamMax 100; TamMaxRes 200; var n1,n2,i1,i2,k : Integer; v1,v2 : array [1..TamMax] of Integer; w : array [1..TamMaxRes] of Integer; begin Readln(n1,n2); 0 n1,n2 TamMax; seq encias ordenadas u for i1: 1 to n1 do Readln(v1[i1]); for i2: 1 to n2 do Readln(v2[i2]); Os dois vetores devem ser lidos ordenados i1 : 1; i2 : 1; k : 0; n1) and (i2 n2) do begin while (i1 k : k1; if v1[i1] v2[i2] then begin w[k] : v1[i1]; i1 : i11 end else begin w[k] : v2[i2]; i2 : i21 end end; for i1: i1 to n1 do begin w[k] : v1[i1]; k : k1 end; for i2: i2 to n2 do begin w[k] : v2[i2]; k : k1 end; for i1: 1 to k do Writeln(w[i1]) end.

Exemplo 6.11 (Busca Bin ria) Note que no exemplo da busca seq encial, descrita no exemplo 6.7 podemos ver que a u no pior caso, a rotina faz comparacoes com elementos do vetor. Uma vez que temos um vetor j ordenado, e possvel a se fazer um algoritmo de busca mais eciente.

A estrat gia e a mesma que usamos para encontrar um determinado nome em uma lista telef nica (uma lista e o telef nica de uma grande cidade pode ter milh es de assinantes). Neste caso, partimos a lista telef nica em uma o o o posicao, vericamos se um nome desta posicao e menor, maior ou igual ao elemento que estamos procurando. Se for menor ou maior, podemos descartar uma das partes da lista. Assim, a estrat gia que podemos usar e a de sempre pegar um elemento do meio do vetor (ou um dos elementos e do meio) e comparar, se este elemento e menor, maior ou igual ao elemento que estamos procurando. Se for menor ou maior, podemos restringir a busca em apenas uma das partes do vetor.

61

program ProgBuscaBinaria; 100; const MAX type TipoVetorReal array[1..MAX] of real; var v : TipoVetorReal; n,pos,i,esq,dir,meio : integer; x : real; begin writeln(Entre com o nmero de elementos a inserir: ); readln(n); u A seq encia lida deve estar ordenada. u for i: 1 to n do begin write(Entre com o ,i,-simo elemento: ); readln(v[i]); end; e Pesquisa de um elemento write(Entre com um elemento a pesquisar: ); readln(x); a pos : 0; Uma vez que o elemento tenha sido encontrado, pos ter o ndice do elemento esq: 1; dir : n; while (esq dir) and (pos 0) do begin meio : (esqdir) div 2; if (x v[meio]) then dir : meio 1 descarta parte da direita else if (x v[meio]) then esq : meio1 descarta parte da esquerda else pos: meio; encontrou o elemento end; if pos 0 then Writeln(O elemento ,x, est na posico ,pos) a a else Writeln(Elemento no encontrado.); a end.

A busca bin ria nos introduz a uma quest o interessante. Quando usar a busca bin ria e quando usar a busca seq encial a a a u ? Considere primeiro o algoritmo que usa busca seq encial. Este algoritmo realiza no pior caso, no m ximo u a iteracoes por busca. Assim, se necessitamos de buscas, faremos em m dia uma quantidade de operacoes proporcio e operacoes. nal a

Para o caso da busca bin ria, note que e necess rio se fazer inicialmente a ordenac ao do vetor. Vamos supor que a a usamos a estrat gia do algoritmo SelectionSort para ordenar o vetor. Fazendo uma an lise em alto nvel, podemos ver e a que a rotina SelectionSort faz iteracoes, mas em cada uma delas h uma chamada da rotina IndMaximo que faz a no m ximo a iteracoes. Assim, a grosso modo, a quantidade de operacoes total para ordenar n o e maior que a . Agora vamos analisar, tamb m em alto nvel, a busca bin ria no pior caso, que faz digamos uma proporc ao de e a iteracoes. Na primeira iteracao s o considerados os elementos. Na segunda iteracao s o considerados elementos. a a Na terceira iteracao s o considerados a elementos, assim, por diante. Com isso a quantidade de operacoes realizadas n o e maior que uma proporc ao de . Considerando o tempo de ordenac ao mais o tempo de se fazer buscas, a temos um tempo que e delimitado por uma proporcao de operacoes.

Assim, podemos dizer que os tempos de processamento total destas duas estrat gias s o pr ximos dos comportae a o mentos de duas funcoes: para a busca seq encial e a funcao u para a busca bin ria ( e s o constantes adequadas). Note que para valores pequenos de , a busca seq encial faz a a u muito menos processamento que a estrat gia que usa busca bin ria. Por outro lado, para valores grandes de (e.g., e a a u valores bem maiores que ), temos que a busca bin ria faz menos processamento que a busca seq encial. Na secao 11 iremos estudar m todos mais ecientes para ordenac ao, o que faz com que m todos de busca usando a estrat gia da e e e busca bin ria quem bem atraentes. a

62

6.2 Vetores Multidimensionais


A linguagem Pascal tamb m permite a declarac ao de vetores de vetores. I.e., e um vetor onde cada elemento tamb m e e e um vetor. Al m disso, voc pode declarar vetores de vetores de vetores ... e e Vetores de vetores s o comumente chamadas de matrizes, e correspondem a forma de matrizes que costumamos a aprender no ensino b sico. Matrizes podem ser declaradas como nas seguintes formas equivalentes: a mat : array of array of Tipo de Cada Elemento; ou mat : array

of Tipo de Cada Elemento;


pode

Na gura 21 apresentamos uma representac ao gr ca da matriz, conforme a declarac ao acima. O elemento a ser acessado usando se a sintaxe .
I2 + I2 1 I1 I1+1 I1+2 i F1-1 F1 j F2

Figura 21: Mat : array

of Tipo de Cada Elemento

Exemplo 6.12 O seguinte programa faz a leitura e a impress o de uma matriz de forma tabular. Para cada uma destas a operacoes, o programa percorre todos os elementos a serem lidos/impressos com dois comandos for encadeados. program matriz; const MaximaDimensao 100; type TipoMatrizReal array[1..MaximaDimensao,1..MaximaDimensao] of real; TipoMsg string[100]; var n,m,i,j : integer; mat : TipoMatrizReal; begin Leitura das dimens es da matriz o write(Entre com o nmero de linhas da matriz: ); readln(n); u write(Entre com o nmero de colunas da matriz: ); readln(m); u Leitura da matriz writeln(Leitura dos elementos da matriz); for i: 1 to n do for j: 1 to m do begin write(Entre com o elemento (,i:3,,,j:3,): ); readln(mat[i,j]); end; Impress o da matriz a for i: 1 to n do begin for j: 1 to m do write(mat[i,j]:5:1, ); writeln; end; end.

63

Exemplo 6.13 O seguinte programa l tr s inteiros, , e ; l duas matrizes e , de dimens es e e e o e , respectivamente; e imprime a multiplicacao da matriz com a matriz . Obs.: Vamos supor que temos descrito o c digo para ler e imprimir as matrizes, como descritos no exemplo 6.12. o program multmat; const MAX 10; type tipomatrizreal array[1..MAX,1..MAX] of real; var Soma,A,B,C : TipoMatrizReal; p,q,r,i,j,k : integer; begin Passo 1: Fazer leitura das dimens es p,q,r o Passo 2: Fazer leitura das Matrizes A e B Passo 3: Multiplicacao das matrizes A e B em C for i: 1 to p do for j: 1 to r do begin Soma : 0; for k: 1 to q do Soma : Soma A[i,k] B[k,j]; C[i,j] : Soma; end; Passo 4: Fazer impress o da matriz C a end.

6.3 Exerccios
1. Faca um programa que l as notas de e vezes com que apareceu cada nota.

alunos, cada nota e um inteiro entre e , e imprima a quantidade de

2. Faca um programa para ordenar um vetor de n meros reais de forma n o crescente (i.e., os maiores primeiro). u a 3. Faca um programa l o nome, idade e sal rio de pessoas ( lido). O programa deve ordenar e imprimir os e a dados destas pessoas ordenados pelo nome, pelo sal rio e pela idade (de maneira n o decrescente). a a 4. Faca um programa que l uma matriz e

e imprime o determinante da matriz.

5. Escreva um programa que imprime um Tri ngulo de Pascal de ordem a um vetor e apenas um comando de repeticao for.

( lido). O programa deve usar apenas

6. Uma matriz quadrada inteira e chamada de quadrado m gico se a soma dos elementos de cada linha, a soma a dos elementos de cada coluna e as soma dos elementos das diagonais principal e secund ria s o todos iguais. a a Exemplo: As matrizes abaixo s o quadrados m gicos: a a

Faca um programa que verica se uma dada matriz quadrada lida e ou n o um quadrado m gico. a a 7. Um n mero e dito ser palndrome se a seq encia dos dgitos do n mero lidos da esquerda para a direita e igual u u u a seq encia de dgitos lidos da direita para a esquerda. Por exemplo: Os seguintes n meros s o palndromes: u u a 123454321, 54445, 789987, 121. Faca duas vers es de um programa que verica se um n mero inteiro e ou n o um n mero palndrome, uma o u a u usando vetor e outra sem usar vetor.

64

8. Leia dois vetores e , com e elementos, respectivamente, onde cada elemento do vetor e um dgito. Faca um programa que realiza a multiplicac ao dos n meros representados por estes dois vetores colocando o u resultado em um terceiro vetor. Obs.: Cada vetor de entrada tem tamanho m ximo de 100 digitos. a 9. Um mapa apresenta cidades denidas pelos n meros u . Cada duas cidades e podem estar ligadas por uma estrada. Chamamos de componente um grupo maximal de cidades que est o ligadas por estradas (i.e., e a possvel ir de uma cidade para outra que esteja no mesmo grupo andando por estradas). Faca um programa que l e um valor , quantidade de cidades, um valor , quantidade de estradas, e pares . a Cada par indica que h uma estrada ligando as cidades e . O programa deve imprimir linhas, onde e a quantidade de componentes no mapa. Cada linha cont m uma lista das cidades que est o em uma mesma e a componente.

65

7 Procedimentos e Funcoes
A linguagem pascal permite que possamos declarar trechos de c digo fora do programa principal e associados a um o identicador que podem ser executadas sempre que invocados. Chamaremos estes trechos de c digo por m dulos ou o o rotinas. Os principais motivos para se usar rotinas s o: a 1. Evitar codicacao: trocar certos trechos de programas que se repetem por chamadas de apenas uma rotina que ser codicada apenas uma vez. a 2. Modularizar o programa, dividindo-o em m dulos (rotinas) l gicamente coerentes, cada uma com funcao bem o o denida. Isto facilita a organizac ao do programa, bem como o entendimento dele. 3. Facilitar a busca e correcao de possveis erros do programa, uma vez que podemos isol -los mais facilmente. a Na linguagem pascal, podemos declarar dois tipos de rotinas, que s o os procedimentos e as funcoes. a

7.1 Procedimentos
Um procedimento e sempre declarado em uma area de declarac oes, podendo ser tanto na area de declaracoes do pro grama principal como nas areas de declarac oes de outras rotinas. Neste ultimo caso, a visibilidade deste procedimento segue as regras de escopo (veja secao 7.4). A forma geral de um procedimento segue o seguinte formato: procedure Identicador Procedimento(Lista de Par metros); a Declaracoes Area de Declaracoes begin Comandos Corpo de Execucao do Procedimento end; O procedimento tem o mesmo formato do programa principal, sendo que o corpo do procedimento est delimitado por a begin e end, este ultimo terminado com um ponto e vrgula (Na rotina principal, o end e terminado com um ponto nal). Al m disso, a lista de par metros e opcional. e a Na area de declaracoes, e possvel denir constantes, tipos, declarar vari veis, funcoes e outros procedimentos, a da mesma forma como declarados na area de declarac oes da rotina principal. E importante observar que os objetos declarados na area de declarac oes de uma rotina, s o v lidos apenas no escopo desta rotina, e n o s o v lidos fora dela. a a a a a Exemplo 7.1 Um determinado programa imprime o seguinte cabecalho diversas vezes no meio de sua execuc o: a Aluno: Fulano de Tal Data: 01/01/01 Programa: Exemplo de Procedimento Desta maneira, e melhor construir um procedimento que escreve este cabecalho sempre que necess rio. O pseudo a programa seguinte declara este procedimento e faz algumas chamadas no meio de sua execuc o. a

66

program Exemplo; procedure Cabecalho; begin writeln(Aluno: Fulano de Tal.); writeln(Data: 01/01/01.); writeln(Programa: Exemplo de Procedimento.); end; begin . . . Cabecalho; . . . Cabecalho; . . . Cabecalho; . . . (*) (*) (*)

end. O cabecalho ser impresso nas chamadas da rotina Cabecalho, linhas comentadas com (*). a

7.2 Passagem de Par metros a


Como estrat gia de programac ao, e desej vel que cada rotina n o faca uso de dados externos, pelo menos de forma e a a direta, e toda a comunicac ao com o resto do programa seja feito atrav s de par metros ou se for o caso, como retorno e a de funcao. No programa seguinte, descrevemos um procedimento chamado ImprimeMaximoDeTres com tr s par metros ree a ais: x, y e z. Os par metros declarados neste procedimento s o declarados com passagem de valor. Isto signica que a a o procedimento ImprimeMaximoDeTres e chamado com tr s par metros: e a ImprimeMaximoDeTres(Express o 1, Express o 2, Express o 3); a a a onde Express o 1, Express o 2 e Express o 3 s o express es num ricas que ser o primeiro avaliadas para valores a a a a o e a num ricos e s ent o transferidas para o procedimento. Internamente ao procedimento estes valores s o acessados e o a a pelos par metros , e . a program Maximos; var a,b,c : Real; i,n : Integer; procedure ImprimeMaximoDeTres(x,y,z : Real); var t : Real; begin t : x; if t y then t : y; if t z then t : z; writeln(O maior entre ,x,,,y,,,z, ,t); e end; MaximoDeTres begin Write(Entre com trs nmeros: ); e u Readln(a,b,c); ImprimeMaximoDeTres(a,b,c); end.

67

Os par metros s o declarados da seguinte forma: a a


onde . . .

ListaDePar metrosDoTipo1 a ListaDePar metrosDoTipo2 a . . . ListaDePar metrosDoTipoK a

Tipo1; Tipo2; . . . TipoK;

indica que a palavra var pode ou n o ser colocada antes da lista de par metros de um tipo. a a

As palavras Tipo1, Tipo2,..., TipoK s o palavras que identicam o tipo do par metro. Assim o seguinte cabecalho a a de procedimento e inv lido. a procedure Imprime(msg : string[50]); Uma construc ao correta seria primeiro denir um tipo associado a string[50] e s ent o usar este tipo na declarac ao o a de msg. I.e., type TipoMSG = string[50]; procedure Imprime(msg : TipoMSG); A insercao da palavra var antes da declarac ao de uma lista de par metros indica que estes par metros s o decla a a a rados com Passagem por Refer ncia e a aus ncia da palavra var indica que a lista de par metros seguinte e feita com e e a Passagem por Valor. A seguir, descrevemos os dois tipos de passagem de par metros. a Passagem por Valor Nesta forma, a express o correspond nte ao par metro e avaliada e apenas seu valor e passado a e a para o vari vel correspondente ao par metro dentro da rotina. a a Passagem por Refer ncia Nesta forma, o par metro que vai ser passado na chamada da rotina deve ser necessariamente uma va e a Isto porque n o e o valor da vari vel que e passada no par metro, mas sim a sua refer ncia. Qualquer alteracao de a a a e valor no par metro correspondente reetir em mudancas na vari vel correspondente, externa ao procedimento. a a a Exemplo 7.2 No exemplo da gura 22 apresentamos um programa com uma rotina chamada Conta, contendo dois par metros, um por valor e outro por refer ncia. Na linha (7), o comando de escrita imprime os valores de a e ( 1) Program exemplo; ( 2) var : integer; :real; ( 3) Procedure Conta( : integer; var : real); ( 4) begin ( 5) ( 6) ( 7) writeln(O valor de = , , e o valor de = , ); ( 8) end; ( 9) begin (10) (11) (12) Conta (13) writeln(O valor de = , , e o valor de = , ); (14) end.

Figura 22: Par metros por valor ( : integer) e por refer ncia (var : real). a e e . Na linha (13), depois da chamada da rotina Conta, s o impressos os valores de e a que a passagem do par metro correspondente a e por valor e a passagem do par metro correspondente a a a refer ncia ( tem o mesmo valor antes da chamada, e tem o valor atualizado pela rotina Conta). e

e por

, j a

68

Exemplo 7.3 A seguir, apresentamos alguns exemplos do cabecalho correspondente a declarac o de rotinas com a par metros: a

Procedure Conta(

:integer;var :integer;var :real); Neste exemplo, os par metros correspondentes a e s o declaracoes de par metros com passagem por valor; a a a e , , e s o declaracoes de par metros com passagem por refer ncia. a a e type MeuTipoString = string[50]; Procedure processa string(var nome1:MeuTipoString; nome2:MeuTipoString;var nome3:MeuTipoString; var :integer; :real); a a Neste exemplo, os par metros correspondentes a nome1, nome3 e s o declaracoes de par metros com passaa gem por refer ncia; e nome2 e s o declaracoes de par metros com passagem por valor. e a a

Exemplo 7.4 O programa para ordenar tr s n meros, descrito na p gina 42, usa a estrat gia de trocar os valores de e u a e vari veis. Note que naquele programa, a troca de valores e feita em tr s pontos do programa. Assim, nada melhor que a e fazer um procedimento para isso. O seguinte programa descreve esta alteracao no programa ordena3. Note que os dois par metros da rotina trocaReal devem ser necessariamente declarados como par metros passados por refer ncia. a a e program ordena3; procedure TrocaReal(var A, B : real); var : real; begin ; ; ; end; Troca os valores das duas vari veis a

var : real; begin write(Entre com o primeiro n mero: ); u readln(n1); write(Entre com o segundo n mero: ); u readln(n2); write(Entre com o terceiro n mero: ); u readln(n3); if then TrocaReal ; if then TrocaReal ; Neste ponto, cont m o menor dos tr s valores e e if then TrocaReal ; Neste ponto, cont m o menor dos tr s valores e e menor ou igual a e e writeln ; end. Note que este programa cou mais enxuto e mais f cil de entender. a

Exemplo 7.5 Um certo programa precisa ter, em v rios pontos do seu c digo, leituras de n meros inteiros positivos a o u e em cada um destes lugares, e necess rio se fazer a validacao do n mero lido. Uma maneira de se validar o n mero a u u a ser lido e usar uma estrutura de repeticao, como no exemplo 4.5 da p gina 34, em um procedimento que l uma a e vari vel inteira e j faz sua validacao. Desta maneira n o precisaremos repetir o c digo para cada leitura. a a a o

69

program ProgramaValidacao; string[50]; type messagetype procedure LeInteiroPositivo(var m : integer; msg:messagetype); begin write(msg); readln(m); while (m 0) do begin writeln(ERRO: Nmero invlido.); u a write(msg); readln(m); end; end; var n1,n2,n3:integer; begin LeInteiroPositivo(n1,Entre com o primeiro nmero inteiro positivo: ); u LeInteiroPositivo(n2,Entre com o segundo nmero inteiro positivo: ); u LeInteiroPositivo(n3,Entre com o terceiro nmero inteiro positivo: ); u writeln(Os trs nmeros positivos foram: ,n1,,,n2,,,n3); e u end. Consideracao sobre a passagem de estruturas grandes como par metros a Muitas vezes, quando temos passagem de estruturas grandes (como vetores e matrizes) como par metros por valor, a e prefervel recodicar a rotina para que esta seja feita como par metro por refer ncia. O motivo disto e justamente a e o fato destas estruturas serem duplicadas na passagem por valor. Na passagem de par metros por refer ncia apenas a e a refer ncia do objeto e transferida, gastando uma quantidade de mem ria constante para isso. Naturalmente esta e o codicacao n o deve mudar os valores da estrutura, caso contr rio estas se manter o ap s o t rmino da rotina. a a a o e Exemplo 7.6 Considere os dois procedimentos seguintes, nas guras 23 e 24, para imprimir o maior valor em um vetor de elementos. Note que nenhuma das duas rotinas faz alteracoes no vetor. A unica diferenca destas duas implementacoes e a passagem do par metro a por valor (gura 23) e por refer ncia (gura 24). Assim, e a implementacao da gura 24 e mais eciente que a da gura 23, caso o compilador em uso n o faca nenhuma a otimizacao para mudar o tipo da passagem de par metro. a

type TipoVetorReal array[1..1000] of real; procedure ImpMaximo(V : TipoVetorReal; n : integer); var M : real; i:integer; begin if (n 0) then begin M : V[1]; for i: 2 to n do if (V[i] M) then M: V[i]; writeln(O mximo ,M); a e end end. Figura 23:

type TipoVetorReal array[1..1000] of real; procedure ImpMaximo(var V : TipoVetorReal; n : integer); var M : real; i:integer; begin if (n 0) then begin M : V[1]; for i: 2 to n do if (V[i] M) then M: V[i]; writeln(O mximo ,M); a e end end. Figura 24:

70

7.3 Funcoes
A linguagem Pascal tamb m permite desenvolver novas funcoes al m das j existentes. Funcoes s o rotinas parecie e a a das com procedimentos, com a diferenca que funcoes retornam um valor. Uma funcao e declarada com o seguinte cabecalho: function Identicador(Lista de Par metros): Tipo da Funcao; a O valor a ser retornado pela funcao e calculado dentro do corpo da funcao e para retorn -lo, e usado um identi a cador com o mesmo nome da funcao. O tipo de valor retornado e do tipo Tipo da Func o que deve ser uma palavra a identicadora do tipo. Assim, uma funcao n o deve ser declarada como no exemplo a seguir a function Maiuscula(str: MeuTipoString):string[50]; Neste caso, string[50] n o e apenas uma palavra. Assim, uma possvel declaracao seria: a function Maiuscula(str: MeuTipoString):MeuTipoString; Exemplo 7.7 No programa a seguir, temos a declaracao de uma funcao chamada Cubo, que dado um valor real (como par metro), a funcao devolve o cubo deste valor. a program exemplo; var : real; function Cubo(x:real): real; begin Cubo ; end; begin write(Entre com o valor de a: ); readln(a); write(O cubo de ,a, e ,Cubo(a)); end.

Exemplo 7.8 No programa a seguir, apresentamos um programa com a declaracao de uma funcao que devolve o maior valor entre dois valores, dados como par metros. a program exemplo; var , , : real; function Maximo(x,y: real): real; begin if ( ) then Maximo else Maximo ; end; begin write(Entre com o valor de a: ); readln(a); write(Entre com o valor de b: ); readln(b); ; write(O m ximo entre ,a, e ,b, e: ,c); a end.

71

Exemplo 7.9 Faca um programa contendo uma funcao que calcula o fatorial de um n mero passado como par metro u a inteiro. program ProgramaFatorial; function fatorial(n:integer):integer; var F,i:integer; begin F : 1; for i: 2 to n do F: F i; fatorial : F; end; var n:integer; begin write(Entre com um nmero: ); readln(n); u writeln(O fatorial de ,n, igual a ,fatorial(n)); e end.

Exemplo 7.10 Implemente o algoritmo de Euclides para calcular o m ximo divisor comum de dois n meros. a u program ProgramaMDC; function mdc(a,b : integer):integer; var aux,maior,menor : integer; begin maior : a; menor : b; while (menor 0) do begin aux : menor; menor : maior mod menor; maior : aux; end; mdc : maior; end; var a,b:integer; begin write(Entre com dois numeros positivos: ); readln(a,b); writeln(O mdc dos dois ,mdc(a,b)); e end. Exemplo 7.11 Descreva uma funcao para testar se um n mero e primo usando a estrat gia do programa Primo2 u e apresentada na p gina 50. a function Primo(n :integer ):boolean; var i,Max : integer; begin if (n 2) then Primo : true else if (n mod 2 0) or (n 1) then Primo: False else begin Primo : True; i: 3; Max : trunc(sqrt(n)); while (i Max) and (n mod i 0) do i : i2; if (i Max) and (n mod i 0) then Primo : false end end

72

7.4 Escopo
Todos os objetos declarados em um programa (subprogramas, vari veis, constantes, tipos, etc) possuem um escopo de a atuacao. Por escopo de um objeto, entendemos como as regi es de um programa onde o objeto e v lido. o a Primeiramente, vamos denir alguns termos: Cabecalho de uma Rotina E o texto que indica o tipo da rotina (se programa principal, procedimento ou funcao), seu nome e seus par metros. a Area de Declaracao da Rotina Area onde se declaram as vari veis, tipos, procedimentos e funcoes da rotina. a Corpo de uma Rotina Deniremos o Corpo de uma Rotina (pode ser o Programa Principal, um Procedimento ou uma Funcao) como o trecho da rotina contendo as instrucoes a serem executadas. Na gura a seguir, temos alguns exemplos de rotinas.
Program teste; { Declaraes } Procedure Rotina1; { Declaraes } Function f1(i:integer):integer; { Declaraes }

Begin { Corpo } End.

Begin { Corpo } End;

Begin { Corpo } End;

Note tamb m que na area de declarac ao de uma rotina podemos declarar novas rotinas. Na gura 25, temos uma e estrutura de um programa com v rias rotinas, declaradas uma dentro da area de declarac oes da outra. a Se em algum lugar e feito alguma refer ncia a um objeto do programa, este j deve ter sido declarado em alguma e a posicao acima desta refer ncia. e Os objetos declarados em uma rotina R s o visveis no corpo de R e em todas as subrotinas dentro da area de a declarac oes de R. Por visualizar, queremos dizer que podemos usar a vari vel/procedimento/func ao no local de a visualizac ao. Se dois objetos t m o mesmo nome, a refer ncia atrav s deste nome e feita para o objeto que estiver na area de e e e declarac oes visvel mais interna. Exemplo: considere duas rotinas, R e R1, onde R1 est declarado na area de a declarac oes de R (R1 est contido em R). Um identicador declarado dentro de R1 pode ser declarado com o mesmo a nome de um outro identicador em R (externo a R1). Neste caso, a vari vel declarada em R n o ser visualizada em a a a R1. Na gura 25 apresentamos o esboco de um programa com diversos nveis de encaixamento de rotinas. A seguir, descrevemos quais objetos podem ser visualizados em cada regi o: a 1. 2. 3. 4. 5. Na regi o 1, podemos visualizar os objetos: a Na regi o 2, podemos visualizar os objetos: a Na regi o 3, podemos visualizar os objetos: a Na regi o 4, podemos visualizar os objetos: a Na regi o 5, podemos visualizar os objetos: a C, B, A (primeiro A), Rotina1 e Rotina2. D, B, A (segundo A), Funcao1, Rotina1 e Rotina2. A (primeiro A), B, Funcao1, Rotina1 e Rotina2. E, A (primeiro A) e Rotina3 e Rotina1. A (primeiro A) e Rotina1 e Rotina3.

Exemplo 7.12 O programa seguinte apresenta um procedimento que encontra as raizes reais de uma equac o do a segundo grau. O procedimento se chama Equacao, tem tr s par metros e chama uma funcao particular chamado Cale a culaDelta. Por ser particular a este procedimento, a funcao CalculaDelta pode estar dentro da area de declaracoes 73

Program escopo; var A: integer; {Primeiro A} Procedure rotina1; var B: integer; Procedure rotina2; var C: integer; begin {Regio 1} end; Function funcao1(x:integer): real; var A: integer; {Segundo A} D: real; begin {Regio 2} end; begin {Regio 3} end; Procedure rotina3; var E: integer; begin {Regio 4} end. begin {Regio 5} end.

Figura 25: Exemplo de objetos com escopos diferentes. de Equacao. program EquacaoSegundoGrau; var a ext, b ext, c ext : real; procedure Equacao(a,b,c: real); imprime as solucoes reais de a x x b xc 0 var x1, x2,delta : real; Vari veis locais ao procedimento. a function CalculaDelta(c1,c2,c3: real): real; begin CalculaDelta : sqr(c2) 4 c1 c3; end; begin delta: CalculaDelta(a,b,c); 0) then begin if (delta x1: ( bsqrt(delta)) / (2 a); x2: ( b sqrt(delta)) / (2 a); writeln(O valor de x1 = ,x1, e o valor de x2 = ,x2); end else writeln(no possivel calcular raizes reais para esta equaco); a e a end; begin writeln(Encontrar raizes reais de equaco na forma: a*x*x + b*x+c = 0); a write(Entre com o valor de a (diferente de zero), b e c: ); readln(a ext,b ext,c ext); Equacao(a ext,b ext,c ext); end.

74

Exemplo 7.13 O seguinte programa apresenta um procedimento para ordenacao usando a estrat gia do algoritmo e SelectionSort, descrita com duas subrotinas encaixadas. program SelectionSort; const MAX 100; type TipoVetorReal array[1..MAX] of real; string[100]; TipoMsg procedure LeVetorReal(var v : TipoVetorReal; n:integer;msg:TipoMsg); var i : integer; begin writeln(msg); for i: 1 to n do begin writeln(Entre com o ,i,-simo elemento: ); readln(V[i]); end e end; LeVetorReal procedure ImprimeVetorReal(var v : TipoVetorReal; n:integer;msg:TipoMsg); var i : integer; begin writeln(msg); for i: 1 to n do begin writeln(V[i]); end end; ImprimeVetorReal procedure SelectionSort(var v : TipoVetorReal; n:integer); var m,imax : integer; procedure TrocaReal(var a,b : real); var aux : real; begin aux : a; a: b; b: aux; end; function IndMaximo(var v : TipoVetorReal; n : integer) : integer; var i, Ind : integer; begin if (n 0) then Ind : 0 else begin Ind : 1; O maior elemento comeca com o primeiro elemento do vetor for i: 2 to n do if v[Ind] v[i] then Ind: i; end; IndMaximo : Ind; end; begin for m: n downto 2 do begin imax : IndMaximo(v,m); TrocaReal(v[m],v[imax]); end; end; SelectionSort var i, n, Ind : integer; V : TipoVetorReal; begin write(Entre com a quantidade de elementos a ler: ); readln(n); LeVetorReal(v,n,Leitura do vetor a ordenar); SelectionSort(v,n); ImprimeVetorReal(v,n,Vetor ordenado); end.

75

7.5 Cuidados na Modularizacao de Programas


A modularizac ao dos programas pode levar ao desenvolvimento de programas mais indepententes e mais f ceis de se a entender. Mas h casos onde devemos tomar algum cuidado, se quisermos evitar processamentos desnecess rios. Dois a a casos onde podemos ter processamento desnecess rio s o: a a 1. Rotinas distintas fazendo os mesmos c lculos, i.e., alguns dados v o ser recalculados. a a 2. Chamadas de uma mesma rotina v rias vezes, onde uma chamada pode ter feito c lculos j realizados pela a a a chamada anterior. Muitas vezes priorizamos a independ ncia e funcionalidade das rotinas e toleramos que algumas computac oes sejam e duplicados. Isto e razo vel quando estas duplicac oes n o s o crticas no tempo de processamento total. Quando o tem a a a po de processamento deve ser priorizado, devemos reconsiderar o programa e evitar estas computac oes desnecess rias. a O seguinte exemplo mostra duas vers es de um programa para calcular a exponencial . o Exemplo 7.14 A exponencial

pode ser calculada pela seguinte s rie: e

O programa seguinte mostra uma implementacao da funcao exponencial, usando duas outras funcoes, uma para calcu lar o fatorial, e outra para calcular a pot ncia. O programa p ra quando a diferenc a entre o valor da s rie calculado e a e at uma iteracao com o valor calculado na iteracao anterior e menor que 0,00001. e program exprog1; var y : real; function fatorial(n : integer):integer; var i,f : integer; begin i: 1; f: 1; n) do begin f: f i; i: i1; end; while (i fatorial: f; end; function potencia(x : real; n:integer):real; var i : integer; p : real; begin p: 1; for i: 1 to n do p: p x; potencia : p; end; function expo1(x : real):real; var termo,ex,exant: real; i:integer; begin ex : 0; termo: 1; i : 0; repeat exant : ex; termo : potencia(x,i)/fatorial(i); ex : ex termo; inc(i); until abs(ex exant) 0.0001; expo1 : ex; end; begin write(Entre com um nmero real: ); readln(y); u writeln(O valor de e elevado a ,y, igual a ,expo1(y)); e end.

76

O programa exprog1 e f cil de entender, uma vez que cada termo da s rie e facilmente calculado atr ves da funcao e a a fatorial e da funcao pot ncia. Mas note que ao se calcular um termo gen rico desta s rie, em uma iteracao, digamos e e e o termo , o programa calcula o valor , sendo que em iteracoes anteriores, j foram computados os valores de a , ,..., . Cada um destes c lculos poderia ter aproveitado o c lculo da pot ncia feita na iteracao anterior. O a a e mesmo acontece com o fatorial, , que poderia ter aproveitado o c lculo de a feito na iteracao anterior. Por tanto, o termo calculado em uma iteracao e igual ao termo anterior, , multiplicado por . O seguinte programa apresenta a vers o modicada, sem repeticao de processamento. a program exprog2; var y : real; function expo2(x : real):real; var termo,ex,exant : real; i:integer; begin termo: 1; i : 1; ex : 0; repeat exant : ex; ex : ex termo; termo : termo x/i; inc(i); until abs(ex exant) 0.0001; expo2 : ex; end; begin write(Entre com um nmero real: ); u readln(y); writeln(O valor de e elevado a ,y, igual a ,expo2(y)); e end.

Exerccio 7.1 O valor do seno

pode ser dado pela seguinte s rie: e

Implemente uma funcao chamada seno , para calcular o valor do seno de . Note que e igual a . OBS.: A funcao deve usar no m ximo um loop. I.e, n o se pode usar loops encaixados. a a

e igual a e

Exerccio 7.2 O valor do co-seno de

pode ser calculado pela serie

Descreva uma funcao com o cabecalho: function coseno(x:real):real; e que devolve o valor do coseno de calculado com os 100 primeiros termos dada pela s rie acima. e OBS.: A funcao deve usar no m ximo um loop. I.e, n o se pode usar loops encaixados. a a

7.6 Exerccios
1. Faca tr s vers es da funcao fatorial: e o function fatorial( :integer):integer; usando as estruturas de repeticao: for, while e repeat. 2. Os n meros de bonacci u s o denidos da seguinte forma: a


77

Faca um programa contendo uma funcao function bonacci( :integer):integer; que retorna o - simo n mero de bonacci. e u 3. Faca um procedimento com um par metro inteiro e que ao ser chamado, o procedimento imprime uma gura a da seguinte forma:

....*.... ...***... ..*****.. .*******. ********* .*******. ..*****.. ...***... ....*.... No caso, o procedimento foi chamado com par metro 5. A quantidade de linhas impressas e a . 4. O valor de tamb m pode ser calculado usando a s rie e e , sendo que o valor de e calculado como . Faca uma funcao para calcular o valor de usando esta s rie e e parando quando a diferenc a do valor de calculado em uma iteracao e a iteracao anterior for menor que 0,0001. 5. Escreva um programa contendo uma funcao function binario( :integer):TipoString; que retorna um tipo chamado TipoString, declarado como type TipoString = string[50]; string contendo o n mero na base bin ria. u a 6. Faca duas funcoes que tem um par metro inteiro e retornam verdadeiro se o par metro for primo e falso caso a a contr rio, uma funcao usando o m todo ing nuo apresentado na p gina 49 e o m todo otimizado apresentado na a e e a e p gina 50. Verique quanto tempo estas duas funcoes gastam se usadas para contar todos os primos no intervalo a . Experimente para outros intervalos maiores. 7. Implemente conjuntos atrav s de vetores e faca os seguintes procedimentos: e

(a) Procedimento chamado conjunto, com dois par metros, um vetor e um inteiro positivo a , indicando a quantidade de elementos no vetor. O procedimento deve remover os elementos duplicados do vetor e atualizar o valor de . (b) Procedimento chamado Intersecao com seis par metros, com o seguinte cabecalho: a procedure intersecao(var :tipovetor; :integer; var :tipovetor; :integer; var :tipovetor; var :integer); O vetor ( ) cont m ( ) elementos. O vetor receber a intersec ao dos elementos de e e e a e deve retornar com a quantidade de elementos em (vamos supor que cada vetor cont m elementos distintos). Voc deve usar a seguinte estrat gia para gerar a intersec ao de e : e e (1) Ordene o vetor . (2) Para cada elemento de , faca uma busca bin ria do elemento no vetor . a (2.1) Se o elemento se encontrar no vetor, insira o elemento no vetor . (c) Procedimento chamado Uniao com seis par metros, com o seguinte cabecalho: a procedure uniao(var :tipovetor; :integer; var :tipovetor; :integer; var :tipovetor; var :integer); e a a O vetor ( ) cont m ( ) elementos. O vetor receber a uni o dos elementos de e e deve retornar com a quantidade de elementos em (vamos supor que cada vetor cont m elementos distintos). e Voc deve usar a seguinte estrat gia para gerar a uni o de e : e e a (1) Copie o vetor no vetor (atualizando ). (2) Para cada elemento de , faca uma busca bin ria do elemento no vetor . a (2.1) Se o elemento n o se encontrar no vetor, insira o elemento no vetor . a

78

8. Tem-se um conjunto de dados contendo a altura e o sexo (M ou F) de 50 pessoas. Fazer um algoritmo que calcule e escreva: (a) A maior e a menor altura do grupo. (b) A m dia de altura das mulheres. e (c) O n mero de homens. u

9. Descreva uma funcao que tenha como par metros uma raz o, , um valor inicial, , e um n mero e devolva a a u a soma dos primeiros elementos de uma progress o aritm tica comecando com e com raz o . a e a 10. Descreva um procedimento, com par metro inteiro positivo e dois outros par metros e que devem retornar a a valores inteiros positivos. Os valores a serem retornados em e s o tais que seja o menor valor inteiro tal a . que 11. Faca uma funcao booleana com par metro e que retorna verdadeiro se e primo, falso caso contr rio. a a 12. Faca uma funcao que tenha como par metro uma temperatura em graus Fahrenheit e retorne a temperatura em a graus Celsius. Obs.: . 13. O imposto que um trabalhador paga depende da sua faixa salarial. Existem at faixas salariais, cada uma com e uma correspondente taxa. Exemplo de um sistema com at 4 faixas salariais: e

(a) Para sal rios entre 0 e 100 reais, e livre de imposto. a (b) Para sal rios maiores que 100 e at 500 reais, e 10 % de imposto. a e (c) Para sal rios maiores que 500 e at 2000 reais, e 20 % de imposto. a e (d) Para sal rios maiores que 2000 e 30 % de imposto. a Faca um programa que leia estas faixas salariais e leia uma seq encia de sal rios e imprima para cada um, o u a imposto a pagar. O programa deve parar quando for dado um sal rio de valor negativo. a u u 14. Faca um programa de lot rica, que l o nome de jogadores e os n meros que eles apostaram (um n mero entre e e 0 e 100). Use a funcao RANDOM(N) para sortear um n mero. Se houver ganhador, imprima o nome dele e o u n mero que ele apostou, caso contr rio, avise que ningu m ganhou. u a e

79

8 Processamento de Cadeias de Caracteres


Em praticamente todos os padr es de codiacao, a representac ao interna das letras est agrupada e ordenada. Este e o a um dos motivos dos computadores poderem fazer comparac oes com letras, como A B rapidamente, internamente e comparada sua codicac ao interna. Al m disso, a codicacao das letras e n meros e em geral seq encial. Um exemplo e u u disto e a codicacao ASCII (veja tabela 1). Como vimos, uma cadeia de caracteres pode ser denida com o tipo string. Al m disso, podemos fazer operac oes e com os caracteres que est o nesta string (cadeia). Considere as seguintes declarac oes: a type TipoTexto = string[1000]; var Texto : TipoTexto; Com estas declarac oes, podemos fazer a seguinte atribuic ao para a vari vel Texto: Texto := Algoritmo; a Uma funcao que devolve o comprimento da cadeia de caracteres e a funcao length. Ap s a atribuic ao acima, length(Texto) o deve retornar o inteiro 9. Al m disso, podemos trabalhar com cada caracter deste texto, como se Texto fosse um vetor e de 9 posicoes, i.e., podemos acessar e atualizar um elemento da cadeia. Assim, ap s a atribuic ao da vari vel Texto feita o a acima, temos em Texto[1] a letra A, Texto[2] a letra l, Texto[3] a letra g, ..., Texto[9] a letra o. Observacoes: 1. Em Turbo Pascal h uma limitacao do tamanho m ximo de uma String, de 255 caracteres. A declarac ao de a a vari veis usando apenas a palavra reservada String denota o tipo string com 255 caracteres. No Turbo Pascal a a passagem de tipos e feita de maneira rgida, de tal forma que uma vari vel declarada como String[255] n o a a pode ser enviada como um par metro declarado apenas como o tipo string. a 2. Em Delphi, String denota normalmente o tipo long string ou AnsiString cujo limite de comprimento m ximo e 2 GB! Com a diretiva de compilacao $H-$, String denota o tipo String[255] como em Turbo a Pascal. Outra alternativa equivalente e usar o tipo pr -denido ShortString. e 3. Em Gnu Pascal n o e possvel declarar vari veis usando apenas a palavra String, mas na passagem de par metros a a a e ponteiros sim. Desta maneira poderemos ter vari veis declaradas como strings de tamanhos diferentes mas que a s o recebidas como par metros do tipo String (sem especicacao do tamanho). a a 4. Em Extended Pascal tamb m n o e possvel se usar apenas a palavra String para declarar vari veis, al m disso e a a e o tamanho da string e declarado usando se parenteses em vez de colchetes. Por exemplo, a seguinte declarac ao apresenta uma string em Extended Pascal com 100 caracteres. var nome:string(100); Nos exemplos deste texto usaremos a seguinte sintaxe:

Na declaracao de variaveis e tipos usaremos colchetes com o devido tamanho da string. Na passagem de parametros daremos prioridade para a sintaxe usando a palavra string. No caso onde a rotina
tem funcionalidade xa para um determinado tipo usaremos o nome do tipo no lugar da palavra string. A seguir apresentamos algumas rotinas para manipulacao de strings. Funcao Length SetLength Pos Concat Copy Insert Delete Resultado Retorna a quantidade de caracteres da string Redene a quantidade de caracteres em uso como Retorna a posicao da cadeia na cadeia (0 se n o ocorre) a Retorna a concatenac ao de (equivale a ) Retorna a cadeia formada pelos caracteres a partir da posicao Insere em a partir da posicao Remove os caracteres a partir da posicao

80

Exemplo 8.1 Descreva uma implementacao em pascal da funcao Pos. function Pos(var s1,s2: String): Integer; var n1,n2,d,i,j : Integer; achou, cont: Boolean; begin n1 : Length(s1); n2 : Length(s2); d : n2 n11; achou : False; i : 1; while (not achou) and (i d) do begin j : 1; cont : True; n1) do while cont and (j begin cont : (s1[j] s2[ij 1]); inc(j) end; achou : cont; inc(i); end; if achou then Pos : i 1 else Pos : 0 end; Pos

Exemplo 8.2 Descreva uma implementacao em pascal da funcao Insert. function Insert(var s1,s2: String; p: Integer); Insere os caracteres de s1 que couberem em s2 const ComprMax 255; var n1,n2,d,i : Integer; begin n1 : Length(s1); n2 : Length(s2); if (n1n2) ComprMax then d : ComprMax n2 else d : n1; i : 1; for i: n2 downto n2 d1 do s2[id] : s[i]; for i: 1 to d do s2[pi 1] : s1[i]; SetLength(s2,n2d) end; Insere

Exemplo 8.3 Uma cadeia de caracteres e dita ser palndrome se a seq encia dos caracteres da cadeia da esquerda u para a direita e igual a seq encia de caracteres da direita para a esquerda. Por exemplo: As seguintes cadeias de u caracteres s o palndromes: ABC12321CBA, ACCA, XYZ6.6ZYX. a Faca uma funcao que retorna verdadeiro se a cadeia de caracteres enviada como par metro e palndrome. a

81

function Palindrome(var s: String): Boolean; var i,m,n : Integer; p: Boolean; begin p : True; n : Length(s); m : n div 2; i : 1; m) do begin while p and (i p : (s[i] s[n i1]); inc(i); end; Palindrome : p end; Palindrome

8.1 Letras com Ac ntos e


Em muitas situacoes temos cadeias de caracteres seguindo uma codicacao para acentuac ao das letras (eg. textos escritos na lngua portuguesa). As codicacoes de acentuac ao n o s o consideradas na codicacao ASCII e na maioria a a das vezes n o seguem uma padronizac ao envolvendo diferentes plataformas (i.e., uma letra acentuada em um ambiente a Unix pode ter c digo diferente da mesma letra acentuada em ambiente MS-DOS). o Uma tarefa comum que temos de fazer, quando consideramos ac ntos, e a remocao destes do texto. A seguir e apresentamos duas aplicacoes onde precisamos fazer um pr -processamento para remover os acentos: e 1. Envio de mensagens pela internet por correio eletr nico. o A internet e uma rede de computadores que n o necessariamente seguem a mesma congurac ao. Os textos como a as mensagens enviadas por correio eletr nico s o enviadas considerando a congurac ao ASCII. Por outro lado, o a letras acentuadas em um computador podem n o ser consideradas realmente letras em outros computadores. a Assim, estes podem ser interpretados como c digos de acao totalmente imprevisvel. Uma solucao para isso e o eliminar os acentos, ou troc -los por uma seq encia de letras ASCII que representem a letra acentuada. a u 2. Ordenacao de cadeias de caracteres. Para comparar duas cadeias de caracteres, a maioria dos programas considera as representac oes bin rias caracter a a caracter. Considerando a codicac ao ASCII, a ordenac ao de letras em ASCII se torna f cil, uma vez que a temos apenas que comparar letra a letra nesta codicacao. Por outro lado, teremos uma ordenac ao errada caso tenhamos acentos. Por exemplo, considere as palavras macro, macaco e maco. Se a codicac ao de c vier antes de c, ent o a teremos a seguinte ordem para estas palavras: maco, macaco e macro, que n o e a ordem que desejamos. Por a outro lado, se a codicac ao de c vier antes de c, ent o teremos a ordem: macaco, macro e maco, que tamb m a e n o e a desejada. Assim, uma solucao para isto e comparar as palavras trocando as letras acentuadas pelas a correspondentes letras sem acento. Exemplo 8.4 O seguinte programa cont m uma funcao que dado uma letra, retorna a letra sem acentuacao. e Obs.: Esta implementacao e dependente da codicao das letras usada no programa fonte.

82

program acentos; function SemAcento(caracter : char):char; begin case caracter of : SemAcento: a; a : SemAcento: A : SemAcento: E; : SemAcento: E : SemAcento: o; o : SemAcento: O : SemAcento: U; U ` : SemAcento: a : SemAcento: A : SemAcento: a; a : SemAcento: E; E : SemAcento: o : SemAcento: A : SemAcento: a; a : SemAcento: O; O : SemAcento: u c : SemAcento: c; C : SemAcento: else SemAcento: caracter; end; case end; var c : char; begin c: ; writeln(A letra ,c, sem acento a c: ; writeln(A letra ,c, sem acento e a c: ; writeln(A letra ,c, sem acento c: ; writeln(A letra ,c, sem acento o end.

A; i; O; a; A; o; A; u; C;

: SemAcento: e : SemAcento: I : SemAcento: u ` : SemAcento: A : SemAcento: e : SemAcento: O : SemAcento: o : SemAcento: U

e; I; u; A; e; O; o; U;

fica fica fica fica

,SemAcento(c)); ,SemAcento(c)); ,SemAcento(c)); ,SemAcento(c));

Exerccio 8.1 Faca uma funcao que tem como par metro uma cadeia de caracteres e retorna a mesma cadeia sem a acentos.

8.2 Transformacao entre Maiusculas e Minusculas


Uma maneira de se tranformar uma cadeia de caracteres trocando cada letra por sua correspondente em mai scula e u percorrer toda a cadeia e para cada caracter colocar uma seq encia de testes, um para cada letra min scula, e troc u u a la pela correspondente letra mai scula. Um algoritmo deste tipo iria requerer uma estrutura com pelo menos 25 u condicoes, tornando o programa longo e lento. Uma maneira mais eciente de se implementar tal procedimento, e considerar a representac ao interna de cada caracter. Considerando que internamente cada letra e representada em um byte, e a representac ao das letras e seq encial u A id ia e mudar apenas aqueles caracteres que estiverem no intervalo [a, ,z]. Quando ocorrer um caracter e neste intervalo, obtemos o valor inteiro em ASCII de e seu deslocamento a partir do caracter . Em seguida, reatribumos o caracter que estiver na posicao de A mais o deslocamento .

83

program ProgramMaiusculas; string[1000]; type TipoTexto procedure Maiuscula(var texto : TipoTexto); var i,tam : integer; begin tam : length(texto); for i: 1 to tam do if (a texto[i]) and (texto[i] z) then texto[i] : chr( ord(A) ord(texto[i]) ord(a)); end; var Cadeia : TipoTexto; begin write(Entre com um texto: ); readln(cadeia); Maiuscula(cadeia); writeln(O texto em maisculo :,cadeia); u e end.

Exerccio 8.2 Faca um programa an logo ao apresentado acima, mas para tranformar uma cadeia em min sculas. a u

8.3 Casamento de Padr es o


Nesta secao vamos construir uma funcao para que dados duas cadeia de caracteres, uma chamada texto, e a outra chamada padr o, verica se existe uma ocorr ncia de padr o no texto. Caso ocorra uma ocorr ncia, a funcao retorna a e a e a posicao no texto onde ocorre o padr o, caso contr rio, a funcao retorna 0. a a Uma id ia simples de implementac ao e ir percorrendo todas as posicoes possveis de texto, de se comecar o padr o e a (i.e., posicoes ). Para cada uma destas posicoes, h uma outra estrutura a de repeticao que verica se o padr o est comecando naquela posicao. A funcao para assim que encontrar o primeiro a a padr o, ou at que todas as possibilidades tenham sido testadas. O seguinte programa implementa esta id ia. a e e

84

program ProgramaBuscaPadrao; type TipoString TipoPadrao string[1000]; string[50];

Retorna a posicao do ndice onde comeca o padrao, 0 caso n o exista. a function BuscaPadrao(var texto : TipoString; var Padrao:TipoPadrao): integer; var i,j,TamTexto,TamPadrao : integer; achou,SubsequenciaIgual : boolean; begin TamTexto : length(texto); TamPadrao : length(padrao); i : 0; achou : false; TamTexto TamPadrao) do begin while (not achou) and (i i: i1; j: 1; SubSequenciaIgual : true; while (j TamPadrao) and (SubsequenciaIgual true) do if (Padrao[j] Texto[ij 1]) then j: j1 else SubSequenciaIgual : false; achou : SubSequenciaIgual; end; if (achou) then BuscaPadrao : i else BuscaPadrao : 0; end; BuscaPadrao

var texto : TipoString; padrao : TipoPadrao; pos : integer; begin write(Entre com um texto: ); readln(texto); write(Entre com um padrao: ); readln(padrao); pos : BuscaPadrao(texto,padrao); if (pos 0) then writeln(Padrao no encontrado.) a else writeln(Padrao encontrado na posico ,pos); a end.

Obs.: Existem outros algoritmos para fazer busca de padr es que s o computacionalmente mais ecientes, como o o a algoritmo de Knuth, Morris e Pratt e o algoritmo de Boyer e Moore.

85

Exerccio 8.3 Faca uma rotina para fazer busca em uma cadeia de caracteres, mas com um padr o contendo smbolos a da seguinte maneira:

Estas duas barras indicam apenas um caracter que e o caracter barra (). Indica o caracter asterisco ( ) ? Indica o caracter de interrogacao (?).
Indica uma quantidade qualquer de caracteres (pode ser vazio). ? Indica um caracter qualquer (n o pode ser vazio). a Assim, se tivermos duas cadeias e , digamos =Algoritmos e Programacao de Computadores =Producao de Programas de Computador A seguinte tabela mostra a pertin ncia de alguns padr es nestas duas cadeias: e o Padr o a Pro cao de Computador ritmo de dor Alg Programa??o r e ma dor

A rotina deve retornar a posicao do primeiro caracter na cadeia que foi associado ao padr o, caso n o exista, retorna a a 0.

86

8.4 Criptograa por Substituicoes - Cifra de C sar e


Criptograa e a ci ncia e o estudo de escrita secreta. Um sistema criptogr co e um m todo secreto de escrita pelo e a e qual um texto legvel e transformado em texto cifrado. O processo de transformac ao e conhecido como ciframento e a transformac ao inversa e conhecida como deciframento. A id ia aqui n o e a de apresentar m todos seguros de criptograa, mas sim de trabalhar mais com as cadeias de e a e caracteres. Provavelmente os primeiros m todos de criptograa usavam m todos de substituic ao. Dado dois alfabetos e e e por outra em . Naturalmente deve haver uma funcao inversa para que o receptor da mensagem criptografada possa recuperar o texto original.

, uma funcao de criptograa por substituic ao troca um caracter de um texto

Cifra de C sar e Um caso particular do m todo de substituic ao e o seguinte. Considere um alfabeto e smbolos. Considere um inteiro , (chamado de chave). Uma funcao de criptograa a inversa (para decriptografar) s o dadas a seguir:

com
e sua


em Assim, se o alfabeto e , em , em ,

. I.e.,

, e

a funcao transforma

Este tipo de criptograa tamb m e chamado de cifra de C sar, porque J lio C sar usou com e e u e . A seguir apresentamos um programa que criptografa um texto, com o alfabeto das letras min sculas, usando este tipo de cripu tograa, transformando apenas as letras e deixando os demais smbolos intactos. program progcifracesar; string[100]; type tipostring procedure criptocesar(var texto,cifra : tipostring; k:integer); var i,tam : integer; begin cifra : ; tam : length(texto); for i: 1 to tam do begin if (texto[i] a) and (texto[i] z) then cifra : cifra chr((ord(texto[i]) ord(a) k) mod 26 ord(a)) else cifra : cifra texto[i]; end; end; criptocesar var Texto,Cripto : tipostring; begin write(Entre com uma cadeia de caracteres: ); readln(texto); criptocesar(texto,cripto,3); writeln(A texto criptografado : , cripto); e end.

87

Exerccio 8.4 Faca um procedimento para decriptografar tendo como dados de entrada a cadeia de caracteres crip tografada pelo programa acima e o valor usado de . Os m todos de substituic ao s o r pidos, mas pouco seguros. Em geral, cada lngua possui freq encias diferentes e a a u para as ocorr ncias de cada letra. e Exemplo 8.5 Em um texto em ingl s, temos em geral as seguintes freq encias esperadas para as letras: e u

Assim, para decriptografar um texto, onde o original e em ingl s, calculamos as freq encias dos smbolos no texto e u criptografado e em seguida relacionamos com as freq encias acima. Isto permite que possamos relacionar os smbolos u com os caracteres originais mais prov veis. a Exerccio 8.5 Faca um programa que l um n mero inteiro , e u Exemplos:

e escreve seu valor por extenso.

1 = um 19 = dezenove 20 = vinte 21 = vinte e um 100 = cem 111 = cento e onze 1000 = mil 2345 = dois mil trezentos e quarenta e cinco 9012 = nove mil e doze 12900 = doze mil e novecentos 100101 = cem mil cento e um 110600 = cento e dez mil e seiscentos 999999 = novecentos e noventa e nove mil novecentos e noventa e nove 1000000 = um milh o a
Sugest o: Escreva funcoes ou procedimentos convenientes que tratam de n meros: a u

ate 9 ate 19 ate 99 ate 999 ate um milh o a


Note que as funcoes para intervalos maiores podem usar as funcoes para intervalos menores. Pense com cuidado na l gica do uso da conjuncao e. o

88

Exerccio 8.6 (C lculo de dgito vericador) Muitas vezes, quando queremos representar objetos de maneira unica, a denimos um c digo para ele. Por exemplo, o sistema da Receita Federal usa o CPF para representar uma pessoa o fsica (note que o nome n o e uma boa maneira de representar um objeto, uma vez que podem ocorrer v rias pessoas a a com o mesmo nome). Certamente o banco de dados de pessoas fsicas e bem grande e uma busca de uma pessoa atrav s e de um c digo incorreto resultaria em um grande desperdcio de tempo de processamento. Assim, para diminuir as o chances de uma busca com um c digo errado, usamos dgitos vericadores nestes c digos. E o caso do CPF, onde o o os dois ultimos dgitos s o dgitos vericadores. O CPF e formado por onze dgitos a e seus dgitos vericadores s o calculados da seguinte maneira: a

O dgito

e calculado da seguinte maneira

O dgito

Caso este c lculo leve a um valor maior que 9, ent o a a

recebe o valor 0.

e calculado da seguinte maneira

Caso este c lculo leve a um valor maior que 9, ent o a a

recebe o valor 0.

Faca um programa que leia um c digo, possvelmente com caracteres ., -, / e e verique se este c digo o o representa um CPF correto.

8.5 Exerccios
1. Faca um programa para converter um n mero romano para n mero no sistema decimal. Ex.: O n mero romano u u u CMXCIX e o n mero 999 no sistema decimal. Obs.: No sistema romano para o decimal, M=1000, D=500, u C=100, L=50, X=10, V=5 e I=1. 2. Faca um programa que converte um n mero decimal em um n mero romano. u u 3. Um programador est implementando um processador de textos e quer adicionar uma facilidade para a composic ao a de cartas, colocando um comando que com apenas os dados da data (dia, m s e ano), apresenta o seguinte e cabecalho: Dia da semana , dia de m s de ano e Ex.: Colocando a data 01/01/1901, temos o seguinte cabecalho: Terca-feira, 1 de janeiro de 1901 Para implementar esta facilidade, ajude este programador construindo uma funcao que tem como par metros o a dia, o m s e o ano e retorna uma string contendo o cabecalho como no exemplo acima. Considere que as datas e est o no intervalo de 01/01/1901 a 01/01/2099. a 4. Pelo calend rio gregoriano, intitudo em 1582 pelo Papa Greg rio XIII, os anos bisextos s o aqueles cujo ano a o a s o divisveis por 4, exceto os anos que s o divisveis por 100 e n o por 400. Por exemplo, os anos 1600, 2000 a a a s o anos bisextos enquanto os anos 1700, 1800 e 1900 n o s o. Com isto, em mente, resolva o exerccio anterior a a a para considerar anos a partir de 1600. Obs.: O dia 01/01/1600 e um s bado. a 5. O programa apresentado na secao 8.4 restringe a criptograa ao alfabeto criptografar e decriptografar considerando o alfabeto formado pelo tipo byte. 6. Faca um programa contendo funcoes com os seguintes cabecalhos:

. Faca um programa para

function criptografa(str : string; k:integer):tipostring; function decriptografa(str : string; k:integer):tipostring;


89

function maiuscula(str : string):tipostring; function minuscula(str : string):tipostring; function semacentos(str : string):tipostring; function cadeialivre(str : string):tipostring;
onde tipostring e denido como: type tipostring=string[255]; As funcoes criptografa e decriptografa s o para criptografar e decriptografar usando a cifra de C sar, com deslo a e camento e o alfabeto das letras min sculas. As funcoes mai scula e min scula s o para retornar a funcao dada u u u a em mai sculo e min sculo. A funcao semacentos retorna a cadeia de caracteres str sem as letras dos acentos (ela u u preserva mai sculas e min sculas). A funcao cadeia livre transforma a cadeia de caracteres str em uma cadeia u u sem acentos e com todos as letras em min sculo. u O programa deve ler uma cadeia de caracteres e uma opcao para uma das seis operacoes acima. Caso a opcao seja para criptografar ou decriptografar, o par metro tamb m deve ser lido. Ap s a execucao de uma opcao, a a e o cadeia de caracteres resultante deve ser impressa.

90

9 Vari veis Compostas Heterog neas - Registros a e


A linguagem Pascal nos permite especicar objetos formados por diversos dados associados a eles, possivelmente de tipos diferentes. Assim, em apenas um objeto (vari vel) poderemos ter v rios outros dados como por exemplo do tipo a a string, integer, real, .... Vamos chamar este tipo de objeto por registro. Poderemos usar dois tipos de registros: um onde os diferentes tipos de dados est o armazenados em mem ria distinta e outro quando parte dos dados est o armazenados a o a em um mesmo enderec o de mem ria. o

9.1 Registros Fixos


Para se especicar um registro onde cada campo est denido em uma determinada mem ria (sem intersecao com os a o demais campos), usamos a seguinte sintaxe (que pode ser usada para denir tanto vari veis como tipos): a record Lista de Identicadores do Tipo 1 : Tipo 1; Lista de Identicadores do Tipo 2 : Tipo 2; . . . Lista de Identicadores do Tipo K : Tipo K; end Na sintaxe acima, cada identicador e chamado de Campo do registro. Al m disso, cada um dos tipos (Tipo i) e tamb m pode ser a especicac ao de outro registro. e Para acessar um campo chamado Campo1 de um registro chamado Reg1, usamos a seguinte sintaxe: Reg1.Campo1 Caso Campo1 seja tamb m um registro e contenha o campo SubCampo11, acessamos este ultimo da seguinte maneira: e Reg1.Campo1.SubCampo11 Numeros Complexos Como tipos num ricos a linguagem Pascal oferece os tipos integer e real, mas a maioria dos compiladores Pascal n o e a oferece um tipo especial para tratar n meros complexos. Como um n mero complexo e dividido em duas partes na u u forma , onde e s o n meros reais, precisamos de um tipo que contemple estes dois n meros em apenas a u u um tipo. Com isso, podemos denir um tipo chamado complexo que cont m as duas partes de um n mero complexo. e u No seguinte quadro, denimos um tipo complexo usando record e apresentamos funcoes para fazer soma, subtrac ao e multiplicac ao de n meros complexos: u

E importante observar que a sintaxe da linguagem Pascal n o permite acessar os campos da pr pria vari vel de a o a retorno de funcao. Devemos usar uma vari vel para receber um valor de retorno e em seguida atribuir esta vari vel para a a o retorno de funcao, sendo este o motivo de usarmos a vari vel nas rotinas SumComplex, SubComplex e MulComplex. a

91

program ProgComplex; type complex record a,b : real; N mero na forma (ab.i) u end; procedure LeComplex(var x : complex); Le um n mero complexo u begin writeln(Entre com um nmero complex (a+b.i) entrando com a e b: ); u readln(x.a,x.b); end; LeComplex procedure ImpComplex(x : complex); Imprime um n mero complexo u begin writeln((,x.a:5:2,+,x.b:5:2,i)); end; ImpComplex function SomComplex(x,y:complex):complex; Retorna a soma de dois n meros complexos u var z : complex; begin z.a : x.ay.a; z.b: x.by.b; SomComplex : z; end; SomComplex function SubComplex(x,y:complex):complex; Retorna a subtracao de dois n meros complexos u var z : complex; begin z.a : x.a y.a; z.b: x.b y.b; SubComplex : z; end; SubComplex function MulComplex(x,y:complex):complex; Retorna a multiplicacao de dois n meros complexos u var z : complex; begin z.a : x.a y.a x.b y.b; z.b: x.a y.bx.b y.a; MulComplex : z; end; MulComplex var x,y : complex; begin LeComplex(x); LeComplex(y); write(A soma dos nmeros complexos lidos ); ImpComplex(SomComplex(x,y)); u e write(A subtraco dos nmeros complexos lidos ); ImpComplex(SubComplex(x,y)); a u e write(A multiplicaco dos nmeros complexos lidos ); ImpComplex(MulComplex(x,y)); a u e end.

Exerccio 9.1 Um n mero racional e denido por duas partes inteiras, o numerador e o denominador. Dena um tipo u chamado racional usando a estrutura record para contemplar estas duas partes. Al m disso, faca funcoes para ler, e somar, subtrair, dividir e simplicar n meros racionais. Por simplicar, queremos dizer que o n mero racional tem u u seu n merador e denominador divididos pelo m ximo divisor comum entre eles (veja programa do exemplo 7.10). u a

92

Cadastro de Alunos Suponha que voc tenha um cadastro de alunos onde cada aluno cont m as seguintes caractersticas: Nome, Data e e de Nascimento (dia, m s e ano), RG, Sexo, Endereco (Rua, Cidade, Estado, CEP), RA (Registro do Aluno) e CR e (Coeciente de Rendimento: n mero real no intervalo ). u Note que um aluno deve ter as informacoes da data de nascimento que podem ser divididas em tr s partes (dia, e m s e ano). Sendo assim, deniremos um tipo chamado TipoData que representar uma data. Note que o mesmo e a ocorre com endereco assim, usaremos um tipo chamado TipoEndereco que representar um enderec o. Obs.: N o a a necessariamente precis vamos denir tipos separados para data e endereco, mas sempre que temos informacoes com a um tipo independente e com certa vida pr pria, e razo vel se denir um tipo particular a ele. o a O seguinte quadro apresenta a declarac ao do tipo aluno e os demais tipos necess rios para den-lo. a type TipoNome string[50]; TipoRG string[10]; TipoDia 1..31; TipoMes 1..12; integer; TipoAno TipoRua string[50]; TipoEstado string[2]; string[9]; TipoCep TipoRA string[6]; real; TipoCR TipoData record Dia : TipoDia; Mes : TipoMes; Ano : TipoAno; end; TipoEndereco record Rua : TipoRua; Cidade : TipoCidade; Estado : TipoEstado; CEP : TipoCep; end; TipoAluno record Nome : TipoNome; RG : TipoRG; DataNascimento : TipoData; Endereco : TipoEndereco; RA : TipoRA; CR : TipoCR; end; Usando as declarac oes dos tipos acima, exemplicamos, nos dois quadros seguinte, o acesso e uso destes tipos com vari veis. Os dois programas apresentados s o equivalentes. a a

93

Supondo feita as declaracoes dos tipos do quadro acima var Aluno : TipoAluno; Data : TipoData; Endereco : TipoEndereco; begin Aluno.Nome : Fulano de Tal; Aluno.RG : 9999999999; Data.Dia : 1; Data.Mes : 1; Data.Ano : 2000; Aluno.DataNascimento : Data; Endereco.Rua : R. Xxx Yyy, 999; Endereco.Cidade : Campinas; Endereco.Estado : SP; Aluno.Endereco : Endereco; Aluno.RA : 999999; Aluno.CR : 0.99; Writeln(O aluno ,Aluno.Nome, mora em , Aluno.Endereco.Cidade,-, Aluno.Endereco.Estado,.); end.

Supondo feita as declaracoes dos tipos do quadro acima var Aluno : TipoAluno;

begin Aluno.Nome : Fulano de Tal; Aluno.RG : 9999999999; Aluno.DataNascimento.Dia : 1; Aluno.DataNascimento.Mes : 1; Aluno.DataNascimento.Ano : 2000; Aluno.Endereco.Rua : R. Xxx Yyy, 999; Aluno.Endereco.Cidade : Campinas; Aluno.Endereco.Estado : SP; Aluno.RA : 999999; Aluno.CR : 0.99; Writeln(O aluno ,Aluno.Nome, mora em , Aluno.Endereco.Cidade,-, Aluno.Endereco.Estado,.); end.

Exerccio 9.2 Usando as declaracoes de tipo apresentadas no quadro da p gina 9.1, faca um cadastro de alunos com a um vetor com 100 posicoes, cada posicao do tipo TipoAluno, i.e., type TipoCadastro = record Quant: integer; Aluno: array [1..100] of TipoAluno; end O campo Quant representa a quantidade de alunos efetivamente inseridos no vetor. O programa deve manipular este cadastro com as seguintes opcoes: 1. 2. 3. 4. 5. 6. 7. Iniciar cadastro vazio (inicialmente sem elementos). Inserir um novo aluno no cadastro (se o cadastro estiver cheio, avise que n o h mem ria disponvel). a a o Ordenar o cadastro por nome em ordem alfab tica. e Ordenar o cadastro por CR, maiores primeiro. Ler o valor de um RA e imprimir os dados do aluno no cadastro com mesmo RA. Imprimir o cadastro na ordem atual. Sair do programa.

9.2 Registros Variantes


A linguagem Pascal permite que possamos denir um registro com uma parte variante. Nesta parte variante, podemos ter diferentes conjuntos de campos. A id ia aqui envolve a situacao onde o valor da caracterstica de um objeto pode e implicar em conjuntos de caractersticas diferentes. Por exemplo, suponha que temos registros com informacoes dos m veis de uma casa. Vamos supor que temos o apenas tr s tipos de m veis: (Arm rio, Mesa, Sof ). Todos os m veis considerados t m atributos em comum, que s o: e o a a o e a (cor, material, comprimento, largura, altura). Mas se o m vel for um arm rio, ent o ele tem um atributo particular que o a a e o n mero de gavetas. Se o m vel for uma mesa, ela tem outro atributo que e a forma, se circular ou retangular e o u o 94

n mero de cadeiras que usa. Se o m vel for um sof , ent o ele tem um atributo especial que e a quantidade de lugares u o a a para se sentar. Al m disso, um atributo particular de um tipo de m vel n o faz sentido para outro tipo de m vel. e o a o Se formos usar o tipo de registro xo, ent o deveriamos colocar todos os atributos no registro que especica o a m vel, cada um usando uma parte da mem ria. Mas note que se o m vel for um Arm rio, ent o o campo que indica a o o o a a quantidade de cadeiras de uma mesa e um desperdcio de mem ria e n o ser usado. A id ia de usar registros variantes o a a e e que cada conjunto de atributos particulares esteja comecando na mesma posicao de mem ria. o Uma restric ao da linguagem Pascal e que podemos ter apenas uma parte que e denida como parte variante. Sua sintaxe e denida da seguinte maneira: record Lista de Identicadores do Tipo 1 : Tipo 1; . . . Lista de Identicadores do Tipo K : Tipo K; case [CampoSelecionador:] Tipo Selecionador of Escalar 1 : (Lista de Declaracao de Campos 1); . . . Escalar P : (Lista de Declaracao de Campos P); end; A lista de identicadores dos tipos Tipo 1...Tipo K formam a parte xa do registro. A parte variante comeca depois da palavra case. O CampoSelecionador e opcional. A id ia e que caso o CampoSelecionador seja igual a Escalar 1, e ent o os campos v lidos ser o os que est o na Lista de Declaracao de Campos 1. Caso o CampoSelecionador seja a a a a igual a Escalar 2, ent o os campos v lidos ser o os que est o na Lista de Declarac o de Campos 2, e assim por a a a a a diante. O tipo do CampoSelecionador deve ser necessariamente um escalar. Note tamb m que temos apenas uma e palavra end, i.e., a palavra end termina a denicao de todo o registro. No programa do quadro seguinte apresentamos as declarac oes e algumas atribuicoes usando registro variante no exemplo dos m veis, apresentado acima. o

95

program ProgMobilia; type TipoMaterial: (Madeira, Metal, Couro, Sintetico); TipoCor: (Branco, Preto, Azul, Amarelo, Vermelho, Verde, Cinza); TipoMovel record Cor : TipoCor; Altura,Comprimento,Largura : real; Material : TipoMaterial; case Tipo : (Mesa,Sofa,Armario) of Armario : (NoGavetas:integer); Mesa : (Forma:(Circular,Retangular); NoCadeiras:integer); Sofa : (NoLugares:integer); end; var M1,M2 : TipoMovel; begin M1.Tipo : Sofa; Denindo o atributo selecionador M1.Cor : Amarelo; M1.Material : Couro; M1.Largura: 1.0; M1.Altura: 0.9; M1.Comprimento : 3.0; M1.NoLugares : 3; Atributo particular de sof a M2.Tipo : Mesa; Denindo o atributo selecionador M2.Cor : Azul; M2.Material : Madeira; M2.Largura: 1.5; M2.Altura: 1.2; M2.Comprimento : 2.0; M2.NoCadeiras : 6; Atributo particular de mesa M2.Forma : Retangular; Atributo particular de mesa ... end. O acesso aos campos do registro e feita da mesma forma como nos registros xos. A seguinte gura apresenta a congurac ao da mem ria para o registro do tipo TipoMovel apresentado no quadro acima. o
Parte Variante NoGavetas Cor Altura Comprimento Largura Material Tipo Forma NoCadeiras NoLugares Parte Fixa

Mesmo que um campo selecionador esteja indicado com um determinado tipo, todos os campos da parte variante do registro s o passveis de serem usados. I.e., a responsabilidade de manter a coer ncia dos campos da parte variante a e e do programador. Outro uso interessante deste tipo de estrutura e a n o necessidade do campo selecionador. Neste caso, podemos ter a campos que nos permitem acessar uma mesma mem ria de diferentes maneiras, sem precisar gastar mem ria com um o o campo selecionador. Tipo32bits record B1,B2,B3,B4 : byte; end; TipoConjuntoElementos record case integer of 1 : VetorByte: array[1..4 1000] of byte; 2 : Vetor32Bits: array[1..1000] of Tipo32Bits; end; Com o tipo TipoConjuntoElementos podemos estar usando no programa o campo VetorByte, mas em situacoes onde precisamos copiar um vetor deste tipo para outro ser em muitos computadores mais r pido fazer 1000 atribuic oes do a a tipo Tipo32Bits do que 4000 atribuic oes do tipo byte. Nestes casos, usaramos o campo Vetor32Bits em vez do vetor VetorByte, j que o resultado ser o mesmo. Isto se deve a arquitetura do computador, que caso seja de 32 bits, pode a a fazer transfer ncia de 32 bits por vez. e type

96

Exemplo 9.1 Uma universidade mant m registros de todos os seus alunos, que inclui os alunos de graduac o e de e a p s-graduacao. Muitos tipos de dados s o iguais para estas duas classes de alunos, mas alguns dados s o diferentes o a a de um para outro. Por exemplo: Todos os alunos possuem nome, data de nascimento, RG, e RA. Entretanto existem algumas diferencas para cada tipo de aluno. As disciplinas feitas pelos alunos de graduac o s o num ricas. Para as a a e disciplinas de p s-graduacao temos conceitos. Al m disso, alunos de p s-graduacao fazem tese, possuem orientador o e o e fazem exame de qualicacao. Assim, podemos ter a seguinte denicao de tipo para um aluno desta universidade: type NivelAluno (Grad, Pos); record TipoData dia : 1..31; mes:1..12; ano:1900..2100; end; TipoAlunoUni record nome : string[50]; RG : string[15]; DataNascimento : TipoData; ... demais campos ... case nivel: NivelAluno of Grad : (Notas: ListaNotas); Pos : (Conceitos: ListaConceitos; ExamQualif, Defesa : TipoData; Titulo: string[100], Orientador: string[50]); end; A seguir apresentamos um esboco de programa que usa esta estrutura para ler os dados de um aluno desta universi dade. var Aluno : TipoAlunoUni; begin ... write(Entre com o nome do aluno: ); readln(Aluno.nome); LeDataNascimento(Aluno.DataNascimento); ... leitura dos demais dados iguais tanto para aluno de graduacao como de pos ... case Aluno.Nivel of Grad : begin LeNotasAlunoGraduacao(Aluno.NotasGrad); end; Pos : begin LeConceitosAlunoPos(Aluno.Notas); LeDataQualicacao(Aluno.ExamQualif); LeDataDefesa(Aluno.Defesa); writeln(Entre com o ttulo da tese/dissertaco: ); readln(Aluno.Titulo); a writeln(Entre com o nome do orientador: ); readln(Aluno.Orientador); end; end; case ... end.

9.3 Comando With


A linguagem Pascal oferece uma maneira f cil para acessar os campos de um registro. Isto e feito usando-se o comando a with que permite referenciar, no escopo do comando, os campos dos registros sem refer ncia aos identicadores dos e registros. A sintaxe do comando with e a seguinte: with Lista de Vari veis de Registro do Comando ou Bloco de Comandos; a 97

Obs.: na lista de vari veis n o deve haver vari veis de mesmo tipo, ou vari veis que tenham campos com o mesmo a a a a nome. Exemplo 9.2 Vamos escrever a funcao MulComplex apresentada no quadro anterior usando o comando with. function MulComplex(x,y:complex):complex; Retorna a multiplicacao de dois n meros complexos u var z : complex; begin with z do begin a : x.a y.a x.b y.b; b : x.a y.bx.b y.a; end; MulComplex : z; end; MulComplex

9.4 Exerccios
1. Declare um tipo chamado tiporeg, denido como um tipo de registro contendo os seguintes campos: Nome, RG, Salario, Idade, Sexo, DataNascimento; onde Nome e RG s o strings, Salario e real, Idade e inteiro, sexo e char a e DataNascimento e um registro contendo tr s inteiros, dia, mes e ano. Declare um tipo de registro chamado e TipoCadastro que cont m dois campos: Um campo, Funcionario, contendo um vetor com 100 posicoes do tipo e tiporeg e outro campo inteiro, Quant, que indica a quantidade de funcion rios no cadastro. a Todos os exerccios seguintes fazem uso do tipo TipoCadastro. 2. Faca uma rotina, InicializaCadastro, que inicializa uma vari vel do tipo TipoCadastro. A rotina atribui a quan a tidade de funcion rios como zero. a 3. Faca um procedimento, LeFuncionarios, com par metro uma vari vel do tipo TipoCadastro. A rotina deve ler a a os dados de v rios funcion rios e colocar no vetor do cadastro, atualizando a quantidade de elementos n o nulos. a a a Caso o nome de um funcion rio seja vazio, a rotina deve parar de ler novos funcion rios. A rotina deve retornar a a com o cadastro atualizado. Lembre que o cadastro n o suporta mais funcion rios que os denidos no vetor de a a funcion rios. a 4. Faca uma rotina, chamada ListaFuncion rios, que imprime os dados de todos os funcion rios. a a 5. Faca duas rotinas para ordenar os funcion rios no cadastro. Uma que ordena pelo nome, OrdenaNome, e outra a que ordena pelo sal rio, OrdenaSalario. a 6. Faca uma rotina, SalarioIntervalo, que tem como par metros: um par metro do tipo TipoCadastro e dois va a a lores reais e , . A rotina lista os funcion rios com sal rio entre e . Depois de imprimir os a a funcion rios, imprime a m dia dos sal rios dos funcion rios listados. a e a a 7. Faca uma rotina que dado um cadastro, imprime o nome do funcion rio e o imposto que e retido na fonte. a Um funcion rio que recebe at R$1000,00 e isento de imposto. Para quem recebe mais que R$1000,00 e at a e e R$2000,00 tem 10% do sal rio retido na fonte. Para quem recebe mais que R$2000,00 e at R$3500,00 tem a e 15% do sal rio retido na fonte. Para quem recebe mais que R$3500,00 tem 25% do sal rio retido na fonte. a a 8. Faca uma funcao, BuscaNome, que tem como entrada o cadastro e mais um par metro que e o um nome de a um funcion rio. O procedimento deve retornar um registro (tipo tiporeg) contendo todas as informacoes do a funcion rio que tem o mesmo nome. Caso a funcao n o encontre um elemento no vetor contendo o mesmo a a nome que o dado como par metro, o registro deve ser retornado com nome igual a vazio. a 9. Faca uma rotina, AtualizaSalario, que tem como par metros o cadastro de funcion rios. A rotina deve ler do a a teclado o RG do funcion rio a atualizar. Em seguida a rotina l o novo sal rio do funcion rio. Por m, a rotina a e a a atualiza no cadastro o sal rio do funcion rio com o RG especicado. a a 10. Faca uma funcao, chamada ListaMaraja, que tem como par metro o cadastro e devolve um registro contendo os a dados de um funcion rio que tem o maior sal rio. a a 11. Faca uma rotina que tem como par metros o cadastro e o RG de um funcion rio. A rotina deve remover do a a cadastro o funcion rio que cont m o RG especicado. Lembre-se que os elementos n o nulos no vetor do a e a cadastro devem estar contguos. Al m disso, caso um elemento seja removido, a vari vel que indica a quantidade e a de elementos deve ser decrementada de uma unidade. Caso n o exista nenhum elemento no vetor com o RG a fornecido, a rotina n o modica nem os dados do vetor nem sua quantidade. a

98

12. Faca uma rotina, ListaAniversarioSexo, que tem como entrada o cadastro, tr s inteiros: dia, mes e ano, que e correspondem a uma data e um caracter (sexo) com valor F ou M. A rotina deve imprimir o nome dos funcion rios que nasceram nesta data e com sexo igual ao denido pelo par metro. a a

99

10 Recursividade
Dizemos que um objeto e dito ser recursivo se ele for denido em termos de si pr prio. o Este tipo de denicao e muito usado na matem tica. Um exemplo disto e a funcao fatorial, que pode ser denido a como: se e se

Existem muitos objetos que podem ser formulados de maneira recursiva. Este tipo de denicao permite que possa mos denir innitos objetos de maneira simples e compacta. Podemos inclusive denir algoritmos que s o recursivos, a i.e., que s o denidos em termos do pr prio algoritmo. Nesta secao veremos como poderemos usar esta poderosa a o t cnica como estrat gia para o desenvolvimento de algoritmos. e e

10.1 Projeto por Inducao


Os algoritmos recursivos s o principalmente usados quando a estrat gia de se resolver um problema pode ser feita de a e maneira recursiva ou quando os pr prios dados j s o denidos de maneira recursiva. Naturalmente exitem problemas o a a que apresentam estas duas condicoes mas que n o se e aconselhado usar algoritmos recursivos. Um problema que a pode ser resolvido de maneira recursiva tamb m pode ser resolvido de maneira iterativa. Algumas das principais e vantagens de usar recurs o s o a possibilidade de se gerar programas mais compactos, programas f ceis de se entender a a a e o uso de uma estrat gia para se resolver o problema. Esta estrat gia e a de atacar um problema (projetando um e e algoritmo) sabendo (supondo) se resolver problemas menores: Projeto por Induc o. Note que j usamos esta id ia a a e para desenvolver o algoritmo de busca bin ria. a Os objetos de programac ao que iremos usar para trabalhar com a recurs o ser o as funcoes e os procedimentos. a a Assim, uma rotina (funcao ou procedimento) e dita ser recursiva se ela chama a si mesma. Uma rotina recursiva pode ser de dois tipos: se uma rotina faz uma chamada de si mesmo no meio de sua descricao ent o a e uma rotina n o faca uma chamada a ela mesma, mas a outras rotinas que porventura podem levar a a recursiva direta; caso chamar a rotina novamente, ent o e uma rotina recursiva indireta. a

Quando uma rotina recursiva est sendo executada, podemos visualizar uma seq encia de execucoes, uma chamana u do a outra. Veja a gura 26.
Rotina R; Parmetros: Par1,...,ParP. (Instncia da rotina R) Variveis V1,V2,...,Vn. R {Chamada 1} Parmetros e Variveis locais: Par1,...,ParP,V1,...,Vn R {Chamada 2} Parmetros e Variveis locais: Par1,...,ParP,V1,...,Vn R {Chamada 3} Parm. e Variveis locais: Par1,...,ParP,V1,...,Vn R {Chamada 4} Parm. e Variveis locais: Par1,...,ParP,V1,...,Vn R {Chamada K} Par. e Var. locais: Par1,...,ParP,V1,...,Vn Instncia suficientemente pequena. Sem chamar recursivamente. Resoluo Direta.

Figura 26: Seq encia das chamadas recursivas de uma rotina u

at sua ultima chamada recursiva. e

Quando em uma determinada chamada recursiva a rotina faz refer ncia a uma vari vel ou par metro, esta est e a a a condicionada ao escopo daquela vari vel. Note que em cada uma das chamadas recursivas, as vari veis e par metros a a a (de mesmo nome) podem ter valores diferentes. Se a rotina faz refer ncia a vari vel na terceira chamada recursiva, e ` a esta ir obter e atualizar o valor desta vari vel naquela chamada. A gura 27 apresenta a congurac ao da mem ria a a o usada para a execucao do programa, chamada pilha de execucao, no momento em que foi feita a - sima chamada e recursiva. A seta indica o sentido do crescimento da pilha de execucao. 100

Configurao da Pilha de Execuo na Chamada K MC PAR VL MC PAR VL Chamada 1 Chamada 2 MC PAR VL Chamada K

MC = Memria de Controle (para retorno da chamada) PAR = Memria relativa aos parmetros da chamada VL = Memria relativa s variveis locais da chamada
Figura 27: Conguracao da pilha de execucao ap s - sima chamada recursiva. o e

10.2 Garantindo numero nito de chamadas recursivas


Note que na gura 26, da primeira chamada at a ultima, zemos chamadas recursivas. Em um programa recursivo e e muito importante se garantir que este processo seja nito. Caso contr rio, voc ter um programa que ca fazendo a e a innitas chamadas recursivas (no caso at que n o haja mem ria suciente para a pr xima chamada). e a o o Para garantir que este processo seja nito, tenha em mente que sua rotina recursiva trabalha sobre uma inst ncia a e para cada chamada recursiva que ela ir fazer, garanta que a inst ncia que ser passada a ele seja sempre mais a a a restrita que a da chamada superior. Al m disso, garanta que esta seq encia de restricoes nos leve a uma inst ncia e u a sucientemente simples e que permita fazer o c lculo deste caso de maneira direta, sem uso de recurs o. E isto que a a garantir que seu processo recursivo tem m. Vamos chamar esta inst ncia sucientemente simples (que a rotina a a recursiva resolve de maneira direta) de base da recurs o. a Nas duas guras a seguir apresentamos um exemplo de programa usando recurs o direta e indireta. a program ProgramaFatorialRecursivo; function fatorial(n : integer):integer; begin if (n 0) then fatorial : 1 else fatorial : n fatorial(n 1); end; fatorial program ProgramaParesImpares; function impar(n : integer):boolean; forward; function par(n : integer):boolean; begin if n 0 then par: true else if n 1 then par: false else par : impar(n 1); end; par function impar(n : integer):boolean; begin if n 0 then impar : false else if n 1 then impar: true else impar : par(n 1); end; impar var n : integer; begin write(Entre com um inteiro positivo: ); readln(n); if (par(n)) then writeln(Nmero ,n, par.) u e else writeln(Nmero ,n, mpar.); u e end.

var n : integer; begin write(Entre com um nmero: ); u readln(n); writeln(O fatorial de ,n, igual a ,fatorial(n)); e end.

Figura 28: Fatorial recursivo (recurs o direta). a

Figura 29: Funcoes par e impar (recurs o indireta). a

Estes dois exemplos s o exemplos fabricados de rotinas recursivas, mas que tem o prop sito de apresentar este a o tipo de rotina como uma primeira inst ncia. Naturalmente existem solucoes melhores para se implementar as funcoes a acima. Discutiremos mais sobre isso posteriormente. Agora vamos analisar melhor a funcao fatorial recursiva. Note que o par metro da funcao fatorial e um n mero a u 101

inteiro positivo . A cada chamada recursiva, o par metro que e passado e diminuido de uma unidade (o valor que a ). Assim, a inst ncia do problema a ser resolvido (o c lculo de a a e passado na pr xima chamada recursiva e o fatorial) vai diminuindo (cando mais restrito) a cada chamada recursiva. E este processo deve ser nito porque existe uma condic ao que faz com que ele pare quando a inst ncia car sucientemente pequena: caso a .

Considere o programa da gura 29. Neste programa apresentamos um exemplo de recurs o indireta. A funcao par a n o chama a si mesma, mas chama a funcao impar que em seguida pode chamar a funcao par novamente. A funcao a par (impar) retorna true caso o par metro seja par (mpar). a

Note que a primeira rotina que aparece no momento da compilacao e a funcao par. Ela faz a chamada da funcao impar. Como esta funcao impar est denida abaixo da funcao par, a compilacao do programa daria erro (por n o a a ter sido previamente denida), caso n o coloc ssemos uma informacao dizendo a cara da funcao impar. Isto pode a a ser feito colocando antes da sua chamada uma diretiva dizendo como e a cara da funcao impar. Colocando apenas o cabecalho da funcao ou procedimento, seguido da palavra forward;, estaremos dizendo ao compilador que tipo de par metros ela aceita e que tipo de resultado ela retorna. Com isso, poderemos fazer chamadas da rotina impar, mesmo a que sua especicac ao seja feita bem depois destas chamadas. Note tamb m que o tamanho das inst ncias das chamadas recursivas das funcoes par e impar tamb m diminui de e a e tamanho.

Projetando algoritmos por Inducao


Projetar algoritmos por inducao e muito parecido com o desenvolvimento de demonstrac oes matem ticas por inducao. a Primeiro verique se seu problema pode ser resolvido atrav s de problemas menores do mesmo tipo que o original. e Neste caso, ao projetar seu algoritmo, assuma que voc j tem rotinas para resolver os problemas menores. Com isto e a em mente, construa seu algoritmo fazendo chamadas recursivas para resolver os problemas menores. Lembrando que toda seq encia de chamadas recursivas deve parar em algum momento, construa uma condicao para u resolver os problemas sucientemente pequenos de maneira direta, sem fazer chamadas recursivas (base da recurs o). a Por m, simule sua rotina para ver se todos os casos est o sendo cobertos. a

10.3 Torres de Hanoi


Vamos ver um exemplo de programa recursivo, usando projeto indutivo, para se resolver um problema, chamado Torres de Hanoi. Torre de Hanoi: H um conjunto de 3 pinos: 1,2,3. Um deles tem discos de tamanhos diferentes, sendo que os a maiores est o embaixo dos menores. Os outros dois pinos est o vazios. O objetivo e mover todos os discos do primeiro a a pino para o terceiro pino, podendo se usar o segundo como pino auxiliar. As regras para resolver o problema s o. a 1. Somente um disco pode ser movido de cada vez. 2. Nenhum disco pode ser colocado sobre um disco menor que ele. 3. Observando-se a regra 2, qualquer disco pode ser movido para qualquer pino. Escreva a ordem dos movimentos para se resolver o problema.

Figura 30: Torres de Hanoi com 4 discos. Note que este problema consiste em passar os discos de um pino de origem, para um pino destino, usando mais um pino auxiliar. Para resolver o problema das torres de hanoi com discos, podemos usar a seguinte estrat gia (veja e gura 31):

1. Passar os

discos menores do primeiro pino para o segundo pino.


102

2. Passar o maior disco para o terceiro pino. 3. Passar os discos do segundo pino para o terceiro pino.

Figura 31: Estrat gia do algoritmo das Torres de Hanoi. e Note que no item 1 acima, passamos discos de um pino para o outro. Aqui e importante observar que todos estes discos s o menores que o maior disco que cou no pino. Assim, podemos trabalhar com estes a discos como se n o existisse o disco grande. Pois mesmo que algum destes discos que em cima do a disco maior, isto n o ser nenhum problema, j que todos os disco em cima do maior disco s o menores que este. Este a a a a mesmo raciocnio se propaga para se mover os discos em etapas.

Observe que resolvemos o problema maior, com discos, sabendo se resolver um problema de discos. Al m e disso, para uma inst ncia sucientemente pequena, com discos, resolvemos o problema de maneira direta (base da a recurs o). a program ProgramaHanoi; procedure Hanoi(n,origem,auxiliar,destino : integer); begin if n 0 then begin hanoi(n 1,origem,destino,auxiliar); writeln(Mova de ,origem, para ,destino); hanoi(n 1,auxiliar,origem,destino); end; end; var n : integer; begin write(Entre com a quantidade de discos no primeiro pino: ); readln(n); writeln(A seqncia de movimentos para mover do pino 1 para o pino 3 :); ue e hanoi(n,1,2,3); end.

10.4 Quando n o usar recurs o a a


H momentos em que mesmo que o c lculo seja denido de forma recursiva, devemos evitar o uso de recurs o. a a a Veremos dois casos onde o uso de recurs o deve ser evitado. a Chamada recursiva no incio ou m da rotina Quando temos apenas uma chamada que ocorre logo no incio ou no m da rotina, podemos transformar a rotina em outra iterativa (sem recurs o) usando um loop. De fato, nestes casos a rotina recursiva simplesmente est simulando a a 103

uma rotina iterativa que usa uma estrutura de repeticao. Este e o caso da funcao fatorial que vimos anteriormente e que pode ser transformado em uma funcao n o recursiva como no exemplo 7.9. a O motivo de preferirmos a vers o n o recursiva e porque cada chamada recursiva aloca mem ria para as vari veis a a o a locais e par metros (al m da mem ria de controle) como ilustrado na gura 27. Assim, a funcao fatorial recursiva a e o chega a gastar uma mem ria que e proporcional ao valor dado como par metro da funcao. Por outro lado, a funcao o a fatorial iterativa do exemplo 7.9 gasta uma quantidade pequena e constante de mem ria local. Assim, a vers o iterativa o a e mais r pida e usa menos mem ria para sua execucao. a o

A seguir apresentamos um outro exemplo onde isto ocorre. Exemplo 10.1 A funcao para fazer a busca bin ria usa uma estrat gia tipicamente recursiva com uso de projeto por a e inducao. A rotina deve encontrar um determinado elemento em um vetor ordenado. A id ia da estrat gia e tomar um e e elemento do meio de um vetor ordenado e compar -lo com o elemento procurado. Caso seja o pr prio elemento, a a o funcao retorna a posicao deste elemento. Caso contr rio, a funcao continua sua busca da mesma maneira em uma das a metades do vetor. Certamente a busca na metade do vetor pode ser feita de maneira recursiva, como apresentamos na gura 32. Na gura 33 apresentamos a vers o iterativa. a Note que a base da recurs o foi o vetor vazio que certamente e um vetor sucientemente pequeno para resolvermos o a const MAX type TipoVet 100; array[1..MAX] of real;

const MAX type TipoVet

100; array[1..MAX] of real;

function BuscaBin(var v : TipoVet; inicio,m : integer; x : real):integer; var meio: integer; begin if (inicio m) then vetor vazio BuscaBinaria : 0 nao achou else begin meio : (iniciom) div 2; if (x v[meio]) then BuscaBin : BuscaBin(v,inicio,meio 1,x) else if (x v[meio]) then BuscaBin : BuscaBin(v,meio1,m,x) else BuscaBin : meio; end; end; BuscaBin

function BuscaBin(var v : TipoVet; inicio,m : integer; x : real):integer; var pos,i,inicio,m,meio: integer; begin pos : 0; while (inicio m) and (pos 0) do begin meio : (iniciom) div 2; if (x v[meio]) then m : meio 1 else if (x v[meio]) then inicio : meio1 else pos: meio; end; BuscaBin : pos; end; BuscaBin

Figura 33: Busca bin ria n o recursivo. a a Figura 32: Busca bin ria recursivo. a problema de maneira direta. Repeticao de processamento Quando fazemos uso de recurs o com v rias chamadas recursivas ocorre na maioria das vezes que cada uma destas a a chamadas recursivas e independente uma da outra. Caso ocorram os mesmos c lculos entre duas chamadas recursivas a independentes, estes c lculos ser o repetidos, uma para cada chamada. Este tipo de comportamento pode provocar a a uma quantidade de c lculos repetidos muito grande e muitas vezes torna o programa invi vel. Um exemplo claro disto a a ocorre na funcao Fibonacci, que apesar de ter sua denicao de maneira recursiva, o uso de uma funcao recursiva causa um n mero exponencial de c lculos, enquanto a vers o iterativa pode ser feito em tempo proporcional a (o par metro u a a a da funcao). se , se e se

104

A funcao Fibonacci recursiva, apresentada a seguir, e praticamente a traducao de sua denicao para Pascal. function bo(n : integer):integer; begin if n 0 then bo: 0 else if n 1 then bo: 1 else bo: bo(n 1)bo(n 2); end;

Na gura 34, apresentamos as diversas chamadas recursivas da funcao bonacci, descrita acima, com simplicidade, chamamos a funcao Fibonacci de .
F(5) := F(4) := F(3) := F(2) := F(2) := F(3) := F(2) := F(1):=1 + F(0):=0 F(2):=1+0=1 F(3):=1+1=2

. Por

+ + F(1):=1 + F(1):=1 + F(0):=0 F(1):=1 + F(0):=0


F(2):=1+0=1

+ F(1):=1

F(2):=1+0=1 F(3):=1+1=2 F(4):=2+1=3 F(5):=3+2=5

Figura 34: Chamadas recursivas feitas por Fibonacci(5). Note que cada chamada recursiva e desenvolvida independente das chamadas recursivas anteriores. Isto provoca uma repeticao dos c lculos para muitas das chamadas. Por exemplo: quando foi feita a chamada (mais a direita na a a gura 34) para o c lculo de , poderamos ter aproveitado o c lculo de que tinha sido feito anteriormente para a se calcular . Este tipo de duplicac ao de chamadas ocorre diversas vezes. Neste pequeno exemplo j e possvel a ver que a chamada de ocorreu 5 vezes. De fato, uma an lise mais detalhada mostraria que a quantidade de a processamento feito por esta funcao e exponencial em (com base um pouco menor que 2) enquanto o processamento feito pela correspondente funcao iterativa e linear em .

105

Exerccio 10.1 Seja

inteiros tal que

faca uma funcao recursiva que calcula . Qual a relacao acima com o tri ngulo de Pascal ? Faca uma funcao que calcula o valor de a estrat gia do c lculo do tri ngulo de Pascal. e a a

. Usando a identidade

aproveitando a

Exerccio 10.2 1. Uma planilha linear e formada por um vetor (com ndices de 1 a MaxInd=100) onde cada elemento e chamado de c lula. e 2. Cada c lula da planilha pode conter um valor real ou uma f rmula simples. Para diferenciar estas duas formas, e o cada c lula apresenta um campo chamado Tipo que pode ser um dos seguintes caracteres: (n,+,-,*,/). e 3. Caso a c lula tenha Tipo igual a n, a c lula cont m um outro campo chamado valor que armazena um n mero e e e u real. 4. Se Tipo tem o caracter + (resp. -,*,/), ent o h dois campos (Ind1 e Ind2) que cont m ndices do vetor e a a e indicam que o valor deste elemento e a soma (resp. subtracao, multiplicacao e divis o) dos valores associados a as c lulas dos ndices Ind1 e Ind2. ` e Por exemplo, a f rmula simples o + 4 5 indica que o valor desta c lula e obtido somando-se os valores das c lulas 4 e 5. e e 5. Para uma ilustracao desta planilha, veja a gura seguinte:

1 (n,10) 2 (n,20) 3 (n,30) 4 (n,40) 5 (n,50) 6 (n,60) 7 1 +2 8 3 - 4 9 5 +6 10 7 * 8 11 10 / 9


Figura 35: Planilha com valores reais e f rmulas simples. o 6. Inicialmente todos as c lulas da planilha cont m um valor real igual a zero (i.e., Tipo=n). e e 7. Para obter o valor de uma c lula o programa deve proceder da seguinte maneira: e Se a c lula cont m um valor real, ent o este e o pr prio valor da c lula. Caso contr rio, obtemos os valores e e a o e a das c lulas indicadas em Ind1 e Ind2 e aplicamos a operacao correspondente. e 8. Voc pode considerar que uma c lula e referenciada no m ximo uma vez. e e a
Clulas contendo frmulas simples Clulas contendo valores reais

106

9. Para manipular os dados nesta planilha, voc dever fazer um programa para ler uma seq encia de linhas que e a u pode ter um dos seguintes formatos: Linha lida Explicacao do comando n [Ind] [Val] Coloca na c lula [Ind] o valor [Val]. e + [Ind] [Ind1] [Ind2] O valor da c lula [Ind] e o valor da c lula [Ind1] somado ao e e valor da c lula [Ind2]. e O valor da c lula [Ind] e o valor da c lula [Ind1] subtraido do e e valor da c lula [Ind2]. e O valor da c lula [Ind] e o valor da c lula [Ind1] multiplicado e e com o valor da c lula [Ind2]. e O valor da c lula [Ind] e o valor da c lula [Ind1] dividido pelo e e valor da c lula [Ind2]. e Imprime na tela o valor da c lula [Ind]. Este comando n o altera e a a planilha. Este comando (.) naliza o programa.

[Ind]

[Ind1]

[Ind2]

[Ind]

[Ind1]

[Ind2]

[Ind]

[Ind1]

[Ind2]

[Ind]

10. Exemplo: Vamos considerar que queremos avaliar o valor da f rmula o , para . Podemos considerar o valor de na c lula 1, o valor de na c lula 2, e e diferentes valores de ..., o valor de na c lula 6. Com isso, podemos montar nossa express o com os seguintes comandos: e a Linhas de entrada Coment rios a n 1 10 n 2 20 n 3 30 n 4 40 n 5 50 n 6 60 + 7 1 2 8 3 4 + 9 5 6 10 7 8 / 11 10 9 Neste ponto a planilha apresenta a conguracao da gura 35 p 11 Imprime o c lculo de a Imprime -2.73

n n p .

1 5 11

1 5


Imprime o c lculo de a

Imprime -3.23

Fim do processamento

Exerccio adicional 1: Considere agora que cada c lula pode ser referenciada mais de uma vez, mas a obtencao do e valor de cada c lula n o deve fazer uso dela mesma. Caso isto ocorra, dizemos que a planilha est inconsistente. e a a Faca uma rotina que verica se uma planilha est inconsistente. a Exerccio adicional 2: Considere agora uma planilha bidimensional, conde cada c lula deve ser especicada por e dois ndices. Faca o mesmo programa, com as devidas modicacoes, para trabalhar com este tipo de planilha.

107

10.5 Exerccios
1. Faca uma funcao recursiva para encontrar um elemento em um vetor. A rotina deve ter como par metros: o a vetor, o n mero de elementos do vetor (o primeiro elemento do vetor comeca no ndice 1), e um valor a ser u procurado. A rotina retorna o ndice do elemento no vetor, caso este se encontre no vetor, -1 caso contr rio. a 2. Faca uma rotina recursiva para imprimir os elementos de um vetor, na ordem do menor ndice primeiro. 3. Faca uma rotina recursiva para imprimir os elementos de um vetor, na ordem do maior ndice primeiro. 4. A funcao de Acherman e denida recursivamente nos n meros n o negativos como segue: u a

Se Se Se

e e

Faca um procedimento recursivo para computar a funcao de Ackerman. Obs.: Esta funcao cresce muito r pido, a assim ela deve poder ser impressa para valores pequenos de e . 5. Faca uma rotina recursiva para imprimir todas as permutac oes dos n meros de a , uma permutacao por linha. u 6. Dado uma cadeia de caracteres de comprimento , escreva uma rotina recursiva que inverte a seq encia dos u caracteres. I.e., o primeiro caracter ser o ultimo e o ultimo ser o primeiro. a a 7. Um vetor tem valores inteiros (gura (a)), onde e um inteiro positivo, . Este vetor representa uma gura hier rquica (gura (b)) da seguinte maneira: a D

A B C D E F G A
(a)

B C
(b)

F E G

Voc pode imaginar que este vetor est representando uma arvore geneal gica de 3 nveis. Infelizmente, o e a o usu rio do programa que faz uso deste vetor necessita de algo mais amig vel para ver esta estrutura. Faca uma a a rotina recursiva que dado este vetor e o valor , imprime as seguintes linhas:

G----------F---------------E----------D--------------------C----------B---------------A----------Note que ca bem mais f cil para enxergar a hierarquia visualizando este desenho. A profundiade que e impresso a cada elemento e feita controlando os espacos denidos para a profundidade de elemento na hierarquia. 8. Escreva uma funcao recursiva para calcular o m ximo divisor comum, mdc, de dois inteiros positivos da seguinte a maneira: se e mod se caso contr rio. a

9. C lculo de determinantes por co-fatores. Seja uma matriz quadrada de ordem . O Menor Complementar a , de um elemento da matriz e denido como o determinante da matriz quadrada de ordem obtida a partir da matriz , excluindo os elementos da linha e da coluna . O Co-Fator de e denido como:

O determinante de uma matriz quadrada seguinte maneira: det

pode ser calculado usando os co-fatores da linha


de ordem

da

108

O mesmo c lculo pode ser feito pelos co-fatores da coluna da seguinte maneira: a det

Faca uma rotina recursiva para calcular o determinante de uma matriz de ordem usando o m todo descrito e acima, onde a rotina tem o seguinte cabecalho: function determinante(var :TipoMatrizReal; n:integer):real; onde TipoMatrizReal e um tipo adequado para denir matriz e e a ordem da matriz. Obs.: Existem na literatura outros m todos mais ecientes para se calcular o determinante. e 10. Seja um vetor com dgitos entre e . Faca uma rotina recursiva para vericar se os elementos formam um n mero palndrome, u . Obs.: Pode considerar que os n meros podem comecar com alguns dgitos s, assim, o n mero 0012100 e palndrome. u u

109

11 Algoritmos de Ordenacao
Nesta secao vamos considerar outros algoritmos para ordenac ao: InsertionSort, MergeSort e QuickSort. Apresen taremos os algoritmos MergeSort e QuickSort implementados recursivamente e utilizando uma importante t cnica e chamada Divis o e Conquista. Estes dois algoritmos est o entre os algoritmos mais r pidos para ordenac ao usando a a a apenas comparacao entre elementos. Neste tipo de ordenac ao, o algoritmo QuickSort e o que tem o melhor tempo m dio para se ordenar seq encias em geral. e u

11.1 Algoritmo InsertionSort


O algoritmo InsertionSort tamb m usa a t cnica de projeto de algoritmo por inducao para resolver o problema, i.e., e e supondo saber resolver um problema pequeno, resolve se um maior.

Considere um vetor a . Vamos supor que j sabemos ordenar o vetor e depois inserir o elemento na posicao (com elementos, e portanto menor que ). A id ia e ordenar o vetor e correta (da o nome InsertionSort). Primeiramente apresentamos um algoritmo recursivo que implementa esta id ia. e procedure InsertionSortRecursivo(var v : TipoVetorReal;n:integer); var i : integer; aux : real; begin if n 1 then begin InsertionSortRecursivo(v,n 1); Ordena os n 1 primeiros elementos aux: v[n]; i: n; while (i 1) and (v[i 1] aux) do begin v[i] : v[i 1]; i: i 1; end; v[i] : aux; end; end; InsertionSortRecursivo

O algoritmo tem uma estrat gia indutiva e ca bem simples implement -lo de maneira recursiva. Note que a base e a da recurs o e para o vetor com no m ximo 1 elemento (nestes caso o vetor j est ordenado e portanto o problema para a a a a este vetor j est resolvido). Uma vez que desenvolvemos a estrat gia, podemos observar que podemos descrev -lo a a e e melhor de forma iterativa, uma vez que o algoritmo acima faz uma chamada recursiva no incio da rotina (veja secao 10.4). Assim, uma estrat gia mais eciente, usando duas estruturas de repeticao, e apresentada a seguir. e procedure InsertionSort(var v : TipoVetorReal;n:integer); var i,j : integer; aux : real; begin for i: 2 to n do begin aux: v[i]; j: i; while (j 1) and (v[j 1] aux) do begin v[j] : v[j 1]; j: j 1; end; v[j] : aux; end; end; InsertionSort

No caso m dio este algoritmo tamb m gasta um tempo computacional quadr tico em relacao a quantidade de e e a elementos. Por outro lado, se a inst ncia estiver quase ordenada, este algoritmo e bastante r pido. a a

110

11.2 Algoritmo MergeSort e Projeto por Divis o e Conquista a


O algoritmo MergeSort tamb m usa a estrat gia por inducao. Al m disso, o algoritmo usa de outra t cnica bastante e e e e importante chamada Divis o e Conquista. Neste tipo de projeto, temos as seguintes etapas: a

Problema sucientemente pequeno: Resolvido de forma direta. Problema nao e sucientemente pequeno:

Divis o: O problema e dividido em problemas menores. a Conquista: Cada problema menor e resolvido (recursivamente). Combinar: A solucao dos problemas menores e combinada de forma a construir a solucao do problema. No algoritmo MergeSort, a etapa de divis o consiste em dividir o vetor, com elementos, em dois vetores (suba vetores) de mesmo tamanho ou diferindo de no m ximo um elemento. No caso, um vetor a e dividido em vetores . e

Para facilitar, em vez de realmente dividir o vetor em dois outros vetores, usaremos ndices para indicar o incio e o m de um subvetor no vetor original. Assim, estaremos sempre trabalhando com o mesmo vetor, mas o subvetor a ser ordenado em cada chamada recursiva ser denido atrav s destes ndices. Caso o vetor tenha no m ximo 1 elemento, a e a o vetor j est ordenado e n o precisamos subdividir em partes menores (base da recurs o). a a a a Uma vez que o vetor (problema) foi dividido em dois subvetores (problemas menores), vamos ordenar (conquistar) cada subvetor (subproblema) recursivamente. A combinacao das solucoes dos subproblemas e feita intercalando os dois subvetores ordenados em apenas um vetor. Para isso, usaremos dois ndices para percorrer os dois subvetores e um terceiro para percorrer o vetor que receber os dois vetores intercalados, vetor resultante. A id ia e comecar os ndices no incio dos dois vetores e a e comparar os dois elementos localizados por estes ndices e atribuir no vetor resultante o menor valor. Em seguida, incrementamos o ndice que tinha o menor valor. Este processo se repete at que tenhamos intercalado os dois vetores e no vetor resultante.

No quadro seguinte apresentamos o procedimento para intercalar os vetores e na gura 36 ilustramos seu comportamento.

procedure IntercalaMergeSort(var v : TipoVetorReal; Inicio,Meio,Fim:integer); var i,j,k : integer; v1 [Inicio..Meio], v2 [Meio1..Fim] begin supondo a declaracao de Vaux no procedimento principal i: Inicio; j: Meio1; k: Inicio; while (i Meio) and (j Fim) do begin if (v[i] v[j]) then begin Sempre inserindo o menor em Vaux vaux[k]: v[j]; j: j1; end else begin vaux[k]: v[i]; i: i1; end; k: k1; end; while (i Meio) do begin vaux[k]: v[i]; Inserindo os elementos do primeiro vetor i: i1; k: k1; end; while (j Fim) do begin vaux[k]: v[j]; Inserindo os elementos do segundo vetor j: j1; k: k1; end; for k: Inicio to Fim do v[k] : vaux[k]; Copiando para o vetor original end; IntercalaMergeSort A seguir, descrevemos o algoritmo MergeSort.

111

inicio

m+1

fim

V Vaux

1
i k

0
j

6
Configurao Inicial

1
i

2
j

Vaux 0
k

3
i

2
j

Vaux 0

1
k

Preenchimento de Vaux at que um dos vetores tenha sido transferido

3 1 3 1 1 1

7
i

8 3 8 3 3 3

9 4 9 4 4 4

0 5 0
i

2 6

6
j

Vaux 0 V 1

2 7 2 2 2

2 6 6 6

4 7 7 7

5 8 8 8

6
j Transferncia do segundo vetor.

Vaux 0 V 0

5 5
i

9
k

9 9

Vaux 0

Copia do vetor j Vaux[inicio,...,fim] para o vetor V[inicio,...,fim] k

Figura 36: Intercalac ao de dois sub-vetores. procedure MergeSort(var V : TipoVetorReal; n:integer); var Vaux : TipoVetorReal; vetor auxiliar para fazer intercalacoes

Inserir rotina Intercala IntercalaMergeSort

procedure MergeSortRecursivo(var V : TipoVetorReal; inicio,m:integer); var meio : integer; begin if (m inicio) then begin Se tiver quantidade suciente de elementos meio: (minicio) div 2; Dividindo o problema MergeSortRecursivo(V,inicio,meio); Conquistando subproblema 1 MergeSortRecursivo(V,meio1,m); Conquistando subproblema 2 IntercalaMergeSort(V,inicio,meio,m); Combinando subproblemas 1 e 2 end; end; MergeSortRecursivo begin MergeSortRecursivo(V,1,n); end; MergeSort Na gura 37 apresentamos uma simulacao do algoritmo MergeSort para o vetor 7,3,8,1,4,2,6,5 . Denotamos a chamado da rotina MergeSort(V) por M(V), e a rotina IntercalaMergeSort por I( ). Se uma chamada da rotina exige chamadas recursivas, esta e substituda pelas chamadas , onde e s o as duas a partes de .

112

M( 7 I( M( 7 I( I( M( 7 I( I( I(M(7) I( I( I( 7 I( I( I( 7 I( I( (3 I( I( (3 I( I( (3 I( I( (3 I( I( (3 I( (1 I( (

, 3 , 3 , 3) ,M(3)) ,M(3) ) , 3) , 7) , 7) , 7) , 7) , 7) , 3 3 2

, 8 , 8 ,M( 8 ,M( 8 ,M( 8 ,M( 8 ,M( 8 ,I(M(8) ,I( 8 ,I( 8 , (1 , 7 , , 7 3

, 1 , 4 , 1) ,M(4 , 1)) ,M(4 , 1)) ,M(4 , 1)) ,M(4 , 1) ) ,M(4 , 1) ) ,M(4 , M(1))) ,M(4 , M(1))) ,M(4 , 1)) ,M(4 , 8)) ,M(4 , 8) ,M(4 , , 8) , (2 4 , 5

, 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , 2 , 6 , , 4 6 , , 5 7

, 5) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , 5) ) , , 6) ) 8)

(1 , 1 ,

Figura 37: Simulacao das chamadas recursivas do procedimento MergeSort para o vetor 7,3,8,1,4,2,6,5 .

11.3 Algoritmo QuickSort


O algoritmo QuickSort tamb m usa a t cnica de divis o e conquista, dividindo cada problema inicial em duas partes. e e a Neste caso, a etapa de divis o em dois subproblemas e mais sosticada mas por outro lado a etapa de combinac ao e a simples (lembrando que no algoritmo MergeSort, dividir e simples enquanto combinar e mais sosticado). Para dividir um vetor de um pivo tal que

em dois subvetores e , o algoritmo usa , e , . Uma vez que o vetor foi dividido nos subvetores e , estes s o ordenados recursivamente (conquistados). a Por m, os vetores s o combinados, que nada mais e que a concatenac ao dos vetores ordenados e . a

A etapa mais complicada neste algoritmo e a etapa de divis o, que pode ser feita ecientemente no mesmo vetor a . Primeiro escolhemos um pivo . Uma das vantagens de se escolher este pivo do pr prio vetor a o ser ordenado e que podemos implementar a estrat gia garantindo sempre que cada subvetor e estritamente menor que e o vetor original. O que faremos e tomar o pivo e dividir o vetor em subvetores e de tal maneira que a ordenac ao nal se torne o vetor , onde o operador e a concatenac ao de vetores.

Antes de apresentar o algoritmo de particionamento em um vetor, vamos apresent -lo usando um vetor auxiliar. A a implementac ao e mais simples e ca mais f cil de se entender a id ia do programa. Primeiro a rotina escolhe um pivo a e (posicao ). Troca com o primeiro elemento ( ). Em seguida percorre-se todos os demais elementos e insere os elementos menores ou iguais ao pivo, lado a lado, no incio do vetor auxiliar. Os elementos maiores que o pivo s o inseridos lado a lado a partir do m do vetor auxiliar. Por m, o a pivo e inserido na posicao intermedi ria e o vetor auxiliar e copiado para o vetor auxiliar. a

113

function ParticionaQuickSort(var v : TipoVetorReal;inicio,m:integer):integer; var esq,dir,IndicePivo:integer; Pivo:real; Supondo a declaracao de Vaux (vetor auxiliar p/ particao) no procedimento principal begin troca(v[inicio],v[(iniciom) div 2]); escolha de um pivo Pivo : v[Inicio]; Pivo ca na posicao Inicio esq: Inicio; dir: Fim; for i: Inicio1 to m do begin if (V[i] Pivo) then begin Vaux[dir] : V[i]; dec(dir); end else begin Vaux[esq] : V[i]; inc(esq); end; end; V[esq] : Pivo; esq dir for i: Inicio to m do V[i] : Vaux[i]; Copia Vaux[inicio..m] para V[inicio..m] ParticionaQuickSort : esq; end; No quadro seguinte mostramos comportamento deste algoritmo.
inicio Pivo fim

V Vaux

8 12 7 13 9 10 2 15 9 17 7
Configurao Inicial esq Pivo i dir

V 10 12 7 13 9 Vaux
esq Pivo

2 15 9 17 7

Colocando o pivo na primeira posio

dir i

V 10 12 7 13 9 Vaux
esq Pivo

2 15 9 17 7 12
dir

(12>pivo) copia. 12 no fim do vetor auxiliar.

V 10 12 7 13 9 Vaux 7
esq Pivo i

2 15 9 17 7 12
dir

(7<pivo) copia 7 no inicio do vetor auxiliar

V 10 12 7 13 9 Vaux 7
esq Pivo

2 15 9 17 7 13 12
dir

(13>pivo) copia 13 no fim do vetor auxiliar.

V 10 12 7 13 9 Vaux 7
Pivo

8 7

2 15 9 17 7 17 15 13 12
esq=dir i

V 10 12 7 13 9 Vaux 7 9 8 2 9

2 15 9 17 7

7 10 17 15 13 12
esq=dir Pivo

Copia pivo na posio intermediria. i Copia vetor auxiliar para o vetor original.

9 9

8 8

2 2

9 9

7 10 17 15 13 12 7 10 17 15 13 12
esq=dir

Vaux 7

114

Agora vamos descrever o procedimento para particionar um vetor, atrav s de um pivo e sem uso de vetor auxiliar. e Primeiramente colocaremos o pivo na primeira posicao do vetor. Para obter os subvetores e , usaremos de dois ndices no vetor original, esq e dir. Inicialmente esq comeca no segundo elemento do vetor (logo depois do pivo) e dir comeca no ultimo elemento do vetor. Em seguida, fazemos o ndice esq andar para a direita enquanto o ndice apontar para um elemento menor ou igual ao pivo. Fazemos o mesmo com o ndice dir, andando-o para a esquerda enquanto o elemento apontado por ele for maior que o pivo. Isto far com que o ndice esq v pulando todos os elea a mentos que v o pertencer ao vetor e o ndice dir pula todos os elementos que v o pertencer ao vetor . Quando os a a dois ndices pararem, estes v o estar parados em elementos que n o s o os pertencentes aos correspondentes vetores a a a e neste caso, trocamos os dois elementos e continuamos o processo. Para manter a separac ao entre e vi vel, a vamos fazer este processo sempre enquanto . Quando todo este processo terminar (i.e., quando ), iremos inserir o Pivo (que estava na primeira posicao) separando os dois vetores. O algoritmo QuickSort est descrito a na p gina 115. Existem outras implementacoes do algoritmo QuickSort que s o mais ecientes que a vers o que aprea a a sentamos, embora s o tamb m um pouco mais complicadas. a e function ParticionaQuickSort(var v : TipoVetorReal;inicio,m:integer):integer; var esq,dir,IndicePivo : integer; Pivo : real; begin troca(v[inicio],v[(iniciom) div 2]); escolha de um pivo Pivo : v[Inicio]; Pivo ca na posicao Inicio esq: Inicio1; primeiro elemento mais a esquerda, pulando o pivo dir: Fim; primeiro elemento mais a direita while (esq dir) do begin while (esq dir) and (v[esq] Pivo) do inc(esq); while (esq dir) and (pivo v[dir]) do dec(dir); if esq dir then begin troca(V[esq],V[dir]); inc(esq); dec(dir); end; end; dir esq, e esq dir 1 if v[dir] Pivo then IndicePivo : dir dir esq 1 ou dir esq else IndicePivo : dir 1; esq dir troca(v[IndicePivo],v[Inicio]); Coloca o pivo separando os dois subvetores ParticionaQuickSort : IndicePivo; end;

A seguir, apresentamos a descricao do algoritmo QuickSort. procedure QuickSort(var V : TipoVetorReal; n:integer); Declarar Vaux e inserir rotina Intercala ParticionaQuickSort procedure QuickSortRecursivo(var V :TipoVetorReal; inicio,m:integer); var IndicePivo : integer; begin if (m inicio) then begin se tem pelo menos 2 elementos IndicePivo : ParticionaQuickSort(v,Inicio,Fim); Dividindo o problema QuickSortRecursivo(V,Inicio,IndicePivo 1); Conquistando subproblema 1 QuickSortRecursivo(V,IndicePivo1,Fim); Conquistando subproblema 2 end; N o e preciso fazer nada para combinar os dois subproblemas a end; begin QuickSortRecursivo(V,1,n); end;

115

11.4 Exerccios
1. Faca uma rotina recursiva para ordenar um vetor usando a estrat gia do algoritmo SelectionSort. e 2. Faca um algoritmo para ordenar um vetor usando uma estrat gia parecida com a usada pelo algoritmo MergeSort e s que em vez de dividir em duas partes, divide em tr s partes. (I.e., se o vetor for sucientemente pequeno, o e ordena-se de forma direta. Caso contr rio este algoritmo divide o vetor em 3 partes iguais (ou diferindo de no a m ximo um elemento). Ordena recursivamente cada um dos tr s subvetores e por m o algoritmo intercala os a e tr s vetores, obtendo o vetor ordenado.) e 3. Seja elementos consecutivos de um vetor do ndice ao ndice . Projete um procedimento recursivo com o cabecalho procedure minmax(var v: TipoVetorReal; i,f: integer; var minimo, maximo: real); que retorna em minimo e maximo o menor e o maior valor que aparecem no vetor dos ndices ao ndice , respectivamente. O procedimento deve dividir o vetor em dois subvetores de tamanhos quase iguais (diferindo de no m ximo 1 elemento). a 4. Faca uma rotina recursiva para bagunc ar os elementos de um vetor (com ndices de a ). Use a funcao Random e e para gerar um n mero entre e e troque o - simo elemento com o - simo elemento. Repita recursivamente u o mesmo processo para os elementos de a . 5. (K- simo) O problema do - simo consiste em, dado um vetor com elementos, encontrar o - simo menor e e e elemento do vetor. Note que se o vetor j estiver ordenado, podemos resolver este problema obtendo o elemento a que est na posicao do vetor. Isto nos d um algoritmo que usa a ordenacao para resolver o problema do a a - simo. Entretanto, e possvel se resolver este problema de maneira mais eciente, no caso m dio. A id ia e e e e combinar duas estrat gias: e

(a) Estrat gia da busca bin ria, de descartar uma parte do vetor. e a (b) Estrat gia do algoritmo ParticionaQuickSort, que divide o vetor em tr s partes, e e cont m os elementos menores ou iguais a e cont m os elementos maiores que . onde e e

Use estas duas estrat gias para desenvolver uma funcao que dado , e , devolve o - simo menor elemento e e do vetor. 6. Faca um programa contendo procedimentos com os seguintes cabecalhos:

procedure MergeSort(var v:TipoVetor; :integer); procedure QuickSort(var v:TipoVetor; :integer); procedure SelectionSort(var v:TipoVetor; :integer); procedure InsertionSort(var v:TipoVetor; :integer); procedure aleatorio(var v:TipoVetor; :integer);
onde TipoVetor e um vetor de n meros: u type TipoVetor=array [1..30000] of integer; As rotinas MergeSort, QuickSort, InsertionSort e SelectionSort s o rotinas para ordenar usando os algoritmos do a mesmo nome. A rotina aleatorio coloca no vetor a quantidade de elementos gerados (pseudo) aleatoriamente pela funcao random(MAXINT).

O programa deve ter rotinas auxiliares para leitura e impress o de vetores. O programa deve ter um menu com a opcoes: (a) (b) (c) (d) (e) (f) (g) (h) Ler um vetor com inteiros ( tamb m e lido). Inicialmente e Gerar vetor aleat rio com elementos ( e lido). o Ordenar por MergeSort. Ordenar por QuickSort. Ordenar por InsertionSort. Ordenar por SelectionSort. Imprimir o vetor. Sair do programa.

O aluno deve cronometrar os tempos gastos pelas rotinas de ordenac ao para ordenar inteiros (pseudo) ale at rios, onde pode ser o (ou o quanto o computador suportar). Caso algum m todo seja muito lento, ignore sua execucao. N o e necess rio entregar estes tempos. e a a

116

7. (Passeio do Cavalo) Considere um tabuleiro retangular com casas. O cavalo e uma peca que anda neste tabuleiro, inicialmente em uma posicao especca. O cavalo pode andar duas casas em um dos sentidos, horizontalmente (verticalmente), e uma casa verticalmente (horizontalmente). Dado um tabuleiro , e uma posicao inicial do cavalo , e , faca um programa que resolve os seguintes itens:

(a) Diga se o cavalo consegue fazer um passeio passando por todas as casas do tabuleiro. (b) Dado uma posicao , e , diga se existe um passeio da casa de origem at a e u casa . Em caso positivo, imprima uma seq encia de movimentos que o cavalo precisa fazer para ir de para .

8. (Problema das 8 Rainhas) O problema das 8 rainhas consiste em encontrar uma disposic ao de 8 rainhas em um tabuleiro de xadrez. Uma rainha pode atacar qualquer outra que esteja na mesma linha, coluna ou diagonal do tabuleiro. Portanto o objetivo e dispor as 8 rainhas de maneira que qualquer duas delas n o se ataquem. Faca a um programa que encontra a solucao para este problema, com rainhas em um tabuleiro . 9. (Pentominos) Um Pentomino e uma gura formada juntando 5 quadrados iguais pelos lados. As 12 guras possveis, exceto por rotacoes, s o as seguintes: a

Dado um ret ngulo a , o objetivo e preencher este ret ngulo com os pentominos a apresentados acima, sem sobreposic ao entre os pentominos e sem que um pentomino ultrapasse a borda do ret ngulo. Por a exemplo, a gura seguinte mostra um ret ngulo a preenchida com pentominos. Al m disso, um pentomino e pode ser girado antes de ser encaixado no ret ngulo. Considere que voc pode usar at pentominos do tipo a e e , , onde cada e lido.

Faca um programa recursivo para resolver este problemas, dado um ret ngulo a

117

12 Passagem de funcoes e procedimentos como par metros a


A linguagem pascal permite passar rotinas como par metros. Isto nos possibilita fazer rotinas focalizadas em um a m todo de forma bem mais gen rica usando rotinas particulares para cada tipo de dado, que s o passadas como e e a par metros. a Mas antes de apresentar a sintaxe destas declaracoes de par metros, precisamos fazer algumas observac oes en a tre dois dos principais padr es da linguagem Pascal: o do Pascal Extendido e o Borland Pascal. Existem algumas o diferenc as entre estes dois padr es e a passagem de funcoes e procedimentos como par metros e uma delas. o a

12.1 Diferencas entre Borland/Turbo Pascal e Extended Pascal


Borland Pascal O padr o Borland Pascal apresenta declarac ao de novos tipos associados a procedimentos ou funcoes, a mas n o aceita a descricao do tipo do procedimento ou funcao na declaracao do par metro. Assim, para declarar a a um par metro que e um procedimento ou funcao precisamos primeiro denir tipos associados a estas rotinas e a s depois declarar as rotinas como par metros usando estes tipos. o a type IdenticadorTipoFuncao = function(Lista de Par metros): Tipo Retorno Funcao; a IdenticadorTipoProcedure = procedure(Lista de Par metros); a O tipo da rotina e igual a declarac ao do cabecalho da rotina, tirando o identicador da rotina. Com isso, podemos declarar um par metro que e uma rotina como um par metro normal. a a Obs.: No Turbo Pascal e necess rio colocar a opcao de funcoes e procedimentos com enderecamento far (Opti a ons, Compiler, Force Far Calls: On) ou colocar a diretiva $F+ antes da declaracao das rotinas. No Free Pascal e necess rio compilar o programa com a opcao de -So na linha de comando. a Extended Pascal O padr o Extended Pascal n o apresenta declarac ao de novos tipos como sendo procedimentos ou a a funcoes. Estes par metros devem ser declarados diretamente na declarac ao do par metro. a a As sintaxes das declarac oes de par metro como procedimento ou funcao e a mesma que a usada nos cabecalhos a de funcoes. Exemplo: procedure P(function F(x: real): real); No cabecalho do procedimento P, temos a declarac ao de um par metro chamado F que e uma funcao. F e uma a funcao que tem um par metro real e retorna um valor real. a O padr o do pascal extendido (Extended Pascal standard) foi completado em 1989 e e tanto um padr o ANa a SI/IEEE como ISO/IEC. Exemplo 12.1 No exemplo das guras 38 e 39, temos um procedimento chamado imprime, com 4 par metros: dois a n meros reais ( e ), uma funcao (fun) e uma string (msg). O procedimento imprime um texto que cont m os dois u e valores reais e o resultado da chamada da funcao sobre estes dois n meros. Note que esta rotina poderia ter sido u chamada com qualquer funcao que tem dois par metros com valores reais e retorna um valor real. No caso, a rotina a imprime foi chamada com as funcoes maximo, minimo e media. Note que na declaracao, foram colocados identicadores associados aos par metros. A declaracao destes tipos ne a cessita que tenhamos identicadores, mas seu nome n o precisa estar associado aos nomes dos identicadores na a descricao da rotina. A traducao de programas escritos em Extended Pascal para Borland Pascal e simples, uma vez que precisamos apenas mudar a declaracao de rotinas que s o par metros, de forma a usar tipos. J a traducao de um programa a a a escrito em Borland Pascal para Extended Pascal pode ser mais complicada, se aquele usar os tipos de rotinas dentro de estruturas como vetores e registros. A partir de agora usaremos apenas uma destas sintaxes. Escolhemos a sintaxe do Borland Pascal, uma vez que esta sintaxe pode ser usada na maioria dos compiladores Pascal, tais como: Turbo Pascal (vers o 5 em diante), Borland a Pascal, Delphi, gpc (Gnu Pascal Compiler) e Free Pascal. Acreditamos que futuras padronizac oes da linguagem Pascal venham a contemplar este tipo de sintaxe. 118

program ParametroFuncaoBorlandPascal; type TipoFuncao function(a,a : real):real; TipoMsg string[100]; function maximo(a,b : real):real; begin if (a b) then maximo : a else maximo : b; end; function minimo(a,b : real):real; begin if (a b) then minimo : b else minimo : a; end; function media(a,b : real):real; begin media : (ab)/2; end; procedure imprime(a,b : real; fun: tipoFuncao; msg : TipoMsg); begin writeln(msg, de ,a:7:2, e ,b:7:2, : , e fun(a,b):7:2); end; var n1,n2 : real; begin write(Entre com dois nmeros: ); u readln(n1,n2); imprime(n1,n2,maximo,O mximo); a imprime(n1,n2,minimo,O mnimo); imprime(n1,n2,media,A mdia); e end.

program ParametroFuncaoExtendedPascal; type TipoMsg string[100]; function maximo(a,b : real):real; begin if (a b) then maximo : a else maximo : b; end; function minimo(a,b : real):real; begin if (a b) then minimo : b else minimo : a; end; function media(a,b : real):real; begin media : (ab)/2; end; procedure imprime(a,b : real; function fun(a,a : real):real; msg : TipoMsg); begin writeln(msg, de ,a:7:2, e ,b:7:2, : , e fun(a,b):7:2); end; var n1,n2 : real; begin write(Entre com dois nmeros: ); u readln(n1,n2); imprime(n1,n2,maximo,O mximo); a imprime(n1,n2,minimo,O mnimo); imprime(n1,n2,media,A mdia); e end.

Figura 38: Exemplo de rotinas como par metros em Bor- Figura 39: Exemplo de rotinas como par metros em Exa a land Pascal tended Pascal

119

12.2 M todo de bissecao para encontrar razes de funcoes e


Um m todo para encontrar solucoes de uma funcao e atrav s do m todo de bissecao. Para usar estes m todo devemos e e e e ter:

Uma funcao para poder calcular um valor de tal que Um intervalo de busca da solucao , de tal forma que

. .

Note que o segundo item nos garante que ou e solucao, ou e solucao ou deve existir uma solucao tal que (veja a gura seguinte).

no intervalo

f(x)

f(a) a f(b) m b x

A id ia e dividir este intervalo em duas partes pelo meio, e das condicoes seguintes: 1. 2.

, digamos e

. Devemos ter pelo menos uma

Se ent o necessariamente temos uma solucao dentro do intervalo a e repetimos o mesmo processo, desta vez iterando com o intervalo no lugar do intervalo . Caso contr rio, teremos uma solucao a dentro do intervalo e continuamos o processo neste intervalo. A cada iteracao o tamanho do intervalo diminui para metade do tamanho do intervalo anterior. Assim, o processo pode parar quando o comprimento do intervalo for sucientemente pequeno.

Com isto, podemos escrever uma rotina que encontra uma solucao para uma certa funcao (recebida pela rotina como par metro) e o intervalo de atuacao. a O m todo de bissecao j pressup e um intervalo e a o v lido tal que . Para encontrar tal intervalo, a podemos comecar com um intervalo sucientemente grande , dividimos este intervalo em partes pequenas, digamos em partes iguais, , , , e vericamos se algum destes intervalos digamos , e tal que . Caso exista tal intervalo, usamos o m todo da bissecao no intervalo, caso e contr rio terminamos sem sucesso. Naturalmente podem ocorrer inst ncias onde este m todo n o encontra solucoes, a a e a mesmo que tal solucao se encontre em um dos intervalos iniciais. Al m disso, dicilmente este m todo ir encontrar e e a solucoes de funcoes n o negativas ou n o positivas. a a

O programa a seguir apresenta a implementac ao do m todo descrito acima. e

120

program ProgramaBicessao; const EPS 0.000000001; type TipoFuncaoReal function (x:real):real; Encontrando o intervalo, retorna sucesso true e a0 e ak atualizados com o intervalo, caso contr rio, retorna com a sucesso false procedure EncontraIntervalo(f: TipoFuncaoReal ; var a0,ak: real;k:integer; var sucesso: boolean); var delta,a: real; begin a: a0; delta : (ak a)/k; while (a ak) and (f(a) f(adelta) 0) do a : a delta; if (f(a) f(adelta) 0) then sucesso : false else begin a0 : a; ak : adelta; sucesso : true; end; end;

funcao real: f(x) (x 5) (x 2) (x 3) (x 4) (x 6) function f2(x : real):real; begin f2 : (x 5) (x 2) (x 3) (x 4) (x 6); end; f1

var sucesso : boolean; raiz: real; begin bicessao(f1, 10,10,sucesso,raiz); if (sucesso) then writeln(Uma soluco de f(x)=x3+2.x2a x+10 : , e raiz:10:8); bicessao(f2, 10,10,sucesso,raiz); if (sucesso) then writeln(Uma soluco de , a f(x)=(x-5)*(x-2)*(x-3)*(x-4)*(x6) : , e raiz:10:8); end.

Encontrando solucao, retorna sucesso true e a raiz em solucao, cc. sucesso false procedure bicessao(f: TipoFuncaoReal; a,b:real; var sucesso:boolean;var solucao:real); var m : real; begin EncontraIntervalo(f,a,b,1000,sucesso); if (sucesso) then begin while (abs(a b) EPS) do begin m : (ab)/2; 0) then b: m if (f(a) f(m) else a: m; end; solucao : m; end; end;

funcao real: f(x) x3 2.x2 x 10 function f1(x : real):real; begin f1 : x x x 2 x x x 10; end; f1

121

Exerccio 12.1 (Integral de funcoes) O c lculo da integral de uma curva denida pode ser calculado por aproximac es a o utilizando-se o m todo dos trap zios. Neste m todo dividimos o intervalo de integracao em partes iguais, digamos e e e divididas pelos pontos e e calculamos a area do trap zio substituindo a curva em cada intervalo por uma reta ligando os pontos e , (veja a gura seguinte). O valor aproximado da integral denida e a soma das areas dos trap zios. e

onde

Area de cada trap zio e

A1

A2

A3

A4

A5

Naturalmente, quanto maior o valor de , melhor a aproximacao da integral. Faca um programa contendo uma funcao chamada integral com o seguinte cabecalho: function integral(f: TipoFuncaoReal; a,b: real; n: integer): real; onde TipoFuncaoReal e um tipo de funcao como declarado como programa de bicess o; os valores e denem o a ; e o valor indica a quantidade de intervalos a ser usado no m todo de aproximacoes. e intervalo de integracao:

x0

x1

x2

x3

x4

x5

12.3 Ordenacao usando funcoes de comparacao


No exemplo 6.9 vimos como podemos ordenar um vetor colocando na posicao correta o maior elemento n o consi a derado a cada instante. Note que o algoritmo faz a selecao do maior elemento fazendo v rias comparacoes entre dois a elementos (se menor, igual ou maior). Em muitos problemas, cada elemento do vetor cont m informac oes de um e objeto que cont m em geral v rias caractersticas e estes podem ser ordenados de v rias maneiras, dependendo das e a a caractersticas consideradas. Por exemplo, vamos considerar que uma universidade, chamada UNICOMP, armazena os dados dos alunos usando o tipo TipoAluno, apresentado na p gina 93. Por simplicidade, vamos considerar os campos Nome, DataNascimento e a CR. Para efeitos de busca e classicac ao, a universidade necessita que estes dados possam estar em ordem alfab tica e pelo nome ou listados pelos alunos mais novos primeiro ou listados ordenados pelo CR em ordem decrescente. Como e apenas a comparacao entre elementos que muda, podemos fazer apenas uma rotina de ordenac ao e usar diferentes funcoes de comparacao para decidir qual aluno vem antes de outro. A funcao para comparar dois elementos tem o seguinte formato: function Compara(var , : TipoAluno):char; a funcao retorna , ou , se e menor, igual ou maior que , respectivamente. A seguinte funcao compara os nomes de dois alunos: function ComparaNome(Aluno1,Aluno2 : TipoAluno):char; begin if (Aluno1.Nome Aluno2.Nome) then ComparaNome : < else if (Aluno1.Nome Aluno2.Nome) then ComparaNome : > else ComparaNome : =; end;

122

A seguir, vamos descrever a nova rotina de ordenacao (atualizada a partir do exemplo 7.13) que pode usar a funcao de comparac ao por nome, dado acima. const MAX 100; type Incluir tipos em TipoAluno TipoVetorAluno array[1..MAX] of TipoAluno; TipoFuncaoComparacao function (a,b: TipoAluno):char; procedure SelectionSortAluno(fcomp: TipoFuncaoComparacao; var v : TipoVetorAluno; n:integer); var m,imax : integer; procedure TrocaAluno(var Aluno1, Aluno2 : TipoAluno); var AlunoAux : TipoAluno; begin AlunoAux: Aluno1; Aluno1: Aluno2; Aluno2: AlunoAux; end;

function IndMaxAluno(fcomp : TipoFuncaoComparacao; var v:TipoVetorAluno; n:integer):integer; var i, Ind : integer; begin if (n 0) then Ind : 0 else begin Ind : 1; O maior elemento comeca com o primeiro elemento do vetor for i: 2 to n do if (fcomp(v[Ind],v[i]) <) then Ind: i; end; IndMaxAluno : Ind; end; begin for m: n downto 2 do begin imax : IndMaxAluno(fcomp,v,m); TrocaAluno(v[m],v[imax]); end; end; Note que a mudanca (al m do tipo de dado) do programa apresentado no exemplo 6.9 est no uso da funcao de e a comparacao entre dois elementos, que e um par metro usado na chamada da rotina SelectionSortAluno. Assim, a a chamada da rotina SelectionSortAluno(ComparaAluno, V, n) far a ordenacao do vetor , com elementos, usando a a funcao de comparacao ComparaAluno. I.e., o vetor car em ordem alfab tica pelo nome. a e

Agora, para fazer a ordenac ao em ordem crescente de idade (mais novos primeiro), podemos usar o mesmo progra ma usando apenas uma funcao de comparac ao diferente. Mas note que agora queremos os de maior data de nascimento primeiro. Para isso, vamos tapear a rotina de ordenacao, usando uma funcao de comparac ao que responde dizendo que o aluno e menor ( ) que o aluno se a data de nascimento de for na verdade maior que a de , e vice versa. Isto far com que a rotina ordene de maneira invertida. Lembre que a rotina de ordenac ao foi feita de maneira que os a menores cassem nas primeiras posicoes; assim, se usamos a rotina de comparacao que diz que um elemento e menor quando na verdade e maior, e vice-versa, obteremos uma ordenacao com os maiores nas primeiras posicoes. A rotina de comparac ao de alunos por data de nascimento (mais novos primeiro) pode ser dada pela seguinte funcao: function ComparaIdade(Aluno1,Aluno2 : TipoAluno):char; begin if (Aluno1.DataNascimento.Ano Aluno2.DataNascimento.Ano) then ComparaIdade : > else if (Aluno1.DataNascimento.Ano Aluno1.DataNascimento.Ano) then ComparaIdade : < else if (Aluno1.DataNascimento.Mes Aluno1.DataNascimento.Mes) then ComparaIdade : > else if (Aluno1.DataNascimento.Mes Aluno1.DataNascimento.Mes) then ComparaIdade : < else if (Aluno1.DataNascimento.Dia Aluno1.DataNascimento.Dia) then ComparaIdade : > else if (Aluno1.DataNascimento.Dia Aluno1.DataNascimento.Dia) then ComparaIdade : < else ComparaIdade : =; end; Note tamb m que o uso da funcao de comparacao permite fazer comparacoes de elementos levando em considerac ao e v rios dados para desempate. O programa nal e dado a seguir. a

123

program OrdenaAlunoIdadeNome; const MAX 100; type Incluir tipos em TipoAluno TipoVetorAluno array[1..MAX] of TipoAluno; TipoFuncaoComparacao function (a,b: TipoAluno):char; function ComparaNome(Aluno1,Aluno2 : TipoAluno):char; var Nome1,Nome2 : TipoNome; begin if (Aluno1.Nome Aluno2.Nome) then ComparaNome : < else if (Aluno1.Nome Aluno2.Nome) then ComparaNome : > else ComparaNome : =; end; ComparaNome function ComparaIdade(Aluno1,Aluno2 : TipoAluno):char; o begin Inserir c digo da funcao ComparaIdade, visto anteriormente. end;

procedure SelectionSortAluno(fcomp: TipoFuncaoComparacao; var v : TipoVetorAluno; n:integer); var m,imax : integer; procedure TrocaAluno(var Aluno1, Aluno2 : TipoAluno); var AlunoAux : TipoAluno; begin AlunoAux: Aluno1; Aluno1: Aluno2; Aluno2: AlunoAux; end; function IndMaxAluno(fcomp : TipoFuncaoComparacao; var v:TipoVetorAluno; n:integer):integer; var i, Ind : integer; begin if (n 0) then Ind : 0 else begin Ind : 1; O maior elemento comeca com o primeiro elemento do vetor for i: 2 to n do if (fcomp(v[Ind],v[i]) <) then Ind: i; end; IndMaxAluno : Ind; end; begin for m: n downto 2 do begin imax : IndMaxAluno(fcomp,v,m); TrocaAluno(v[m],v[imax]); end; end; procedure ImprimeVetorAluno(var v : TipoVetorAluno; n:integer; msg:TipoString); begin Exerccio: Rotina para imprimir os Alunos na tela end; procedure LeVetorAluno(var v:TipoVetorAluno;var n:integer); begin Exerccio: Rotina para ler Alunos end; var i, n, Ind : integer; V : TipoVetorFunc; begin LeVetorAluno(V,n); SelectionSortFunc(comparaNome,v,n); ImprimeVetorFunc(v,n,Ordenados por nome (ordem alfabtica)); e SelectionSortFunc(comparaIdade,v,n); ImprimeVetorFunc(v,n,Ordenados por idade (mais novos primeiro)); end.

124

Exerccio 12.2 A universidade UNICOMP deseja dar bolsas de estudo para os alunos que apresentam melhores valo res do Coeciente de Rendimento (CR). Assim, faca uma funcao de comparacao para ordenar os alunos, colocando os de maiores valores do CR primeiro. Caso dois alunos possuam o mesmo valor de CR, estes devem ser desempatados pelo RA.

12.4 Exerccios
1. E dado uma funcao e um intervalo tal que . Faca uma funcao recursiva que encontra uma solucao usando o m todo da bissecao (dividindo sucessivamento o intervalo ao meio) e tal que . A funcao pode dar o resultado dentro de uma precis o de (diferenc a entre a solucao a verdadeira e a solucao encontrada pela rotina) e deve ter o seguinte cabecalho: function Bissecao( : TipoFuncao; : real): real; onde e a funcao para a qual calcularemos a solucao e dene o intervalo que cont m a solucao. O tipo e TipoFuncao e denido como: type TipoFuncao = function (x:real):real;

2. Para calcular a integral

pode-se usar a aproximacao de uma soma nita de valores amostrados:

onde

e Escreva uma funcao que calcule a integral de uma funcao usando o m todo de Simpson. A funcao tem como par metros: a funcao , o intervalo de integrac ao a e o valor . A funcao retorna a aproximac ao da integral de no intervalo . Aplique sua funcao para calcular as integrais:

e a dist ncia entre dois pontos de amostragem adjacentes. O a valor da integral e aproximado pela seq encia u , que converge se a funcao e sucientemente bem comportada (suave). O m todo acima e chamado de m todo de Simpson. e e

O n mero de pontos de amostragem e e u

3. Faca um programa para manipular um cadastro de alunos, nos moldes do exemplo da secao 12.3, de maneira a ter as seguintes opcoes: (a) Iniciar cadastro vazio (inicialmente o cadastro j comeca vazio (n mero de elementos igual a zero)). a u (b) Inserir um novo elemento no cadastro (se o cadastro estiver cheio, avise que n o h mem ria disponvel). a a o (c) Ordenar o cadastro por nome em ordem alfab tica. e (d) Ordenar o cadastro por idade, mais novos primeiro. (e) Ordenar o cadastro por idade, mais velhos primeiro. (f) Ordenar o cadastro por RA, ordem crescente. (g) Ordenar o cadastro por CR, maiores primeiro. Sempre que o programa executar alguma destas opcoes, ele deve imprimir a lista de alunos na ordem do vetor e imprimir logo em seguida o menu antes de pedir por nova opcao. Al m disso, o programa deve usar apenas de e uma rotina de ordenacao para ordenar os alunos. Os diferentes tipos de ordenac ao s o denidos usando funcoes a de comparacao especcas para cada tipo de ordenacao que devem ser passadas como par metros da rotina de a ordenac ao.

125

13 Arquivos
Quando um programa trabalha com dados que est o na mem ria RAM, estes s o apagados sempre que o computador a o a e desligado ou mesmo quando o programa e terminado. Mas muitas vezes queremos que os dados se mantenham em mem ria para que possam ser processados posteriormente. Neste caso, e necess rio que estes dados estejam gravados o a em uma mem ria n o vol til. Este e o caso de se usar arquivos, que permite gravar os dados e recuper -los sem o a a a necessidade de reentrada dos dados. Outra raz o para se usar arquivos e que estes s o armazenados em mem ria a a o secund ria, discos e tas magn ticas, que t m em geral uma capacidade muito maior de armazenamento. a e e Podemos distinguir os arquivos suportados pela linguagem Pascal como sendo de dois tipos: arquivos de texto e arquivos bin rios. a

13.1 Arquivos Texto


Quando trabalhamos com arquivos de texto, supomos que n o iremos trabalhar com qualquer tipo de dado, mas com a dados que nos representem um texto. Neste caso, vamos supor que os dados de um texto est o organizadas por linhas, a onde cada linha cont m uma seq encia de caracteres ASCII que podem ser impressos. Exemplo destes caracteres s o e u a as letras (mai sculas/min sculas/com acento), dgitos e os caracteres especiais (como: $, %, #, , ?, ...). Al m disso, um u u e arquivo texto cont m alguns caracteres de controle, como por exemplo os caracteres que indicam o m de uma linha. e A unidade b sica em arquivos texto e o caracter. a Um programa em Pascal considera o vdeo e o teclado como arquivos texto especiais. O vdeo como um arquivo onde podemos apenas escrever e o teclado como um arquivo que podemos apenas ler. Existem algumas diferencas entre um arquivo texto feito para o sistema operacional MS-DOS e um arquivo texto feito para o ambiente UNIX. Um arquivo texto no ambiente MS-DOS usa dois caracteres para especicar que comecar a a pr xima linha, o caracter Carriage Return seguido do caracter Line Feed, que tem os c digos internos 13 e 10, o o respectivamente. No caso dos arquivos texto em ambiente UNIX, a pr xima linha comeca apenas depois de um o caracter, Line Feed, de c digo interno 10. o Quando trabalhamos com arquivos, e importante considerar que todo arquivo tem um indicador da posicao corrente de leitura e escrita (gravacao). Inicialmente este indicador est posicionado no primeiro byte do arquivo. Se for a realizada uma operacao de leitura ou gravacao de bytes, ent o o indicador da posicao corrente no arquivo se deslocar a a destes bytes para frente. Al m disso, existe uma posicao que ser a seguinte do ultimo byte do arquivo (posicao de e a m de arquivo) e n o poderemos ler nenhum byte seguinte, mas poderemos escrever outros bytes a partir desta posicao. a

A sintaxe para declarar uma vari vel para trabalhar com arquivos texto e a seguinte: a var Lista de Identicadores de Arquivos: Text; O identicador declarado desta forma ser usado para trabalhar com um arquivo que est gravado em disco. O a a arquivo que est em disco (ou outro meio de armazenamento secund rio) tem um nome e a primeira operacao para a a trabalhar com ele e associar este nome (nome externo) com a vari vel de arquivo. O comando para fazer esta associac ao a e a seguinte: assign(Vari vel de arquivo,Nome Arquivo Externo); a Esta operacao apenas diz para o programa qual o arquivo (que est em disco) que iremos trabalhar pela vari vel a a de arquivo. Mas isto n o faz com que os dados que est o no arquivo (em disco) j estejam disponveis para serem a a a manipulados. Para isso, precisamos dar outro comando que de fato ir possibilitar esta manipulac ao. Informalmente, a este comando ir abrir o arquivo para ser manipulado. Podemos ter tr s tipos de comandos para abrir um arquivo a e texto, um que e somente para leitura dos dados, outro que e para escrita em um arquivo novo e outro que e para escrita a partir do m do arquivo texto. Para abrir um arquivo somente para leitura (a partir do incio do arquivo), usamos o seguinte comando: reset(Vari vel de arquivo); a Note que n o precisamos dar o nome externo do arquivo, uma vez que isto j foi feito pelo comando assign. Neste a a caso, o indicador de posicao corrente ca apontando para o incio do arquivo. Para abrir um arquivo somente para escrita comecando com um arquivo vazio, usamos o seguinte comando:

126

rewrite(Vari vel de arquivo); a Se j existir um arquivo com o mesmo nome, o arquivo que existia antes e reinicializado como arquivo vazio. Como a neste caso sempre comecamos com um arquivo vazio, o indicador da posicao corrente comeca no incio do arquivo. Por m, para abrir um arquivo somente para escrita a partir do m do arquivo (i.e., o conte do inicial do arquivo e u preservado) usamos o seguinte comando: append(Vari vel de arquivo); a Neste caso, o indicador da posicao corrente no arquivo ca inicializado como o m de arquivo. O comando de abertura de arquivo, em um programa Pascal, usa uma mem ria auxiliar (em mem ria RAM) o o para colocar parte dos dados que s o lidos/escritos do/para o arquivo. Isto e porque em geral, qualquer mecanismo de a armazenamento secund rio (disco rgido, tas magn ticas, disquetes,...) funcionam atrav s de meios eletro-mec nicos, a e e a o que forca com que a leitura e escrita de dados usando estes dispositivos seja muito lenta. Assim, sempre que uma operacao de leitura ou escrita e feita, ela n o e feita diretamente no arquivo, mas sim nesta mem ria auxiliar (que e a o extremamente r pida). Caso algum comando faca uso de um dado do arquivo que n o est nesta mem ria auxiliar, o a a a o programa usa servic os do sistema operacional para atualizar o arquivo com a mem ria auxiliar e colocar na mem ria o o auxiliar os novos dados que o programa precisa manipular. Se um programa for nalizado sem nenhum comando especial, os arquivos que ele estiver manipulando poder o a n o estar atualizados corretamente, j que parte dos dados pode estar na mem ria auxiliar. Assim, quando n o precia a o a sarmos mais trabalhar com o arquivo, e necess rio usar de um comando que descarrega todos os dados desta mem ria a o auxiliar para o arquivo propriamente dito (al m de liberar esta mem ria auxiliar para futuro uso do sistema operacioe o nal). Isto e feito com o comando close da seguinte maneira: close(Vari vel de arquivo); a Uma vez que o arquivo foi aberto, poderemos ler e gravar dados (dependendo do modo como o arquivo foi aberto) no arquivo. Lembrando que para ler do teclado, usamos o comando read/readln, e para escrever no vdeo, usamos o comando write/writeln. Do mesmo jeito, para ler e escrever (gravar) em um arquivo texto, usamos os comandos read, readln, write e writeln. A unica diferenc a e que colocamos um par metro a mais nestes comandos, especicando em a qual arquivo ser feita a operacao de leitura ou escrita. a Assim, vamos supor que em determinado momento os dados do arquivo e a posicao corrente no arquivo est o a como apresentados no quadro seguinte, onde apresentamos as tr s primeiras linhas do arquivo e a posicao corrente est e a indicado por uma seta.
1 2 3 Esta a primeira linha do arquivo texto 123 456 3.14 999 Esta a segunda linha Terceira Linha

se dermos o comando: read(Vari vel de arquivo, a ); ); e entr ssemos pelo a , respectivamente, onde , e s o vari veis reais, teremos o mesmo resultado se d ssemos o comando read( a a e

teclado com os dados 456 3.14 999 . I.e., as vari veis , e car o com os valores a a , e e o indicador da posicao corrente e atualizado de maneira a car com a seguinte congurac ao:
1 2 3 Esta a primeira linha do arquivo texto 123 456 3.14 999 Esta a segunda linha Terceira Linha

Outra rotina importante e a funcao para vericar se estamos no m de arquivo, pois neste caso n o poderemos ler a mais nenhum dado a partir do arquivo texto. A funcao para fazer esta vericacao e a funcao booleana eof, cuja sintaxe e: eof(Vari vel de arquivo) a A funcao eof retorna verdadeiro (true) caso o indicador da posicao corrente esteja no m do arquivo e falso (false) caso contr rio. a

127

Al m do comando read, tamb m podemos usar o comando readln. Neste caso, os dados s o lidos como no e e a comando read, mas se ainda existir alguns dados na mesma linha corrente do arquivo texto, estes s o ignorados e o a indicador da posicao corrente ca situado no primeiro caracter da pr xima linha. o Se a vari vel a ser lida e uma cadeia de caracteres (string), a quantidade de caracteres e denida pelo n mero a u de caracteres que ela foi denida. Al m disso, se a rotina read for aplicada para ler uma cadeia de caracteres e a e quantidade de caracteres a ler ultrapassa a linha do arquivo, o indicador da posicao corrente ca posicionado no m desta linha. I.e., se uma pr xima leitura com o comando read for usado para ler uma string, o indicador de posicao o corrente se manter naquele mesmo m de linha. Neste caso, para comecar a ler a pr xima linha como string, o a o comando de leitura anterior deve ser o readln. Caso a leitura seja de algum outro tipo (integer, real, ...), mesmo que se use o comando read, e o dado n o estiver na linha corrente, o comando busca o dado a ser lido nas pr ximas linhas. a o Os comandos de impress o (gravac ao), write e writeln t m resultado semelhante aos correspondentes comandos a e para imprimir na tela. A diferenca e que o resultado da impress o ser feita no arquivo. Al m disso, um arquvo texto a a e n o tem a limitacao de n mero de colunas, como temos em um vdeo. Lembrando que para ir para a pr xima linha, a u o em um arquivo texto MS-DOS s o usados os caracteres Carriage Return e Line Feed, enquanto em arquivos Unix, e a usado apenas o caracter Line Feed. Em um arquivo texto, como em um arquivo bin rio, podemos obter a quantidade de elementos b sicos do arquivo a a atrav s da funcao lesize, cuja sintaxe e: e lesize(Vari vel de arquivo) a e retorna a quantidade de elementos b sicos do arquivo. a Exemplo 13.1 O seguinte programa l o nome de um arquivo texto e o lista na tela, especicando o n mero de cada e u linha. Por m, o programa tamb m imprime o n mero de linhas e o n mero de bytes do arquivo. e u u program ListaArquivo(input,output); type TipoString string[255]; procedure LeArquivoTexto(NomeArquivo:TipoString); var ArquivoTexto : text; linha : TipoString; nlinha : integer; begin assign(ArquivoTexto,NomeArquivo); Associar o nome do arquivo com a vari vel a reset(ArquivoTexto); Abrir o arquivo para leitura nlinha: 0; while not eof(ArquivoTexto) do begin nlinha: nlinha1; readln(ArquivoTexto,linha); writeln([,nlinha:3,] ,linha); end; writeln(NomeArquivo, tem ,nlinha, linhas e usa ,lesize(ArquivoTexto), bytes.); close(ArquivoTexto); Fecha o arquivo end; LeArquivoTexto var NomeArq : TipoString; begin write(Entre com o nome do arquivo a listar: ); readln(NomeArq); LeArquivoTexto(NomeArq); end.

128

Exemplo 13.2 O programa seguinte elimina os espacos em branco repetidos (seguidos) de um arquivo texto. program Brancos; var linha : String; nomeEntrada, nomeSaida : String[20]; arqEntrada, arqSaida : Text; procedure EliminaBrancos(var s: String); var i,desl,n : Integer; p : char; begin desl : 0; n : Length(s); p : x; for i: 1 to n do begin if s[i] then s[i desl] : s[i] else if p then s[i desl] : s[i] else inc(desl); p : s[i] end; Setlength(s,n desl) end; EliminaBrancos

begin Write(Forneca o nome do arquivo de entrada: ); Readln(nomeEntrada); Write(Forneca o nome do arquivo de sada: ); Readln(nomeSaida); AssignFile(arqEntrada,nomeEntrada); AssignFile(arqSaida,nomeSaida); Reset(arqEntrada); Rewrite(arqSaida); while not eof(arqEntrada) do begin Readln(arqEntrada,linha); EliminaBrancos(linha); Writeln(arqSaida,linha) end; Close(arqSaida) end.

129

Exerccio 13.1 Os professores do curso de Algoritmos e Programacao de Computadores desenvolveram uma lin guagem assembler, chamada HIP, para um computador hipot tico com conjunto de comandos bastante reduzido. A e linguagem e voltada para manipulacao de inteiros e tem 16 instrucoes que explicitaremos a seguir: O unico tipo de dado existente em HIP e o tipo inteiro. Cada valor inteiro deve ser armazenado em uma vari vel representada por um a identicador que usa apenas uma letra. Al m de vari veis, os identicadores podem representar labels que podem ser e a pontos de desvios do programa.

var Ident Faz a declaracao da vari vel Ident , inicializada com valor 0 (zero). a ler Ident L o valor da vari vel Ident pelo teclado. e a atr Ident Constante Atribui a constante Constante (n mero inteiro) para a vari vel Ident . u a mov Ident Ident1 Atribui o valor da vari vel Ident1 para a vari vel Ident . a a sum Ident Ident1 Ident2 Soma os valores das vari veis Ident1 e Ident2 e atribui o resultado na vari vel Ident . a a sub Ident Ident1 Ident2 Subtrai o valor da vari vel Ident1 do valor da vari vel Ident2 e atribui o resultado na vari vel a a a mul Ident Ident1 Ident2 Multiplica os valores das vari veis Ident1 e Ident2 e atribui o resultado na vari vel Ident . a a div Ident Ident1 Ident2 Divide o valor da vari vel Ident1 por Ident2 e atribui a parte inteira na vari vel Ident . a a mod Ident Ident1 Ident2 Este comando atribui o resto da divis o inteira de Ident1 por Ident2 na vari vel Ident . a a lab Ident Este comando dene um label (ponto de desvio do programa) com o nome Ident . des Ident Este comando desvia o uxo de execucao do programa para o comando com label Ident . ifz Ident Ident1 ifp ifn
Este comando desvia o uxo de execucao do programa para o comando com label vari vel identicada por Ident tiver valor 0 (zero). a Ident Ident1 Este comando desvia o uxo de execucao do programa para o comando com label vari vel identicada por Ident tiver valor positivo. a Ident Ident1 Este comando desvia o uxo de execucao do programa para o comando com label vari vel identicada por Ident tiver valor negativo. a Ident na tela. Ident1 Ident1

Ident .

se o valor da

se o valor da

Ident1

se o valor da

imp Ident Imprime o valor da vari vel a m

Termina a execucao do programa.

Vamos exemplicar esta linguagem com um programa feito em HIP para calcular o m ximo divisor comum pelo a algoritmo de Euclides.

130

Linha lida var var var ler ler lab mod mov mov ifz des lab imp m

Explicacao do comando Declara a vari vel . a Declara a vari vel . a Declara a vari vel . a L um valor na vari vel atrav s do teclado. e a e L um valor na vari vel atrav s do teclado. e a e Declara ponto de desvio Incio da estrutura de repeticao mod . . . At que e . Neste caso, desvio o ponto . Volta a repetir desde o ponto . Ponto de desvio fora da estrutura de repeticao Impress o do MDC. a Fim do programa.

Faca um programa que l um programa em HIP (armazenado como um arquivo texto) e faz a execucao do progra e ma. Para facilitar, armazene o programa em um vetor, comando por comando, incluindo as operac es var e lab. A o posicao que tiver o comando var cont m um campo chamado valor que pode armazenar um valor inteiro. e Exerccio adicional: Implemente programas em HIP para: (i) Calcular o fatorial de um n mero positivo. (ii) Vericar u se um n mero positivo e primo. u Exerccio adicional: Modique o programa para que comandos como lab e var n o sejam mais representados no a vetor. As vari veis s o representadas em um vetor adicional, chamado mem ria e os comandos de desvios s o ara a o a mazenado com o ndice da posicao no vetor para onde o uxo e desviado. Os comandos que fazem manipulacao de vari veis devem armazenar seus respectivos ndices na mem ria. Estas modicacoes agilizam a execucao de um a o programa em HIP, uma vez que n o h necessidade de se buscar um identicador dentro do programa. a a

13.2 Arquivos Bin rios a


Um arquivo bin rio e um arquivo que n o tem necessariamente a restricao de ter apenas texto. A linguagem Pascal a a trata os arquivos bin rios como sendo uma seq encia de elementos de arquivo. Os elementos de um mesmo arquivo a u tem o mesmo tipo, que pode ser um tipo b sico da linguagem Pascal, ou outro denido pelo programador. a Os comandos read e write tamb m podem ser usadas em arquivos bin rios (as funcoes readln e writeln n o s o e a a a v lidas para arquivos bin rios), mas neste caso, usamos pelos menos dois par metros para estas funcoes, primeiro o a a a arquivo a ler/escrever e a seguir as vari veis (de mesmo tipo que o elemento b sico) que iremos ler/escrever. a a Um arquivo bin rio e declarado da forma: a FILE of tipo elemento b sico; a Exemplo 13.3 A seguir apresentamos alguns exemplos de declaracao de arquivos. ArqDados: File of TipoAluno; ArqNums: File of Integer; ArqVetCars: File of array [1..100] of char; ArqCars: File of char; Obs.: Arquivos texto (text) s o muito semelhantes com arquivos do tipo le of char, mas arquivos do tipo text tem a operacoes como EOLN (End of Line), o que n o ocorre com arquivos do tipo le of char. a Para associar o nome externo (nome do arquivo em disco) tamb m usamos o comando assign, da mesma forma e que usada para arquivos texto. Os comandos de abertura de um arquivo bin rio s o o reset e o rewrite. a a Para abrir um arquivo para leitura e gravacao de um arquivo j existente, usamos o comando: a reset(Vari vel de arquivo); a 131

Note a diferenc a deste comando para arquivos texto e arquivos bin rios. Usando este comando para arquivos texto, s a o podemos ler do arquivo, enquanto para arquivos bin rios, podemos ler e escrever. Inicialmente os dados j existentes a a no arquivo s o mantidos, podendo ser atualizados por comandos de escrita. Caso o arquivo j esteja aberto, este a a comando reposiciona o indicador de posicao corrente do arquivo para o incio do arquivo. Para abrir um arquivo novo (vazio) para leitura e gravacao comecando com um arquivo vazio, usamos o comando rewrite: rewrite(Vari vel de arquivo); a Se j existir um arquivo com o mesmo nome, o arquivo que existia antes e reinicializado como arquivo vazio. Com a este comando tamb m podemos ler, escrever/atualizar no arquivo bin rio. e a Tanto usando o comando reset como rewrite, o indicador de posicao corrente e inicializado no incio do arquivo. Para ler um elemento do arquivo (denido pela posicao do indicador corrente do arquivo) podemos usar o comando read: read(Vari vel de arquivo,Vari vel Elemento B sico); a a a onde Vari vel Elemento B sico e a vari vel que ir receber o valor do elemento que est indicado no arquivo. Ap s a a a a a o a leitura deste elemento o indicador de posicao corrente passa para o pr ximo elemento (ca em m de arquivo, caso o n o exista o pr ximo elemento). a o Para escrever um elemento no arquivo (na posicao indicada pelo indicador de posicao corrente do arquivo) usamos o comando write: write(Vari vel de arquivo,Vari vel Elemento B sico); a a a onde Vari vel Elemento B sico e a vari vel que ir receber o valor do elemento que est indicado no arquivo. Ap s a a a a a o a escrita deste elemento o indicador de posicao corrente passa para o pr ximo elemento (ca em m de arquivo, caso o n o exista o pr ximo elemento). a o Quando usamos arquivos bin rios, podemos usar a funcao eof, que retorna true caso estejamos no m de arquivo a e false caso contr rio e tamb m podemos redenir a posicao do indicador corrente de arquivo, tanto para frente como a e para tr s. O comando que nos permite mudar este indicador e o comando seek cuja sintaxe e a seguinte. a seek(Vari vel de arquivo,NovaPosic ao); a onde NovaPosicao e um inteiro entre 0 e (lesize(Vari vel de arquivo)-1). Com este comando, o indicador ir car a a posicionado no elemento de arquivo de n mero NovaPosicao. Lembrando que o primeiro elemento est na posicao 0 u a (zero) e lesize(Vari vel de arquivo) retorna o n mero de elementos de arquivo. a u

132

Exemplo 13.4 A universidade UNICOMP mant m um cadastro de alunos, cada aluno do tipo TipoAluno, como dee clarado no exerccio 9.2 da p gina 94. Para que os dados sejam armazenados de maneira permanente, em algum tipo a de mem ria secund ria (discos exiveis, discos rgidos, ...) e necess rio guardar os dados usando arquivos. Faca o a a mais duas rotinas para o programa do exerccio 9.2 de maneira que o programa possa gravar os alunos em um arqui vo, lidos a partir de um vetor, e ler os alunos de um arquivo inserindo-os em um vetor. O nome do arquivo deve ser fornecido pelo usu rio. a program LeituraGravacaoDeAlunos; type Inserir aqui a declaracao de TipoAluno e TipoCadastro mystring string[255];

procedure LeArquivo(var C : TipoCadastro; NomeArquivoDisco:mystring); var Arq: File of TipoAluno; Cada elemento b sico do arquivo e do tipo TipoAluno a begin assign(Arq,NomeArquivoDisco); reset(Arq); C.quant: 0; while not eof(Arq) do begin inc(C.quant); read(Arq,C.Aluno[C.quant]); Le o n esimo elemento b sico do arquivo a end; Quando terminar o loop, n ter a quantidade de elementos a close(Arq); end;

procedure GravaArquivo(var C: TipoCadastro; NomeArquivoDisco:mystring); var i : integer; Arq: File of TipoAluno; Cada elemento b sico do arquivo e do tipo TipoAluno a begin assign(Arq,NomeArquivoDisco); rewrite(Arq); Comeca um arquivo vazio for i: 1 to C.quant do write(Arq,C.Aluno[i]); Grava n elementos b sicos (alunos) a close(Arq); end; var i : integer; Cadastro : tipocadastro; NomeArquivoDisco : mystring; begin writeln(Entre com o nome do arquivo contendo os alunos: ); readln(NomeArquivoDisco); LeArquivo(Cadastro,NomeArquivoDisco); writeln(Os nomes dos alunos lidos so:); a for i: 1 to n do writeln(Cadastro.Aluno[i].nome); writeln(Entre com o nome do arquivo para conter uma cpia do arquivo original: ); o readln(NomeArquivoDisco); GravaArquivo(Cadastro,NomeArquivoDisco); end.

133

Exemplo 13.5 Vamos considerar que temos um sistema que mant m um cadastro de alunos, cada aluno do tipo Tie poAluno, como no exemplo 13.4. Agora vamos supor que temos uma grande restricao de limitacao de mem ria do o computador (e conseq entemente do programa) usado. I.e., n o podemos guardar todos os alunos do cadastro em u a um vetor. Al m disso, vamos supor que necessitamos da seguinte operacao: Ordenar os alunos, no pr prio arquivo e o e list -los na tela. Desenvolva uma rotina de ordenacao, por nome de aluno, usando n o mais que uma quantidade a a limitada (constante) de mem ria para guardar alunos. o program OrdenacaoDeAlunos; uses tipoaluno1; type Inserir aqui a declaracao de TipoAluno mystring string[255]; TipoArquivoAluno File of TipoAluno; procedure TrocaAlunoArquivo(var Arq :TipoArquivoAluno; i1,i2 : integer); var Aluno1,Aluno2: TipoAluno; begin seek(Arq,i1); read(Arq,Aluno1); seek(Arq,i2); read(Arq,Aluno2); seek(Arq,i2); write(Arq,Aluno1); seek(Arq,i1); write(Arq,Aluno2); end; function IndMaximoArquivo(var Arq:TipoArquivoAluno; n : integer) : integer; var i, Ind : integer; Maior,Aux : TipoAluno; begin seek(Arq,0); read(Arq,Maior); Ind : 0; O maior elemento comeca com o primeiro elemento do vetor for i: 1 to n do begin J comeca no segundo elemento (posicao 1) a read(Arq,Aux); Le um elemento do arquivo if Maior.nome Aux.nome then begin Ind: i; Se o elemento lido e maior que o que encontramos, Maior: Aux; Atualize o maior e o indice do maior end; end; IndMaximoArquivo : Ind; end; IndMaximoArquivo procedure OrdenaAlunosArquivo(NomeArquivoDisco:mystring); Id ia do SelectionSort e var Arq : File of TipoAluno; Cada elemento b sico do arquivo e do tipo TipoAluno a n,m,imax : integer; begin assign(Arq,NomeArquivoDisco); reset(Arq); n: lesize(Arq) 1; Obt m a posicao do ultimo elemento do arquivo e for m: n downto 1 do begin Modicacao devido ao arquivo comecar com posicao 0 imax : IndMaximoArquivo(Arq,m); TrocaAlunoArquivo(Arq,m,imax); Troca os alunos das posicoes m e imax end; close(Arq); end; OrdenaAlunosArquivo var aluno:TipoAluno; n,i:integer; Arq:TipoArquivoAluno; begin assign(Arq,Arquivo.dat); reset(Arq); n: lesize(Arq); for i: 1 to n do begin read(Arq,Aluno); writeln(Aluno.nome); end; end.

134

Exerccio 13.2 A rotina de ordenacao de elementos de arquivo, sem uso de vetores (diretamente no arquivo), apresen tada no exemplo 13.5, usa a estrat gia do SelectionSort. I.e., localiza o elemento de maior valor e coloca na posic o e a correta, e continua com o mesmo processo com os demais elementos. Faca uma rotina de ordenac o, nas mesmas a condicoes apresentadas no exemplo 13.5, mas agora usando o algoritmo QuickSort. Exerccio 13.3 A universidade UNICOMP tem milhares de funcion rios e todo incio de m s, quando deve fazer o a e pagamento de seus funcion rios, deve imprimir uma listagem de funcion rios, e para cada funcion rio o programa a a a deve imprimir seu nome, cargo e sal rio. O n mero de funcion rios e grande, mas a quantidade de empregos diferentes a u a e bem pequena. H apenas 5 tipos de empregos diferentes, conforme a tabela a seguir: a Cargo Faxineira Pedreiro Carpinteiro Professor Reitor Sal rio a 100,00 110,00 120,00 130,00 200,00

Como os recursos da UNICOMP s o escassos, ela deve economizar mem ria (em disco) do computador que far a a o a listagem. Assim, o programador que decide fazer o sistema resolve colocar a tabela acima em apenas um arquivo, chamado CARGOS. Cada registro deste arquivo e do seguinte tipo: type tipocargo = record nomecargo: string[50]; salario:real; end; Outro arquivo a ser manipulado e o arquivo CADASTRO, que cont m os funcion rios. Este arquivo e da seguinte e a forma: Nome Jos Carlos e Carlos Alberto Alberto Roberto Roberto Jos e . . . Cada registro deste arquivo e do seguinte tipo: type tipofuncionario = record nome: string[50]; poscargo:integer; end; Desta maneira n o e necess rio guardar todos os dados do cargo junto com o do funcion rio. Basta guardar um a a a indicador de onde est a informacao de cargo. a Se um funcion rio tem o campo poscargo igual a , ent o seu cargo e o cargo que esta na linha do arquivo a a de cargos. Assim, o funcion rio Jos Carlostem cargo Carpinteiroe ganha 120,00 reais; o funcion rio Roberto a e a Jos tem cargo Reitore ganha 200,00 reais. Faca um programa (com menu) que: e PosCargo 2 1 0 4 . . .

Inicialmente gera o arquivo CARGOS, apresentado acima. Le sempre que o usu rio quiser, um novo funcion rio e o inteiro indicando a posicao do cargo dele para adicia a on -lo no arquivo CADASTRO (inicialmente vazio). a Se o usu rio quiser lista todos os funcion rios, um por linha, indicando o nome, cargo e sal rio dele. a a a
135

Sugest o: Durante a execucao do programa, mantenha os dois arquivos abertos ao mesmo tempo. a

Exerccio 13.4 Em um sistema computacional, existem dois arquivos, um chamado Funcionarios.dat e outro chamado Cargos.dat, ambos arquivos bin rios. O arquivo Funcionarios.dat e um arquivo de elementos do tipo tipofunc e o a arquivo Cargos.dat e um arquivo de elementos do tipo tipocargo, denidos a seguir: type tipofunc = record nome:string[50]; codcargo:string[2]; end; tipocargo = record codcargo:string[2]; nomecargo:string[50]; salario:real; end; A seguir apresentamos um exemplo do arquivo Funcionarios.dat e do arquivo cargos.dat. Ambos os arquivos podem ter v rios elementos. a Codcargo Cargo Sal rio a Nome Codcargo Fa Faxineira 100,00 Jos Carlos e Fa Pe Pedreiro 110,00 Carlos Alberto Re Ca Carpinteiro 120,00 Alberto Roberto Pr Pr Professor 130,00 Roberto Jos e Pe Re Reitor 200,00 . . . . . . . . . . . . . . . O campo codcargo e um c digo de cargo composto de duas letras e relaciona o cargo de um funcion rio. No o a exemplo acima, o funcion rio Carlos Alberto tem codcargo igual a Re e procurando no arquivo Cargos.dat, vemos que a ele tem cargo de Reitor e ganha R$200,00 reais por m s. Faca um procedimento que imprime para cada funcion rio e a (do arquivo Funcionarios.dat) seu nome, seu cargo e seu sal rio. a Exerccio 13.5 Suponha que no programa anterior o arquivo Cargos tem seus registros sempre ordenados pelo campo Codcargo. Faca um procedimento, como no exerccio anterior, que imprime para cada funcion rio (do arquivo Funci a onarios.dat) seu nome, seu cargo e seu sal rio, mas para buscar os dados de um cargo (nome do cargo e o sal rio) faz a a uma busca bin ria no arquivo Cargos pelo campo Codcargo. Faca rotinas auxiliares para inserc o e remocao nestes a a arquivos.

13.3 Outras funcoes e procedimentos para manipulacao de arquivos


Alguns compiladores oferecem outras rotinas para manipular arquivos. Listamos algumas destas a seguir. ush(vararq) Flush esvazia o buffer do arquivo (mem ria auxiliar em RAM) em disco vararq e garante que qualquer o operacao de atualizac ao seja realmente feita no disco. O procedimento Flush nunca deve ser feito em um arquivo fechado. erase(vararq) E um procedimento que apaga o arquivo em disco associado com vararq. Ao dar este comando, o arquivo n o pode estar aberto, apenas associado (pelo comando assign). a rename(vararq,novonome) O arquivo em disco associado com vararq e renomeado para um novo nome dado pela express o de seq encia de caracteres novonome. Ao dar este comando, o arquivo n o pode estar aberto, apenas a u a associado (pelo comando assign). lepos(vararq) E uma funcao inteira que retorna a posicao atual do indicador de posicao corrente do arquivo. O primeiro componente de um arquivo e 0. Se o arquivo for texto, cada componente e um byte. Observacao: Note que e de responsabilidade do programador garantir a exist ncia do arquivo nomeado por uma e string. Se o programa tentar abrir um arquivo para leitura e o mesmo n o existir, o programa abortar . a a

136

13.4 Exerccios
1. Faca uma rotina que tem como par metros dois vetores a e , de elementos reais, e um par metro inteiro a indicando a quantidade de n meros em . Faca uma rotina que escreve os dados de e em um arquivo texto u da seguinte maneira: Na primeira linha e impresso o valor . Em seguida imprima linhas. Na primeira linha imprima os valores e separados por um espaco em branco. Na segunda linha imprima os valores e , assim por diante at os - simos elementos de e . e e

2. Faca uma rotina que leia um valor anterior.

e dois vetores

a partir de um arquivo texto, conforme o exerccio

3. Um grupo de alunos do curso de Algoritmos e Programacao de Computadores usa um compilador Pascal de linha de comando para compilar seus programas. Entretanto o editor de textos usado por eles n o apresena ta o n mero de linhas do programa, cando difcil para encontrar a linha que cont m o erro no programa. u e Faca um programa para ajud -los. O programa deve ler o nome de um arquivo texto, NomeArq e deve ler o a n mero de uma linha, nlinha. O programa deve imprimir na tela as linhas do programa: nlinha-5, nlinhau 4, ,nlinha,nlinha+1, ,nlinha+5. Caso alguma destas linhas n o exista, ela n o deve ser apresentada. Mostre a a tamb m o n mero de cada uma das linhas impressas (com 4 dgitos). e u Por exemplo, vamos supor que um compilador de linha tenha dado erro na linha 125 de um programa. Ent o a usamos este programa para imprimir as linhas . Como mostrado a seguir: 120> var esq,dir,IndicePivo : integer; 121> Pivo : real; 122> begin 123> troca(v[inicio],v[(inicio+fim) div 2]);{escolha de um ndice do piv ini o 124> Pivo := v[Inicio]; {Pivo fica na posico Inicio } a 125> esq=Inicio+1; {primeiro elemento mais a esquerda, pulando o piv} o 126> dir:=Fim; {primeiro elemento mais a direita} 127> while (esq<dir) do begin 128> while (esq<dir) and (v[esq] <= Pivo) do esq:=esq+1; 129> while (esq<dir) and (pivo < v[dir]) do dir:=dir-1; 130> if esq<dir then begin Uma vez que sabemos qual a linha que tem erro (125), podemos dizer que a atribuicao esq=Inicio+1 est a errada, e deveramos consertar para esq:=Inicio+1 . Obs.: Note que muitas vezes um compilador apresenta um erro em uma linha, quando na verdade o erro ocorreu em alguma linha anterior. 4. Faca um programa que, dados dois nomes de arquivo texto: NomeArq1, NomeArq2, l o texto que est no arquivo e a de nome NomeArq1 e grava em um arquivo de nome NomeArq2. O texto gravado deve ser o mesmo texto que foi lido, exceto que em min sculas e sem acento. Este e um programa util quando precisamos mandar um texto u acentuado por uma rede que traduz os acentos em outros c digos, deixando o texto difcil de ser lido para quem o o recebe. 5. Faca um programa que, dados dois nomes de arquivo texto: NomeArq1, NomeArq2 e um inteiro , , l o texto que est no arquivo de nome NomeArq1 e grava em um arquivo texto de nome Noe a meArq2. O texto gravado deve ser o texto que foi lido criptografado com a cifra de Cesar, com deslocamento . Considere apenas a criptograa das letras. 6. Faca um programa que, dados dois nomes de arquivo texto: NomeArq1, NomeArq2 e um inteiro , , l o texto que est no arquivo de nome NomeArq1 e grava em um arquivo texto de nome Noe a meArq2. O texto gravado deve ser o texto que foi lido decriptografado com a cifra de Cesar, com deslocamento . 7. (Busca de Padr o) Faca um programa que, dado um nome de um arquivo texto: NomeArq, e uma string: padrao, a l o arquivo texto e imprime (na tela) as linhas que cont m a string padrao. Al m disso, o programa tamb m e e e e 137

e em seguida deve imprimir o n mero da linha impressa (sugest o: imprima o n mero da linha, a string u a u a linha do arquivo). No m do programa, o programa deve imprimir quantas vezes o padrao apareceu no texto (considere repeticoes em uma mesma linha).
8. Um professor do curso de Algoritmos e Programacao de Computadores tem um arquivo texto chamado entra da.txt contendo as notas dos alunos do seu curso. O arquivo tem v rias linhas, uma linha para cada aluno. Cada a linha tem o RA do aluno (string de 6 caracteres) e tr s notas (n meros reais) separadas por pelo menos um e u espaco em branco: RA A m dia e e calculada da seguinte maneira: Se e tal que , o aluno est Aprovado, caso contr rio o aluno est de Exame. Faca um procedimento a a a que l o arquivo entrada.txt e gera um outro arquivo texto chamado saida.txt contendo uma linha para cada e aluno. Cada linha deve ter o seguinte formato: RA Resultado e a m dia do aluno e Resultado e a palavra Aprovado ou Exame, dependendo se o aluno passou ou cou e Onde de exame. Os seguintes dois quadros ilustram o formato destes dois arquivos: entrada.txt saida.txt 991111 7.5 6.5 8.5 991111 7.5 Aprovado 992222 9.0 7.0 9.0 992222 8.25 Aprovado 993333 3.5 4.0 5.0 993333 4.25 Exame . . . . . .

9. Um usu rio necessita copiar um programa instalado no computador do seu escrit rio para o computador da sua a o casa. Infelizmente o programa usa muita mem ria e n o cabe em apenas um disquete. Ajude este usu rio, da o a a seguinte maneira: (a) Faca um programa que l um valor inteiro e o nome de um arquivo, digamos NomeArq, e gera arquivos e com nomes: NomeArq.1, NomeArq.2, ...., NomeArq.k, assim, por diante, onde todos estes arquivos tem exatamente bytes, exceto talvez o ultimo que pode usar menos bytes.

(b) Faca um programa que dado uma lista de nomes, digamos NomeArq.1, NomeArq.2, ...., NomeArq.k gera um novo arquivo contendo a concatenac ao destes arquivos, nesta ordem. Com isso, o usu rio poder quebrar seu programa em partes menores, gravar cada parte em um disquete, a a copiar cada arquivo no computador da sua casa e por m concaten -los, obtendo o programa original. a 10. Os exerccios seguintes consideram as declaracoes feitas na secao 9.4 (exerccio 1). Faca uma rotina, Grava CadastroArquivo, que tem como par metros o cadastro e um nome (nome de arquivo). A rotina grava todos os a registros do cadastro neste arquivo, que ter o nome especicado no par metro. a a 11. Faca uma rotina, LeCadastroArquivo, que tem como par metros o cadastro e um nome (nome de arquivo). A a rotina l o cadastro do arquivo com o nome especicado no par metro. e a 12. Faca uma rotina, InsereDeCadastroArquivo, que insere os funcion rios que est o em um arquivo dentro do a a cadastro. Obs.: Os funcion rios anteriores que est o no cadastro s o permanecidos. a a a 13. Faca as rotinas que fazem impress o/listagem, insercao, atualizac ao de funcionarios, nos exerccios anteriores, a mas agora sem uso do cadastro (vetor). Voc deve fazer as operacoes diretamente no arquivo. e

138

14 Figuras e Gr cos a
Muitas vezes queremos vizualizar objetos que est o sendo representados no modelo computacional, como guras, a curvas, retas, polgonos, etc. Embora muitos objetos possam ter caractersticas tridimensionais, na maioria das vezes precisamos traduzi-los de maneira que possam ser visualizados de maneira bidimensional, uma vez que o vdeo e um dispositivo de apresentac ao bidimensional. Al m disso, um vdeo de computador apresenta os objetos como uma e matriz de pontos forcando a apresentar os objetos de maneira discretizada. Assim, vamos considerar que o menor elemento usado para apresentar um gr co/gura e um ponto (pixel). Deste modo, podemos considerar o desenho de a uma reta no vdeo como sendo um conjunto de pontos, onde cada ponto da matriz tem coordenadas especcas nos dois eixos da matriz. Naturalmente, os objetos que iremos apresentar n o precisam necessariamente estar denidos atrav s a e de pontos, podendo ter uma representac ao interna contnua, como e o caso de funcoes de retas e curvas. Embora, no momento de sua apresentac ao na tela, esta deva ser discretizada para pontos, uma vez que o vdeo e uma matriz de pontos. Duas maneiras comuns de representac ao de uma tela gr ca com matriz de pontos por coordenadas s o a a apresentadas nas duas guras seguintes.
Pixel
14 (20,14) (0,0) 20

14 (0,0) 20

(20,14)

(a)
Para simplicar nossos programas, iremos usar a representac ao (a).

(b)

No processo de apresentac ao de objetos gr cos no vdeo, os pontos (representados por bits) s o lidos de uma a a mem ria (mem ria de vdeo) e s o apresentados no vdeo, em torno de 30 vezes por segundo. o o a Uma gura pode ser apresentada em um dispositivo gr co usando cores, em geral usando uma quantidade limitada a de mem ria para armazenar cada ponto de uma gura (e conseq entemente usando um n mero limitado de cores). Esta o u u mem ria depender da quantidade de cores possveis que cada ponto pode assumir. Se consideramos uma gura em o a preto e branco, cada ponto pode ser representado por apenas um bit. Para representar 256 cores (ou tonalidades diferentes), precisaremos de um byte para representar cada bit. Neste caso, uma gura usando pontos, onde cada ponto assume 256 cores, usa uma mem ria de vdeo de pelo menos 1 Megabyte. o

Uma maneira muito comum de se representar pontos coloridos e usando o formato RGB (Red-Green-Blue), atrav s e de tr s valores que indicam a intensidade das cores Vermelha, Verde e Azul (lembrando que uma determinada cor pode e ser obtida misturando quantidades especcas destas tr s cores). e

14.1 Usando o formato PPM Portable PixMap


Para podermos trabalhar com gr cos de maneira independente de computador e sistema operacional, vamos usar a um formato que pode ser visualizado em diversos ambientes computacionais. Vamos usar o formato PPM (Portable PixMap Format). Este formato representa uma matriz de pontos em um arquivo, usando o formato RGB, onde cada ponto colorido e apresentado por tr s bytes seguidos, representando a intensidade das cores vermelha, verde e azul. e Cada byte apresenta um valor entre 0 e 255. Portanto, cada pixel pode ser uma de cores (naturalmente, sua visualizac ao depender da qualidade do vdeo usado). Uma vez que temos esta matriz de pontos, podemos formar uma a gura mudando as cores dos elementos desta matriz, ponto a ponto. Existem diversos programas para visualizac ao de guras armazenadas em arquivos de diversos formatos gr cos, a alguns destes livres ou a precos reduzidos (Freeware e Shareware) que podem visualizar guras no formato PPM. Para o ambiente Linux, podemos usar o programa GQview, que pode ser obtido na p gina http://gqview.netpedia.net/. a No ambiente Unix/XWindows, podemos usar o program xv, disponvel para a maioria das plataformas. Para o ambien te Windows podemos usar o programa Irfan View32, disponvel livremente na rede http://sunsite.auc.dk/tucows/g Por simplicidade, usaremos um tipo restrito para as guras do formato PPM. Neste formato usamos um cabecalho apresentando 4 valores descritos em formato texto (P6 Largura Altura 255), separados por um espaco em branco ou 139

em linhas diferentes. P6 s o os caracteres ASCII P e 6, e devem ser os primeiros dois bytes do arquivo. Em a seguida devem vir a largura e altura da gura, Largura e Algura, descritos em n meros ASCII. Por m, devem vir u o tr s caracteres ASCII do n mero 255, indicando que a maior componente de uma cor (intensidade de Vermelho, e u Verde ou Azul) e 255. Caracteres neste cabecalho que estejam em uma linha ap s o smbolo # n o s o considerados o a a (coment rios). Logo em seguida, como ultimo byte deste cabecalho, temos o byte de valor 10 (NewLine) e em seguida a devem vir a seq encia de bytes que representam os pixels da gura. A cada tr s bytes (usando o sistema RGB) u e representamos um pixel (o primeiro byte para a intensidade de vermelho, o segundo para a intensidade de verde e o terceiro para a intensidade de azul), ao todo temos Largura Altura pixels. Um exemplo de um cabecalho para uma gura com 200 pixels de largura e 300 pixels de altura e apresentado no quadro seguinte: P6 200 300 255

A seq encia de pixels gravados no arquivo PPM segue a ordem apresentada pelas setas na gura seguinte: u
A ltimo Pixel (L,A)

Primeiro Pixel (0,0) L

Para trabalhar com a matriz de pixels, vamos usar um tipo chamado TipoTela, onde cada pixel e do tipo TipoCor, em RGB, declarados no seguinte quadro. const MAXPONTOS 200; type TipoCor record red,green,blue : Byte; end; TipoTela array[0..MAXPONTOS 1,0..MAXPONTOS 1] of TipoCor;

Com estas declarac oes podemos gerar uma gura, usando uma matriz de MAXPONTOS MAXPONTOS pixels. Al m disso, podemos denir algumas cores para facilitar a atribuic ao de cores. Para denir a cor vermelha, podemos e atribuir, em RGB, a intensidade m xima para vermelho (Red) e intensidade zero para as outras duas cores (Green e a Blue). Podemos fazer o mesmo processo para denir as cores verde e azul. A cor branca e denida quanto temos a m xima intensidade (valor 255) para as componentes vermelha, verde e azul, e a cor preta e denida pela aus ncia de a e cores (valor zero). O quadro da p gina 141 mostra a denicao destas cores e rotinas para iniciar a tela com cor branca a e gravar a tela em um arquivo no formato PPM. Obs.: Al m do formato PPM, existem diversos outros formatos gr cos, sendo que alguns incorporam m todos de e a e compress o de dados, como e o caso dos formatos GIF e JPG. a

140

const MAXPONTOS 200; type TipoCor record Red,Green,Blue : Byte; end; TipoTela array[0..MAXPONTOS 1,0..MAXPONTOS 1] of TipoCor; TipoNomeArq string[100]; TipoArquivoBinario le of byte; var Branco,Vermelho,Verde,Azul,Preto : TipoCor; procedure InicializaAlgumasCores; Cores: Branco, Preto, Vermelho, Verde, Azul begin Denicao das cores usadas no formato RGB (Red Green Blue) Branco.Red: 255; Branco.Green: 255; Branco.Blue: 255; Preto.Red: 0; Preto.Green: 0; Preto.Blue: 0; Vermelho.Red: 255; Vermelho.Green: 0; Vermelho.Blue: 0; Verde.Red: 0; Verde.Green: 255; Verde.Blue: 0; Azul.Red: 0; Azul.Green: 0; Azul.Blue: 255; end; procedure InicializaTela(var tela: tipotela); Coloca todos os pixels como Branco var i,j : integer; a begin Obs.: O ponto (0,0) est no canto inferior esquerdo for i: 0 to MAXPONTOS 1 do for j: 0 to MAXPONTOS 1 do tela[i,j] : Branco; end; inicializatela procedure DesenhaPonto(var tela : tipotela; x,y:integer; Cor:TipoCor); begin tela[x,y] : Cor; Atribui o pixel (x,y) com Cor end; procedure EscreveCabecalhoPPM(var arq : TipoArquivoBinario;largura,altura:integer); var i : integer; str1,str2,cabecalho : string[100]; b:byte; begin str(largura,str1); str(altura,str2); Pegar a largura e altura como strings cabecalho : P6 str1 str2 255); for i: 1 to length(cabecalho) do begin b: ord(cabecalho[i]); write(Arq,b); end; b: 10; write(Arq,b); Caracter para Pular linha end; procedure GravaTela(var t:TipoTela; nomearq:tiponomearq); Grava a tela em arquivo var Arq: TipoArquivoBinario; lin,col : integer; begin assign(Arq,NomeArq); rewrite(Arq); EscreveCabecalhoPPM(Arq,MAXPONTOS,MAXPONTOS); for col: MAXPONTOS 1 downto 0 do for lin: 0 to MAXPONTOS 1 do begin Grava um pixel denido em RGB write(Arq,t[lin,col].Red); write(Arq,t[lin,col].Green); write(Arq,t[lin,col].Blue); end; close(Arq); end; GravaTela

141

14.2 Retas e Crculos


Uma vez que sabemos como imprimir um ponto em uma gura e grav -la em um arquivo no formato PPM, vamos a construir duas primitivas gr cas para construir desenhos mais complexos, as rotinas para desenhar um segmento de a reta e um crculo. Para estas duas operacoes, vamos construir rotinas param tricas, que denem os pontos do objeto e atrav s de um par metro. e a

Podemos denir os pontos de um segmento de reta , ligando dois pontos um par metro no intervalo como a , onde

e , usando Note que quando obtemos o ponto e quando obtemos o ponto . Para desenhar o segmento de reta , podemos plotar alguns pontos de , cuja quantidade depender da dimens o da matriz de pontos, escolhendo a a valores de distribudos no intervalo . e raio , tamb m vamos usar um par metro que reetir um e a a Para desenhar um crculo , com centro
angulo no intervalo e raio .

. Primeiramente, vamos vericar a seguinte representac ao para um crculo com centro em


y sen(t) t
(0,0)

cos(t)

Note que as coordenadas do ponto pertencente ao crculo, denido pelo angulo e o ponto . Para denir um crculo de raio maior, basta multiplicar as coordenadas dos pontos pelo valor de , e para que o crculo seja denido com centro , adicionamos os valores de e nas coordenadas correspondentes. Desta forma, onde obtemos a seguinte representac ao param trica para os pontos do crculo: e

Agora podemos denir uma gura ou objeto gr co, mais elaborado, como um conjunto de objetos primitivos a (retas e crculos). Vamos denir este objeto mais elaborado como o tipo TipoFigura da seguinte maneira: const MAXOBJETOS 200; Quantidade m xima de objetos que uma gura pode ter a type TipoCor record red,green,blue : Byte; end; TipoForma (FormaCirculo,FormaReta); TipoObjeto record Cor : TipoCor; case Forma : TipoForma of FormaCirculo : (centrox,centroy:integer; Raio:Real); FormaReta : (p1x,p1y,p2x,p2y:integer); end; TipoFigura record nobjetos : 0..MAXOBJETOS; quantidade de objetos, armazenados em vetor objeto : array[1..MAXOBJETOS] of TipoObjeto; end; A seguir, apresentamos um programa, contendo os procedimentos para desenhar um segmento de reta e um crculo, para gravar uma gura de um desenho de um rosto construdo com crculos e retas e gravado em um arquivo no formato PPM.

142

program ProgFigura; const MAXPONTOS 200; MAXOBJETOS 200; type TipoCor record red,green,blue : Byte; end; TipoTela array[0..MAXPONTOS 1,0..MAXPONTOS 1] of TipoCor; TipoForma (FormaCirculo,FormaReta); TipoObjeto record Cor : TipoCor; case Forma : TipoForma of FormaCirculo : (centrox,centroy:integer;Raio:Real); FormaReta : (p1x,p1y,p2x,p2y:integer); end; TipoFigura record nobjetos : 0..MAXOBJETOS; objeto : array[1..MAXOBJETOS] of TipoObjeto; end; TipoNomeArq string[100]; TipoArquivoBinario le of byte; var Branco,Vermelho,Verde,Azul,Preto : TipoCor; Incluir as seguintes rotinas procedure InicializaTela(var tela : tipotela); procedure DesenhaPonto(var tela : tipotela; x,y:integer; cor:TipoCor); procedure GravaTela(var t : TipoTela; nomearq: tiponomearq); procedure DesenhaReta(var tela : tipotela; x1,y1,x2,y2:integer; cor:TipoCor); var t,delta,maxit,x,y : real; representacao parametrica begin delta : 1/MAXPONTOS; x: x1; y: y1; t: 0; while t 1 do begin 0 t 1 x: x1(x2 x1) t; y: y1(y2 y1) t; DesenhaPonto(tela,round(x),round(y),cor); t: tdelta; end; end; procedure DesenhaCirculo(var tela : tipotela; cx,cy:integer;raio:real; cor:TipoCor); var t,delta,maxit,x,y,DoisPi : real; representacao parametrica begin DoisPi : PI 2; delta : 1/MAXPONTOS; t: 0; while t DoisPi do begin 0 t DoisPi Usando Coordenadas Polares x: cx raio cos(t); Y: cy raio sin(t); DesenhaPonto(tela,round(x),round(y),cor); t: tdelta; end; end;

143

procedure DesenhaObjeto(var tela : TipoTela; obj : TipoObjeto); begin case Obj.Forma of FormaCirculo : DesenhaCirculo(tela, obj.centrox, obj.centroy, obj.raio, obj.cor); FormaReta : DesenhaReta(tela, obj.p1x, obj.p1y, obj.p2x, obj.p2y, obj.cor); end; case end; procedure DesenhaFigura(var t : TipoTela; var Fig:TipoFigura); var i:integer; begin for i: 1 to Fig.nobjetos do DesenhaObjeto(t,Fig.objeto[i]); end; procedure EscreveString(var arq : TipoArquivoBinario;str:string); var i : integer; begin for i: 1 to length(str) do write(Arq,ord(str[i])); end; var t : tipotela; face : TipoFigura; begin Denicao de algumas cores usando o formato RGB (Red Green Blue) Branco.Red: 255; Branco.Green: 255; Branco.Blue: 255; Preto.Red: 0; Preto.Green: 0; Preto.Blue: 0; Vermelho.Red: 255; Vermelho.Green: 0; Vermelho.Blue: 0; Verde.Green: 255; Verde.Blue: 0; Verde.Red: 0; Azul.Red: 0; Azul.Green: 0; Azul.Blue: 255; inicializatela(t); cabeca face.objeto[1].Forma : FormaCirculo; face.objeto[1].cor : Preto; face.objeto[1].centrox : 100; face.objeto[1].centroy : 100; face.objeto[1].raio : 50; olho esq face.objeto[2].Forma : FormaCirculo; face.objeto[2].cor : Azul; face.objeto[2].centrox : 80; face.objeto[2].centroy : 120; face.objeto[2].raio : 6; olho dir face.objeto[3].Forma : FormaCirculo; face.objeto[3].cor : Verde; face.objeto[3].centrox : 120; face.objeto[3].centroy : 120; face.objeto[3].raio : 10; nariz face.objeto[4].Forma : FormaReta; face.objeto[4].cor : Preto; face.objeto[4].p1x : 100; face.objeto[4].p1y : 110; face.objeto[4].p2x : 100; face.objeto[4].p2y : 90; boca face.objeto[5].Forma : FormaReta; face.objeto[5].cor : Vermelho; face.objeto[5].p1x : 80; face.objeto[5].p1y : 80; face.objeto[5].p2x : 120; face.objeto[5].p2y : 80;

face.nobjetos : 5; face foi denido com 5 objetos gracos DesenhaFigura(t,face); GravaTela(t,saida.ppm); end.

144

14.3 Exerccios
1. O formato PGM (Portable Grayscale pixMap) e muito parecido com o formato PPM. Neste formato podemos representar guras monocrom ticas, com intensidade nos pixels. I.e., todos os pixels tem apenas uma cor, mas a podem ter intensidade que pode ir de 0 a 255. A seguir, listamos as diferenc as/semelhanc as nos formatos destes dois arquivos: (a) O cabecalho e descrito da mesma maneira que o cabecalho de um arquivo PPM, mas em vez de P6, voc e deve colocar P5. (b) A seq encia de pixels segue a mesma ordem que no formato PPM. u (c) Cada pixel usa apenas 1 byte (em vez de 3). O valor deste byte indica a intensidade do pixel. O valor 255 para o branco e 0 para preto. Os valores entre 0 e 255 indicar o uma intensidade intermedi ria. a a Faca um programa que desenha a gura apresentada na p gina 144, mas em formato PGM. a 2. Faca outras primitivas gr cas, al m do segmento de reta e o crculo: Ret ngulo, Ret ngulo Preenchido (todo a e a a preenchido com uma cor), Crculo Preenchido, Poligono fechado de pontos. 3. Faca um programa contendo uma rotina que plota uma funcao em um arquivo de formato PPM, para valores de em um intervalo . A rotina deve ter o seguinte cabecalho: procedure PlotaFuncao(f: TipoFuncaoReal; :real; NomeArquivo:TipoString);

Faca uma imagem de tamanho pontos (com digamos e ). Naturalmente voc ter e a que fazer uma reparametrizac ao, de maneira que o ponto na matriz de pontos seja equivalente a posicao e o ponto na matriz de pontos seja equivalente a posicao . 4. Faca uma rotina que tenha como par metros, um vetor de valores reais positivos com elementos. Faca um a programa que gere gr cos de barras, histograma e tipo torta, de acordo com a escolha do usu rio. a a 5. A gura de uma letra pode ser armazenada em uma matriz de tamanho . Gere matrizes para algumas letras, atribuindo os valores dos pontos atrav s de um programa (vc pode usar as rotinas de reta e crculo para isso). e Uma vez que voc gerou estas letras, faca uma rotina que tem como par metro uma posicao (bidimensional) e e a uma letra. A rotina deve imprimir a matriz que forma a letra na tela de pontos. Isto permitir que possamos a escrever na gura. 6. Faca uma rotina que tem como par metro os nomes de dois arquivos e um valor real positivo, . A rotina l o a e arquivo do primeiro nome, que e uma gura no formato PPM e gera outro arquivo que e a mesma gura, mas com tamanho reparametrizado de um fator .

Com isso, iremos passar a funcao a plotar como par metro. Para plotar os pontos a , discretize os valores de no intervalo , imprima os pontos que caem no intervalo . Al m disso, imprima as retas e e , caso estas estejam nos intervalos de impress o. a dos eixos

onde TipoFuncaoReal foi denido como: type TipoFuncao = function(x:real):real;

145

15 Ponteiros
Ponteiros (pointers) ou apontadores s o vari veis que armazenam um endereco de mem ria (e.g., endereco de outras a a o vari veis). a Na linguagem Pascal cada ponteiro tem um tipo, podendo ser um ponteiro para um tipo pr -denido da linguagem e Pascal ou um tipo denido pelo programador. Assim, podemos ter ponteiros para integer, ponteiro para real, ponteiro para TipoAluno etc. Quando um ponteiro cont m o endereco de uma vari vel, dizemos que o ponteiro est apontando para essa e a a vari vel. a Como um ponteiro e apenas um endereco de mem ria, n o e preciso muitos bytes para sua denicao, em geral s o o a a usados 4 bytes para isso. Vamos representar um ponteiro

da seguinte maneira:
P

Neste caso, a vari velPonteiro , lado esquerdo, est apontando para a vari vel/mem ria que est do lado direito. a a a o a Internamente, a vari vel cont m o enderec o da vari vel apontada. a e a Declaracao: Para declarar um ponteiro de um certo tipo, usamos a seguinte sintaxe: var Lista Ident Pont:TipoPonteiro; Ao declarar um ponteiro

Varivel/Memria

, o endereco inicial contido nesta vari vel deve ser considerado como lixo, i.e.: a
P Lixo

Atribuindo um endereco para um ponteiro: Vamos supor que temos uma vari vel, , e queremos que um ponteiro, , (ponteiro para integer) aponte para esta a vari vel. Para isso, usamos o operador para obter o endereco de , da seguinte maneira: a

Um ponteiro tamb m pode receber o conte do de outro ponteiro. Al m disso, existe um enderec o especial, chamado e u e nil (nulo), que serve para dizer que e um enderec o nulo e n o teremos nenhuma vari vel neste enderec o de mem ria. a a o Este enderec o e util para dizer que o ponteiro ainda n o tem nenhum enderec o v lido. a a

Trabalhando com a mem ria apontada pelo ponteiro: o


Para acessar a mem ria que o ponteiro est apontando, usamos o operador , com a sintaxe . Naturalmente o a dever ter um endereco v lido, i.e., deve estar apontando para uma vari vel ou para uma mem ria de tipo compatvel. a a a o Na gura seguinte apresentamos exemplos das operacoes com ponteiros e a representac ao de cada comando. {Programa} {Configurao da Memria} var X:integer; X p lixo p,q:^integer; lixo q lixo begin p X lixo X := 10; 10 q lixo
p := @X; q^ := 30; q := p; q^ := p^ + 10; writeln(p^); end. p X 10 q lixo { ERRO: q aponta p/ lixo } p X 10 q p X 20 q { Imprime o valor 20 }

O comando q:=30; causa um erro no programa; assim, vamos supor que este comando e apenas ilustrativo e n o a

146

afeta os demais comandos. Exemplo 15.1 Considere dois vetores de alunos (registros) usando o tipo TipoAluno (veja p gina 93), que temos a que listar ordenados por nome, digamos pelo algoritmo QuickSort (veja p gina 113). Os dois vetores n o devem ser a a alterados, nem mesmo na ordem dos seus elementos. Este problema poderia ser resolvido facilmente usando um terceiro vetor para conter a uni o dos dois primeiros a e em seguida ordenamos este terceiro vetor por nome. Desta maneira manter amos os dois vetores originais intactos. Entretanto, se cada registro do tipo TipoAluno for muito grande e a quantidade de alunos nos dois vetores tamb m for e grande, teramos dois problemas: 1. A declaracao do terceiro vetor deve usar uma mem ria grande o suciente para acomodar a uni o dos dois o a primeiros vetores. 2. Os algoritmos de ordenacao, baseados em troca de elementos, iriam fazer muitas transfer ncias de bytes (lem e brando que para trocar dois elementos fazemos 3 atribuicoes de vari veis, veja rotina troca na p gina 69). a a Uma maneira mais econ mica e r pida para resolver este problema e usar o terceiro vetor como um vetor de ponteiros o a para alunos. I.e., cada elemento do terceiro vetor aponta para um elemento dos dois vetores. Note que cada elemento do terceiro vetor deve gastar em torno de 4 bytes, j que e apenas um enderec o, gastando menos mem ria que do modo a o anterior. Na gura 40(a) apresentamos a representacao dos tr s vetores com os elementos do terceiro vetor apontando e para os elementos dos dois vetores originais. Na gura 40(b) apresentamos o terceiro vetor a ordenado. No programa j da p gina 148 apresentamos a funcao de comparacao e a rotina de troca de elementos usadas para ordenar o terceiro a vetor.

Antes da ordenao do vetor Unio D G A Uniao E H B C (a) F Aluno2 Aluno1

Depois da ordenao do vetor Unio D G A Uniao E H B C (b) F Aluno2 Aluno1

Figura 40: Ordenacao de dois vetores, usando um terceiro vetor de ponteiros.

147

program OrdenaDoisVetores; 100; const MAXALUNOS type Inserir declaracoes de TipoAluno TipoApontadorAluno TipoAluno; Apontador de TipoAluno TipoVetorAluno array[1..MAXALUNOS] of TipoAluno; TipoVetorApontadorAluno array[1..2 MAXALUNOS] of TipoApontadorAluno; Vetor de Apontadores procedure LeVetorAluno(var V : TipoVetorAluno;var n:integer); var i : integer; begin write(Entre com a quantidade de alunos a ler: ); readln(n); for i: 1 to n do begin write(Entre com o nome do aluno: ); readln(V[i].nome); ... leia outros atributos do aluno ... end; end; LeVetorAluno procedure TrocaApontadorAluno(var ApontAluno1,ApontAluno2 : TipoApontadorAluno); var ApontAux : TipoApontadorAluno; begin ApontAux: ApontAluno1; ApontAluno1: ApontAluno2; ApontAluno2: ApontAux; end; TrocaApontadorAluno function ComparaApontadorAluno(var ApontAluno1,ApontAluno2:TipoApontadorAluno):char; begin if (ApontAluno1.nome ApontAluno2.nome) then ComparaApontadorAluno: > else if (ApontAluno1.nome ApontAluno2.nome) then ComparaApontadorAluno: < else ComparaApontadorAluno: =; end; var Aluno1,Aluno2 : TipoVetorAluno; Uniao : TipoVetorApontadorAluno; i,n1,n2,nuniao : integer; begin LeVetorAluno(Aluno1,n1); LeVetorAluno(Aluno2,n2); nuniao : 0; for i: 1 to n1 do begin nuniao : nuniao 1; Uniao[nuniao] : @Aluno1[i]; end; for i: 1 to n2 do begin nuniao : nuniao 1; Uniao[nuniao] : @Aluno2[i]; end; Chamada da rotina QuickSort usando rotina de comparacao: ComparaApontadorAluno e rotina de troca de elementos: TrocaApontadorAluno QuickSortApontAluno(Uniao,nuniao,ComparaApontadorAluno); for i: 1 to nuniao do begin writeln(Uniao[i].nome,Uniao[i].rg, ... Uniao[i].cr); end; end.

148

Exerccio 15.1 Um sistema da Universidade UNICOMP trabalha com um cadastro muito grande, contendo o dados de alunos (veja declaracao do tipo TipoAluno na p gina 93). Uma das rotinas do sistema faz uma seq encia de a u selecoes realizadas pelo usu rio no cadastro de alunos, at que o usu rio esteja satisfeito. A cada iteracao com o a e a usu rio a rotina imprime o n mero de alunos nas condicoes. Em cada iteracao, o usu rio pode restringir o atual a u a conjunto com os seguintes tipos de restricao:

, onde e um valor lido. 2. Retringir o atual conjunto para alunos com idade inferior a , onde e um valor lido. 3. Retringir o atual conjunto para alunos com CR superior a , onde e um valor lido.
1. Retringir o atual conjunto para alunos com idade superior a Quando o usu rio estiver satisfeito, a rotina deve imprimir os nomes dos alunos selecionados. Implemente esta rotina a usando um vetor auxiliar de ponteiros para alunos, sendo que este vetor de ponteiros deve ser atualizado a cada iteracao com o usu rio. O cadastro de alunos n o deve ser modicado, apenas o vetor de ponteiros. Note que cada a a nova selecao e feita (possivelmente) em um conjunto de dados menor.

15.1 Alocacao Din mica de Mem ria a o


A linguagem Pascal permite que possamos pedir mais mem ria que a usada para o sistema operacional. Este nos o retornar o enderec o da mem ria que nos foi alocada ou um aviso que n o foi possvel alocar a mem ria requisitada. a o a o A mem ria a ser requisitada deve ter um tipo associado a ela e para receber o enderec o desta nova mem ria, devemos o o usar um ponteiro do mesmo tipo da mem ria sendo requisitada. Por exemplo, usamos um ponteiro para TipoAluno o para obter mem ria do tipo TipoAluno. o O comando para obter mem ria e atrav s do comando new da seguinte maneira: o e new ; Este comando aloca uma mem ria que ser apontada pelo ponteiro . Caso o sistema operacional n o consiga alocar o a a a o a o a esta mem ria, o ponteiro retornar com valor nil. Esta nova mem ria n o e mem ria de nenhuma vari vel, mas sim o uma mem ria nova que pode ser usada com o mesmo tipo daquele declarado para o ponteiro . Al m disso, qualquer o e mem ria que tenha sido obtida atrav s do comando new pode ser liberada novamente para o sistema operacional, que o e poder consider -la para futuras alocacoes de mem ria. O comando para liberar uma mem ria obtida por alocacao a a o o din mica, apontada por um apontador , e atrav s do comando dispose da seguinte maneira: a e dispose ; A gura seguinte apresenta um programa contendo alguns comandos usando alocac ao din mica e a situacao da a mem ria ap s cada comando. Alguns dos comandos causam erro de execucao e foram colocados apenas para ns o o did ticos, vamos supor que estes n o afetam os demais comandos. a a

149

program exemplo; type TipoRegistro = record nome: string[50] idade:integer; end; var p,q:^TipoRegistro; R: TipoRegistro; begin new(p); R.nome := Carlos; R.idade := 50; writeln(p^.nome); p^.nome := Jos; p^.idade := 10;

CONFIGURAO DA MEMRIA APS COMANDOS

p q p q

lixo lixo lixo lixo lixo

R= lixo

lixo

R= Carlos

50

PROBLEMA: p^.nome ainda no foi inicializado p Jos 10 R= Carlos 50 q lixo PROBLEMA: Memria alocada antes foi perdida p nil Jos 10 q lixo R= Carlos 50 p q nil Carlos 50 Jos R= Carlos 10 50

p:=nil; new(q); q^ := R; writeln(p^.nome); p := @R; q^.idade := 60; writeln(q^.nome, ,q^.idade); dispose(p); dispose(q); end.

ERRO: p no aponta para memria p Jos q Carlos 60 R= Carlos { Imprime Carlos 60 } ERRO: p no aponta para memria obtida por alocao dinmica. p Jos q lixo R= Carlos

10 50

10 50

150

15.2 Listas Ligadas


Uma das grandes restric oes de se representar um conjunto de elementos por vetores e a limitacao imposta pelo n mero u de elementos na declaracao do vetor. O n mero de elementos declarado no tamanho de um vetor deve ser um valor u xo e nos traz dois inconvenientes: 1. Devemos assumir uma declarac ao do vetor usando muitos elementos para que n o tenhamos problemas quando a precisarmos manipular muitos elementos. 2. Uma declaracao de um vetor com muitos elementos pode causar desperdcio de mem ria. Note que se todos os o programas usassem vetores com tamanhos muito grandes, provavelmente teramos poucos programas residentes na mem ria do computador. o Um vetor pode representar v rios elementos de maneira simples e direta. Isto e possvel pois seus elementos est o a a em posicoes contguas de mem ria, embora n o seja possvel estender esta mem ria quando precisarmos inserir mais o a o elementos que o denido no tamanho do vetor. Usando alocacao din mica podemos representar um conjunto de dados usando uma quantidade de mem ria pro a o porcional ao n mero de elementos sendo representados no conjunto. Isto pode ser feito fazendo uma interligacao entre u os elementos do conjunto usando tipos recursivos de dados. Um elemento de um tipo recursivo e um registro de um tipo onde alguns dos campos s o apontadores para o mesmo tipo. A primeira vista parece estranho, uma vez que a estamos denindo um campo que referencia um tipo que ainda estamos denindo. Vamos chamar estes campos de campos de ligacao. Estes campos de ligacao nos permitir o fazer um encadeamento entre os elementos de maneira a a poder percorrer todos os elementos de um conjunto atrav s de apenas um ponteiro inicial. Al m disso, poderemos e e inserir novos elementos neste encadeamento, usando alocacao din mica. a Na linguagem Pascal podemos denir tipos recursivos das seguintes maneiras: type type TipoApontadorRegistro = TipoRegistro; TipoRegistro = record TipoRegistro = record Campos com dados do elemento Campos com dados do elemento ListaDeCamposDeLigacao: TipoRegistro; ListaDeCamposDeLigacao:TipoApontadorRegistro; end; end; Um importante exemplo de um tipo recursivo e a estrutura de dados chamada lista ligada, que assim como o vetor, representar uma seq encia de elementos. a u

Dado um conjunto de elementos

, uma lista de elementos de

pode ser denida recursivamente como:

1. Uma seq encia vazia. u 2. Um elemento de concatenado a uma lista de elementos

Para representar listas ligadas em Pascal podemos usar de registros com apenas um campo de ligacao, que indicar a o pr ximo elemento da seq encia. Usaremos um ponteiro para representar toda esta seq encia. Caso este ponteiro o u u esteja apontando para nil, estaremos representando a seq encia vazia. Vamos ver um exemplo de declarac ao de lista u ligada: type TipoElementoListaAluno = record NomeAluno: TipoString; proximo: TipoElementoListaAluno end; TipoLista = TipoElementoListaAluno var Lista: TipoLista;

151

A gura seguinte apresenta duas listas do tipo TipoLista, uma com 3 elementos e uma lista vazia:

L Jair Jeca Joca nil

L nil

Vamos chamar o elemento (ou ponteiro) que representa o incio da lista como cabecalho ou cabeca da lista e a lista comecando do segundo elemento em diante, tamb m uma lista, chamada de cauda da lista. e Primeiramente vamos descrever uma rotina para listar os elementos contidos em uma lista ligada. Para isso, usaremos um outro ponteiro auxiliar para percorrer os elementos da lista. Inicialmente este ponteiro auxiliar comecar no a cabecalho. Uma vez que tenhamos processado o elemento apontado por este ponteiro auxiliar, iremos para o pr ximo o elemento, usando o campo proximo do elemento corrente. Isto e feito at que o ponteiro auxiliar chegue no m da lista, e i.e., quando o ponteiro auxiliar tiver valor nil. A seguir apresentamos uma rotina para imprimir os nomes de alunos de uma lista ligada, bem como os tipos usados. type TipoApontElementoLista TipoElementoLista; TipoElementoLista record Aluno: TipoAluno; proximo: TipoApontElementoLista; end; TipoLista TipoApontElementoLista; procedure ImprimeAlunosLista(Lista: TipoLista); var Paux:TipoApontElementoLista; begin Paux : Lista; while (Paux nil) do begin writeln(Paux.nome, ,Paux.RA, ,Paux.CR); Paux : Paux.proximo; end; end; Vamos ver como podemos inserir um novo elemento no incio da lista . Primeiramente vamos alocar mem ria o para o novo elemento, ler os dados nesta mem ria e por m inserir o elemento no incio da lista. Para esta ultima parte o devemos tomar especial cuidado na ordem das operacoes para que nenhum elemento da lista seja perdido. Podemos dividir esta operacao nos seguintes passos: 1. Alocar mem ria para o novo elemento, digamos Paux. o 2. Ler os dados na mem ria apontada por Paux. o 3. Como Paux ser o primeiro elemento da lista , os atuais elementos da lista devem seguir Paux. Assim, podemos a fazer Paux.proximo apontar para o primeiro elemento da lista atual. 4. Atualizar o cabecalho

para que que apontando para a posicao Paux. represente uma lista vazia, a lista resultante conter uma lista com exatamente um a

A gura 41 apresenta uma rotina para insercao de um elemento no incio da lista e a conguracao da mem ria ap s o o cada comando. Note que mesmo que a lista elemento.

A id ia para desenvolver uma rotina para remover o primeiro elemento da lista segue a mesma id ia. A rotina e e RemovePrimeiroAlunoLista, descrita na p gina 153, apresenta tal operacao. a

152

program exemplo; { Inserir as declaraes do tipo TipoAluno } type TipoApontElemLista = ^TipoElemLista; TipoElemLista = record Aluno: TipoAluno; proximo: TipoApontElemLista; end;

CONFIGURAO DA MEMRIA APS COMANDOS

TipoLista = TipoApontElemLista;
procedure InsereAlunoLista(var L:Tipolista; pAux L AlunoNovo:TipoAluno); var pAux:TipoApontElemLista; lixo begin pAux new(pAux); L lixo lixo pAux pAux^.Aluno := AlunoNovo; L Joca lixo pAux pAux^.proximo := L; pAux L := pAux; end; L Joca AlunoNovo Joca L Joca AlunoNovo Joca Joo Jos nil Joo AlunoNovo Joca Jos nil Joo AlunoNovo Joca Jos nil Joo Jos nil

AlunoNovo Joca Joo Jos nil

Figura 41: Insercao de elemento em uma lista ligada. function RemovePrimeiroAlunoLista(var L:TipoLista; var AlunoRemovido:TipoAluno):boolean; var Paux:TipoApontElemLista; begin if L nil then RemovePrimeiroAlunoLista : false else begin Paux: L; Guarda o primeiro elemento antes de atualizar L L: L.proximo; Atualiza L para comecar no segundo elemento AlunoRemovido : Paux.Aluno; Copia os dados do elemento para o dispose(Paux); par metro de retorno, e libera a mem ria alocada para o elemento a o RemovePrimeiroAlunoLista: true; end; end;

Exemplo 15.2 O procedimento seguinte inverte a ordem dos elementos da lista. procedure InverteListaAluno(var p: TipoLista); var q,r,s : TipoApontElemLista; begin q : nil; r : p; while r nil do begin s : r.proximo; r.proximo : q; q : r; r: s end; p: q end;

153

Listas

Vetores
Vetores Listas simplesmente ligadas restrito ao tamanho declarado no Restrito a quantidade de mem ria disponibio vetor. lizada pelo sistema operacional. Direta. A partir do primeiro elemento at chegar ao e - simo. e E necess rio deslocar todos os Em tempo constante. a elementos de uma posicao. Processamento direto na ordem. Necessita mais processamento ou mem ria. o

Como tanto listas como vetores s o usados para representar uma seq encia ordenada de elementos, vamos ver algumas a u diferenc as entre estas duas estruturas de dados. N mero m ximo de elemenu a tos Acesso ao - simo elemento e Insercao no incio Processamento de tr s para a frente

15.3 Recursividade e Tipos Recursivos


Muitas vezes o uso de rotinas recursivas para manipular dados com tipos recursivos nos possibilita gerar rotinas simples e de f cil entendimento. Esta facilidade se deve pelo tipo ser recursivo, pois ao acessar um ponteiro para um tipo a recursivo, digamos , podemos visualiz -lo como uma vari vel que representa todo o conjunto de elementos, digamos a a , acessveis por ele. Do mesmo jeito, se um elemento deste conjunto cont m um campo de ligacao, digamos , e este representa um subconjunto com as mesmas caractersticas de . Isto permite que possamos chamar a mesma rotina que foi denida para o ponteiro recursivamente para (projeto indutivo). A gura 42 ilustra o tipo recursivo para o caso de lista ligada. O primeiro elemento apontado pelo ponteiro representa a lista inteira. O ponteiro .proximo representa uma sublista da lista original.

Lista apontada por L


L Joo

Lista apontada por L^.proximo


Jos Joca Jair Nil

Figura 42: Inserc ao no m de uma lista ligada usando recursividade.

Exemplo 15.3 Este importante exemplo mostra como podemos fazer uso de recursividade e passagem de par metros a por refer ncia para inserir um elemento no m de uma lista. e procedure InsereAlunoFimLista(var L:TipoLista; var AlunoNovo:TipoAluno); begin if L nil then begin Chegou no m da lista new(L); Aloca a mem ria para ser apontada por L o L.Aluno : AlunoNovo; Insere o ultimo elemento L.proximo : nil; Ultimo elemento deve ter campo proximo igual a nil end else InsereAlunoFimLista(L.proximo,AlunoNovo); Insere na lista denida por L.proximo end; Primeiramente verique que a chamada desta rotina para uma lista vazia ( aponta para nil) insere de fato um novo elemento, fazendo com que a lista que com um elemento. E importante observar que o ponteiro retorna atualizado, a e uma vez que o par metro foi declarado com passagem de par metro por refer ncia (usando var). a

Agora observe o caso que a lista cont m pelo menos um elemento. Neste caso, a primeira chamada recursiva deve e fazer uma nova chamada recursiva para que o elemento seja inserido no m da lista .proximo. Note que .proximo e um apontador e tamb m representa uma lista. Assim, esta segunda chamada recursiva deve inserir o elemento no m e desta sublista como desejamos. Note que mesmo que .proximo seja uma lista vazia ( .proximo=nil), este voltar a atualizado com o novo elemento.

154

A observac ao dos seguintes itens pode ajudar no desenvolvimento de rotinas para estruturas din micas, como listas a ligadas e arvores. 1. Desenvolva as rotinas simulando e representando a estrutura de dados de maneira gr ca, e.g., desenhadas em a um papel. Para cada operacao atualize seu desenho. 2. Tome cuidado na ordem das operacoes efetuadas pela rotina. Verique se ap s a execucao de um passo, n o h o a a mem ria din mica perdida. o a 3. Desenvolva inicialmente a rotina considerando uma estrutura contendo v rios elementos. Verique se a rotina a funciona para a estrutura com poucos elementos, sem elementos ou com 1 elementos. Caso necess rio, adapte a sua rotina. 4. Aproveite a volta da recurs o, para possvel processamento posterior do elemento. a 5. Se for o caso, faca a atualizac ao dos campos de ligacao por passagem de par metros por refer ncia. a e Exerccio 15.2 Um certo programa manipula cadeias de caracteres que podem ser de tamanhos bem diversos. Algu mas muito grandes outras bem pequenas. Por ter cadeias de caracteres muito longas, n o e aconselhado usar o tipo a string[ n mero de caracteres ] pois isto xaria o tamanho da maior cadeia de caracteres. Al m disso, mesmo que u e possamos limitar o tamanho m ximo, isto faria com que todas as cadeias fossem denidas usando esta quantidade de a caracteres, o que poderia gerar um desperdcio de mem ria. o Faca um programa em Pascal para manipular cadeias de caracteres, que podem ser de tamanhos bem diversos usando listas ligadas. Cada n da lista apresenta um campo, cadeia, denida como uma string de tamanho MAXCAo DEIA. Al m disso, todos os n s da lista devem usar esta quantidade de caracteres, exceto o ultimo n que pode ter e o o menos caracteres. O valor de MAXCADEIA e uma constante inteira apropriada, n o muito grande. O programa deve a ter os seguintes tipos e rotinas: const MAXCADEIA 10; CadeiaVazia nil; type tipoString String[MAXCADEIA]; Str regStrString; regStrString record cadeia : tipoString; proximo : Str; end; function Strlength(s:Str):integer; Retorna a quantidade de caracteres da string s procedure Strwrite(s:Str); imprime uma String na tela, sem pular linha procedure Strwriteln(s:Str); imprime uma String na tela, pulando linha procedure StrConcatChar(var s:Str; c:char); Concatena um caracter no m da String s. procedure StrReadln(var s:Str); Leitura de uma string, colocando caracter por caracter function StrKesimo(s:Str ; K:integer):char; Retorna o k esimo caracter de s

retorna em destino uma cadeia do tipo Str comecando do caracter de origem da posicao a e inicio at (iniciotam 1). Se n o houver caracteres da String at a posicao e (iniciotam 1), ou anteriores, estes n o s o inseridos na cadeia de destino. a a procedure StrSubString(var destino:str; origem:Str ; inicio , tamsub:integer); Retorna em destino uma nova String formada pela concatenacao de s1 e s2 procedure StrConcat(var destino:str ; origem:Str); Retorna em destino uma copia da string origem procedure StrCopy(var destino:str ; origem:Str); Libera a mem ria (obtida por alocacao dinamica) da lista ligada o procedure Strlibera(var ls:Str );

155

15.4 Exerccios
1. 2. 3. 4. 5. 6. Faca um procedimento recursivo para imprimir uma lista de alunos, na ordem da lista. Faca um procedimento recursivo para imprimir uma lista de alunos, na ordem inversa da lista. Faca um procedimento n o recursivo para inserir um aluno no m da lista. a Faca um procedimento recursivo para remover um aluno com certo nome da lista. Faca um procedimento recursivo para duplicar uma lista em ordem inversa. Uma lista ligada e declarada da seguinte maneira: type TipoString = string[255]; TipoElementoLista = record nome: TipoString; proximo: TipoElementoLista; end; TipoLista = TipoElementoLista; Faca uma rotina recursiva com o seguinte cabecalho procedure InsereOrdenadoLista(var L:TipoLista; Nome:TipoString); A rotina insere um novo elemento na lista, com nome dado no par metro Nome. A funcao insere de maneira ordea nada, i.e., os elementos devem estar ordenados. Al m disso, a lista j cont m os elementos e a e ordenados antes da insercao. A seguinte gura apresenta exemplo de duas listas ordenadas do tipo TipoLista, uma com 3 elementos e uma lista vazia:
L L Jair Jeca Joca nil nil

7. Faca um procedimento para ordenar uma lista ligada, usando o algoritmo do quicksort tomando sempre o pri meiro elemento como piv . o 8. Uma lista e dita circular quando temos uma lista muito parecida com a lista ligada, com excecao que o ultimo elemento da lista (campo pr ximo do ultimo elemento) aponta para o primeiro elemento da lista. Na gura o seguinte apresentamos a representac ao de listas circulares com 4 elementos, 1 elemento e lista vazia.
L Joo Jos Joca Jair L Joo L Nil

Faca uma rotina que insere um elemento em uma lista circular (n o estamos preocupados na posicao da lista a circular onde o elemento vai ser inserido). Faca uma rotina para remover um elemento da lista, caso este exista. 9. Em um certo jogo temos v rios homens que devem ser executados, sendo que eles est o dispostos de maneira a a a formar um crculo. O carrasco pode escolher um dos homens para ser libertado e usa a seguinte regra: Ele escolhe um primeiro homem a ser executado, executa-o e escolhe o segundo homem ap s o homem que acabou o de ser executado como pr ximo homem a ser executado. Isto continua at que tenha sobrado apenas um homem, o e sendo que este homem e libertado. Faca um programa que leia uma lista de nomes de homens e coloque em uma lista circular. Em seguida le o nome do primeiro homem a ser executado. A partir disto, lista na ordem o nome dos homens a serem executados, e por m o nome do homem libertado. 10. Quando temos uma lista ligada s podemos caminhar por esta lista apenas em um dos sentidos. Uma maneira de o contornar este tipo de restricao e usar uma lista duplamente ligada. Neste tipo de lista temos em cada elemento dois campos de ligacao. Um chamado proximo, que tem a mesma funcao que o campo proximo em listas ligadas e outro campo chamado anterior, que aponta para um elemento anterior na seq encia denida pelo u campo proximo. O primeiro elemento da lista tem seu campo anterior com valor nil. A gura seguinte apresenta uma lista duplamente ligada com 4 elementos. Faca um programa com rotinas para insercao no incio da lista, remocao do primeiro elemento e remocao de um elemento com um determinado nome.
L Joo Nil Jos Joca Jair Nil

156

16 Usando e Construindo Biblioteca de Rotinas


Um dos fatores que contribuem para que possamos construir programas de maneira mais produtiva e o uso de biblioteca de rotinas ou unidades. A id ia e ter o c digo do programa execut vel gerado por partes a partir de v rias unidades. e o a a Apresentamos a seguir algumas vantagens de se usar unidades.

Reaproveitamento de c digo. A implementacao de uma mesma rotina pode ser usada em diversos programas o sem necessidade de recodicac ao. Divulgar rotinas para serem usadas com outros programas em Pascal sem que seja necessario divulgar seu c digo o fonte. Uso de bibliotecas livres. Muitos compiladores ja oferecem rotinas, na forma de bibliotecas, para manipulacao

de objetos mais complexos. Exemplo disso s o unidades para manipulacao de janelas gr cas, disponibilizado a a por muitos compiladores. Divis o funcional do programa. O uso de unidades permite dividir o programa em pedacos menores com o a conjunto de rotinas divididas segundo algum crit rio. e Agilizar a geracao do c digo do programa execut vel. Cada unidade pode ser compilada separadamente e o a seu c digo objeto pode ser ligado ao de outros para formar o programa execut vel. Caso haja necessidade da o a recompilac ao de uma das unidades, apenas aquela dever ser compilada. a

At agora descrevemos programas formados por apenas uma unidade, o programa principal. As demais unidades e podem ser descritas atrav s de units da linguagem Pascal. Uma unit tem uma organizac ao parecida com a de um e programa Pascal. As sintaxes do padr o Borland Pascal e Extended Pascal s o diferentes, embora parecidas. Optamos a a por apresentar apenas a sintaxe do padr o Borland Pascal. O leitor interessado n o ter diculdades em transformar a a a programas descritos na sintaxe Borland Pascal para o padr o do Extended Pascal. a

16.1 Estrutura de uma unit


Uma unidade, no padr o Borland Pascal, e formada por tr s partes: uma Parte P blica, uma Parte Privada e um a e u C digo de Inicializacao (opcional). Na gura seguinte apresentamos a estrutura de uma unidade e nas secoes seguintes o detalharemos cada uma destas partes. unit Identicador Unit ; interface Parte P blica u implementation Parte Privada

begin
end.

C digo de inicializac ao Opcional o

Parte Publica
Na parte p blica fazemos as declarac oes dos objetos que poder o ser visualizados por programas ou outras unidades. u a Nesta parte podemos declarar constantes, tipos, vari veis e prot tipos de rotinas. A declarac ao de constantes, tipos e a o vari veis e feita com a mesma sintaxe vista anteriormente. J os prot tipos de rotinas s o os cabecalhos das rotinas a a o a que ser o visualizadas pelas outras unidades. A seguir exemplicamos os prot tipos das rotinas BuscaBin (veja p gina a o a 104) e SelectionSort (veja p gina 75), vistas anteriormente. a function BuscaBin(var v:TipoVet; inicio,m:integer; x:real):integer; procedure SelectionSort(var V:TipoVetorReal; n:integer); 157

Naturalmente todos os tipos n o b sicos usados nestes prot tipos dever o ter sido previamente declarados na unidade a a o a ou obtidos atrav s de alguma outra unidade. e A implementacao das rotinas n o e descrita nesta parte, mas apenas seu cabecalho para que possamos saber como a ser feita a interface destas com o programa que far uso delas. a a Dentro da parte privada podemos usar ou aproveitar as declaracoes de objetos feitas em outras unidades. Para isso, devemos colocar imediatamente depois da palavra interface o seguinte comando uses lista de unidades ; Com este comando podemos descrever (depois da palavra uses) a lista de units que estamos usando para construir a parte p blica. u

Parte Privada
Nesta parte descrevemos os objetos (constantes, tipos, vari veis, funcoes e procedimentos) que n o poder o ser vistos a a a por outras unidades. Todos os objetos que foram declarados na parte p blica podem ser utilizados nesta parte, mas u as declaracoes feitas dentro da parte privada n o podem ser utilizados fora da unidades. E nesta parte que iremos a descrever a implementac ao completa das rotinas que tiveram os prot tipos declarados na parte p blica, bem como de o u outras rotinas auxiliares. Al m disso, o c digo desta implementac ao s poder ser visto pelo usu rio se este tiver o e o o a a c digo fonte da unidade (um usu rio n o necessariamente precisa do c digo fonte de uma unidade para us -lo). o a a o a Aqui tamb m podemos fazer uso de outras unidade. Para isso, devemos colocar imediatamente depois da palavra e implementation o seguinte comando uses lista de unidades ;

C digo de Inicializacao o
Esta parte e opcional e serve para executar um c digo de inicializac ao da unidade antes da execucao do c digo do o o programa principal. Para descrever esta parte, devemos colocar a palavra begin logo depois da descricao das rotinas da parte privada e antes de end (indicador do m da unit). O c digo de inicializac ao da unidade e descrito no bloco o de comandos formado por este begin e end. Caso uma unidade faca uso de v rias unidades, suas inicializac oes ser o a a feitas na ordem descrita no comando uses.

16.2 Usando Units


Para declarar o uso de unidades no programa principal, devemos inserir a seguinte cl usula no incio da area de a declarac oes do programa principal uses lista de unidades ; No quadro seguinte apresentamos um exemplo de como poderamos declarar uma unidade para manipulac ao de n meros complexos. u

158

unit complexos; Arquivo: complexos.pas interface type complex record a,b : real; N mero na forma (ab.i) u end; procedure LeComplex(var x : complex); Le um n mero complexo u procedure ImpComplex(x : complex); Imprime um n mero complexo u function SomComplex(x,y:complex):complex; soma de dois n meros complexos u function SubComplex(x,y:complex):complex; subtracao de dois n meros complexos u function MulComplex(x,y:complex):complex; multiplicacao de dois n meros complexos u implementation procedure LeComplex(var x : complex); Le um n mero complexo u begin writeln(Entre com um nmero complex (a+b.i) entrando com a e b: ); u readln(x.a,x.b); end; LeComplex procedure ImpComplex(x : complex); Imprime um n mero complexo u begin writeln((,x.a:5:2,+,x.b:5:2,i)); end; ImpComplex function SomComplex(x,y:complex):complex; soma de dois n meros complexos u var z : complex; begin z.a : x.ay.a; z.b: x.by.b; SomComplex : z; end; SomComplex function SubComplex(x,y:complex):complex; subtracao de dois n meros complexos u var z : complex; begin z.a : x.a y.a; z.b: x.b y.b; SubComplex : z; end; SubComplex function MulComplex(x,y:complex):complex; multiplicacao de dois n meros complexos u var z : complex; begin z.a : x.a y.a x.b y.b; z.b: x.a y.bx.b y.a; MulComplex : z; end; MulComplex end.

No programa seguinte apresentamos um exemplo de programa que usa esta unit. program ProgComplex; Arquivo: principal.pas uses complexos; var x,y : complex; begin LeComplex(x); LeComplex(y); write(A soma dos nmeros complexos lidos ); ImpComplex(SomComplex(x,y)); u e write(A subtraco dos nmeros complexos lidos ); ImpComplex(SubComplex(x,y)); a u e write(A multiplicaco dos nmeros complexos lidos ); ImpComplex(MulComplex(x,y)); a u e end.

159

Usando GPC para compilar e ligar unidades


Antes de apresentar as alternativas para gerar o programa execut vel usando unidades no GPC, vamos precisar de duas a denicoes: Arquivos gpi e arquivos com c digo objeto. o (i) Arquivos GPI (GNU Pascal Interface): S o arquivos que cont m as informacoes pr -compiladas da interface da a e e unidade. N o cont m o c digo de m quina das rotinas da unidade. O nome dos arquivos deste tipo tem extens o a e o a a .gpi. (ii) Arquivos com c digo objeto: S o estes arquivos que cont m a codicacao em linguagem de m quina das unidades o a e a ou do programa principal principal. Em geral s o arquivos com extens o .o. a a A seguir descrevemos tr s maneiras para se gerar o programa execut vel usando unidades no GPC. e a 1. Usando a opcao automake: Nesta opcao, o compilador compila apenas as unidades que foram modicadas ou aquelas que direta ou indiretamente fazem refer ncia a unidade modicada. Sintaxe: e ` gpc - -automake - -borland-pascal lista de unidades programa principal.pas -o arquivo execut vel a Ap s a execucao deste comando, s o gerados os arquivos GPI e os arquivos objetos de cada unidade. o a Caso o nome do arquivo de cada unidade, sem a extens o .pas, for igual ao identicador da unidade, ent o a a n o e necess rio especicar a lista de unidades no comando acima. Todas as unidades que forem referenciadas a a direta ou indiretamente ser o consideradas na compilacao. Neste caso, o comando pode ser resumido para: a gpc - -automake - -borland-pascal programa principal.pas -o arquivo execut vel a 2. Especicando todos os arquivos fontes: Nesta opcao, o compilador compila todos os arquivos fontes para gerar um arquivo execut vel. A seguir apresentamos uma sintaxe para o comando de compilac ao: a gpc - -borland-pascal lista de unidades programa principal.pas -o arquivo execut vel a No comando acima, a lista de unidades e separada por espacos em branco e deve seguir uma ordem. Se uma unidade faz uso de uma unidade , ent o deve vir antes de . O compilador GPC gera um arquivo GPI a para cada unidade mas n o gera arquivos objetos. a Esta maneira de compilar os programas e mais lenta, uma vez que todos os arquivos fonte s o compilados. a 3. Gerando o c digo objeto: Neste caso, a compilacao de uma unidade pelo GPC deve ser feita com a opcao -c o (sem aspas). Por exemplo, a unidade complexos.pas poderia ter sido compilada com o seguinte comando: gpc - -borland-pascal -c complexos.pas Ap s este comando, obtemos os arquivos GPI e objeto da unidade complexos.pas. Para gerar o c digo exeo o cut vel, basta entrar com o seguinte comando: a gpc complexos.o principal.pas -o executavel O compilador distingue os arquivos no formato pascal (.pas) e os arquivos j compilados (.o). Para os arquivos a no formato pascal, o compilador gera seu c digo objeto (correspondente .o) e liga todos estes c digos objetos o o em apenas um programa execut vel. a Uma vez que temos o arquivo gpi e o c digo objeto da unidade, n o mais necessitamos do seu c digo fonte. Nao a o turalmente, se houver necessidade de mudar o c digo fonte ou de gerar c digo para um outro tipo de computador, o o os arquivos gpi e o c digo objeto dever o ser gerados novamente a partir do arquivo fonte da unidade. o a

16.3 Exerccios
1. Faca uma unit em um arquivo chamado numerico.pas com as seguintes operacoes para manipulac ao de n meros u e rotinas num ricas: (i) C lculo de uma raiz de funcao usando o m todo da bissecao, (ii) c lculo da integral e a e a denida (iii) vericacao da primalidade de um n mero, (iv) funcoes num ricas como: c lculo da raiz quadrada, u e a seno, cosseno, fatorial, pot ncia, exponencial etc. e 2. Faca uma unit em um arquivo chamado cadeias.pas com as seguintes operac oes para manipulac ao de cadeia de caracteres: (i) Insercao de cadeias em outras (insert), (ii) busca de uma cadeia em outra, (iii) demais operac oes como: mudanca para mai sculas ou min sculas, remocao de acentos etc. u u 3. Faca uma unit em um arquivo chamado ordena.pas com as seguintes rotinas para ordenar vetores de n meros u reais: SelectionSort, MergeSort e QuickSort. Al m disso insira rotinas auxiliares como: para fazer busca bin ria, e a intercalar dois vetores ordenados em um terceiro vetor etc. 160

4. Faca uma unit para manipulac ao de inteiros longos. Cada inteiro longo ser armazenado como um vetor de a dgitos. Al m disso cada inteiro longo ter um atributo que deve ser o n mero de dgitos usado pelo n mero e a u u representado. Faca rotinas para manipular estes n meros, como por exemplo: (i) Leitura de inteiro longo, (ii) u Soma, (iii) Subtracao, (iv) Multiplicac ao, (v) Divis o inteira, (vi) Resto de divis o inteira de dois inteiros longos a a e (vii) Impress o de inteiros longos. a

161

Indice Remissivo
, 78 Algebra Booleana, 7 Algoritmo, 3 Alinhamento de comandos, 48 Alocacao din mica, 149 a and, 18 append, 127 Arquivos, 126 bin rios, 131 a texto, 126 assign, 126 Base da recurs o, 101, 102 a Bit, 4 Bloco de Comandos, 26 Boolean, 14 Borland Pascal, 28, 118 Byte, 4 C lculo do CPF, 89 a C lculo do dia da semana, 89 a crculo, 142 campos de ligacao, 151 carriage return, 126, 128 Char, 14 Cifra de C sar, 87 e close, 127 Codicacao ASCII, 4 Comando , 15 Begin...End, 26 Case, 27 Dec, 20 For, 31 forward, 102 If-then, 25 If-then-else, 25 Inc, 20 Read, 22 Readln, 22 Repeat, 36 While, 34 With, 97 Write, 20, 128 Writeln, 20, 128 Coment rios, 11 a Compilador, 2 Concat, 80 const, 13 Convers o de n meros romanos, 89 a u Copy, 80 CPU, 1 Criptograa, 87 Delete, 80 dispose, 149 div, 17 Endereco de uma vari vel, 146 a eof, 127 erase, 136 Extended Pascal, 28, 118 false, 14 fatorial, 77 bonacci, 77 gura, 139 le, 131 lepos, 136 lesize, 128 ush, 136 Fluxograma, 9, 10 Formato PPM, 139 freeware, 139 Funcao Abs, 20 ArcTan, 20 Chr, 20 Cos, 20 Exp, 20 Frac, 20 Int, 20 Length, 20 Ln, 20 Ord, 20 Random, 20 Round, 20 Sin, 20 Sqr, 20 Sqrt, 20 Trunc, 20 Funcoes, 19, 71 function, 71 Gigabyte, 4 Gr cos, 139 a Hardware, 2 Insert, 80 Integer, 14 Intercalacao de dois vetores., 61 internet, 82 Interpretador, 2 Irfan View32, 139 Kilobyte, 4 Length, 80 line feed, 126, 128 Linguagem Assembler, 2 de Alto Nvel, 2 de M quina, 2 a Pascal, 9 Listas circulares, 156 duplamente ligadas, 156 ligadas, 151154, 156 M todo e da Bissecao, 120 Matrizes, 63 Megabyte, 4 Mem ria o Cache, 1 de vdeo, 139 Principal, 1 RAM, 1

162

ROM, 1 Secund ria, 2 a mod, 17 Modularizacao de programas, 76 N meros por extenso, 88 u new, 149 nil, 146 not, 18 Operadores Aritm ticos, 17 e Em strings, 19 L gicos, 18 o Relacionais, 18 or, 18 Par metros, 67 a funcoes e procedimentos, 118 Perif rico, 2 e pixel, 139 Ponteiros, 146 Pos, 80 Pot ncia: , 20 e PPM, 139 Preced ncia entre operadores, 19 e procedimentos, 66 procedure, 66 Programas Algoritmo de Euclides, 3, 37 Busca bin ria, 62, 104 a Busca de padr o em texto, 85 a Busca sequencial em um vetor, 59 BuscaSequencial, 59 C lculo de , 39 a C lculo do MDC, 3, 37 a Cadastro de Alunos em Arquivo, 134 Cifra de C sar, 87 e Comandos de escrita, 21 Comandos de leitura, 22 Coment rio, 11 a Concatenacao de strings, 19 Constantes, 13 Convers o para mai sculas, 84 a u Denicao de tipos novos, 53 Desenho de Crculo, 142 Desenho de Reta, 142 Desvio padr o, 58 a Equacao do segundo grau, 27, 74 Erro de precis o, 50 a Escrita em Arquivo Bin rio, 133 a Exponencial, 76, 77 Fatorial, 31, 72, 101 Fibonacci, 105 Figura de Rosto, 144 Formato PPM, 141 Funcao cubo, 71 Hello world, 10 Idade, 12, 13 Impress o de vetor em ordem inversa, 57 a Impress o em lista ligada, 152 a ImprimeVetorReal, 57 Indice do m ximo em um vetor, 58 a Indmaximo, 58 Insercao no m de listas ligadas, 154 Insert, 81 Intercala, 61 Inverte, 57 Inverte Lista, 153

Lados de um tri ngulo, 41 a Leitura de Arquivo Bin rio, 133 a Leitura de Arquivo Texto, 128 Leitura de vetor e impress o dos elementos acima da a m dia, 57 e Leitura e impressao de matrizes, 63 LeVetorReal, 57 M ximo de 2 n meros, 25, 26, 71 a u M ximo de tr s, 67 a e M ximo divisor comum, 72 a M ximo valor de uma seq encia, 32 a u M dia e maiores notas, 56 e M dias e maiores notas, 55 e Menu, 29 MergeSort, 112 Multiplicacao de matrizes, 64 N mero primo, 49, 50, 72 u N meros Complexos, 92, 159 u Ordena 3 n meros, 41, 42, 69 u Ordenacao usando ponteiros, 148 Palndrome, 82 ParesImpares, 101 Passagem de par metros, 68 a Pos, 81 Pot ncia, 20 e Procedimento, 67 QuickSort, 115 Remocao de brancos repetidos, 129 Remocao em listas ligadas, 153 SelectionSort, 60, 75 Soma 3 n meros, 16 u Tabuada, 32 Tiraacentos, 83 Torre de Hanoi, 103 Tri ngulo de Floyd, 33 a Tri ngulo de Pascal, 60 a TrocaReal, 69 Units, 159 Validacao de entrada, 70 Programas de computador, 2 Projeto de Algoritmos por inducao, 100 por divis o e conquista, 111 a RAM, 1 Random access memory, 1 read, 127, 131, 132 Real, 14 Recursividade, 100 Registrador, 1 Registros, 91 Fixos, 91 Variantes, 94 rename, 136 reset, 126, 131 reta, 142 rewrite, 127, 132 RGB, 139 seek, 132 SetLength, 80 shareware, 139 Sistema Operacional, 2 Software, 2 String, 14 text, 126 Tipoaluno, 93 Tipos

163

Boolean, 14 Byte, 14 Char, 14 Escalar, 23 Faixa, 23 Integer, 14 Real, 14 Recursivos, 151, 154 String, 14 tipos b sicos, 14 a true, 14 type, 53 Unidade, 159 Unidade Central de Processamento, 1 Unidade de Controle, 1 Unidade de Entrada, 1 Unidade de Sada, 1 Unidade L gica e Aritm tica, 1 o e Unit, 159 vdeo, 139 Valor em um endereco de mem ria, 146 o var, 15 Vetores, 55 Vetores Multidimensionais, 63 write, 131, 132

164

Vous aimerez peut-être aussi