Académique Documents
Professionnel Documents
Culture Documents
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.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 de Controle
Memrias Secundrias Memria Cache Registradores
Unidades de Sada
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.
Programa Fonte
Compilador
Programa Executvel
Programa Executvel
Sistema Operacional
CPU
Sistema Operacional
CPU
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
e e atrav s e
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 .
; until writeln( );
; ;
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
. . .
. . .
. . . . . . . . . . . .
. . .
. . .
. . .
. . .
. . .
. . .
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
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
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 ( ).
. E
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
. . .
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 ?
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.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 .
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
N2
2.N1 + 3.N2 5
N E
N+E 2
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.
11
INICIO
WRITE(Bom );
WRITELN(Dia!);
FIM
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:
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;
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;
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
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
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
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
e true (verdadeiro). Como a codicacao de A em ASCII e menor que a, ent o o resultado da relacao 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
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.
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
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.
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.:
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
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.
ou
true
false
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.
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.
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
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.
VC:=VI; Condio
VC>VF
true
VC := VC + 1; {OBS:} {VC = Varivel de Controle} {VI = Valor Inicial} {VF = Valor Final}
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.
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
1 2 3 4 5 6 1 4 9 16 25 36
1 8 27 64 125 216
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.
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
igual a 6.
33
Condio C true
false
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.
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
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
Comando1 Comando2
C true
Condio
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
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
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
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
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
ent o a ent o a
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
type
var
end;
end;
. . .
end;
. . . until (Condicao);
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
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
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
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
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 ,
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.:
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
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
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.
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
5. Escreva um programa que imprime um Tri ngulo de Pascal de ordem a um vetor e apenas um comando de repeticao for.
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
67
onde . . .
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 }
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
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.
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
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
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
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;
e; I; u; A; e; O; o; U;
Exerccio 8.1 Faca uma funcao que tem como par metro uma cadeia de caracteres e retorna a mesma cadeia sem a acentos.
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
84
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
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:
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
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
O dgito
recebe o valor 0.
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:
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
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.
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.
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
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.
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
var n : integer; begin write(Entre com um nmero: ); u readln(n); writeln(O fatorial de ,n, igual a ,fatorial(n)); e end.
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.
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
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.
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;
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
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
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:
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:
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
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
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
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
Figura 36: Intercalac ao de dois sub-vetores. procedure MergeSort(var V : TipoVetorReal; n:integer); var Vaux : TipoVetorReal; vetor auxiliar para fazer intercalacoes
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
, 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 .
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
dir i
V 10 12 7 13 9 Vaux
esq Pivo
2 15 9 17 7 12
dir
V 10 12 7 13 9 Vaux 7
esq Pivo i
2 15 9 17 7 12
dir
V 10 12 7 13 9 Vaux 7
esq Pivo
2 15 9 17 7 13 12
dir
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
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
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
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
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;
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
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
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;
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
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
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
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
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.
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
e dois vetores
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
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)
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
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 .
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
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
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.
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.
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;
p q p q
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
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 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;
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
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
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
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
begin
end.
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.
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
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