Prévia do material em texto
UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO CENTRO DE CIÊNCIAS AGRÁRIAS DEPARTAMENTO DE ENGENHARIA RURAL ENG06842 PROGRAMAÇÃO I PARTE 2 Prof. Geraldo Regis Mauri CCA-UFES Agosto - 2009 ENG06842 – Programação I Sumário 7.Linguagens de programação e execução de programas ........................................................... 3 7.1.Introdução ............................................................................................................................. 3 7.2.Tradutores: compiladores e interpretadores .......................................................................... 5 7.3.Compilador PASCAL ........................................................................................................... 6 7.4.Exercícios ............................................................................................................................ 14 8.A Linguagem Pascal .............................................................................................................. 16 8.1.Introdução ........................................................................................................................... 16 8.2.Tipos de dados simples ....................................................................................................... 16 8.3.Mapeamento Portugol x Pascal ........................................................................................... 18 8.4.Unidades pré-definidas ....................................................................................................... 21 8.5.Palavras reservadas ............................................................................................................. 22 8.6.Funções pré-definidas ......................................................................................................... 22 8.7.Tipos definidos pelo usuário ............................................................................................... 29 8.8.Exercícios ............................................................................................................................ 31 9.Estruturas de dados ................................................................................................................ 33 9.1.Introdução ........................................................................................................................... 33 9.2.Variáveis compostas homogêneas ...................................................................................... 33 9.3.Variáveis compostas heterogêneas ..................................................................................... 39 9.4.Algoritmos de classificação e busca ................................................................................... 46 9.5.Exercícios ............................................................................................................................ 48 10.Modularização ...................................................................................................................... 51 10.1.Introdução ......................................................................................................................... 51 10.2.Procedimentos ................................................................................................................... 52 10.3.Funções ............................................................................................................................. 53 10.4.Escopo de variáveis ........................................................................................................... 56 10.5.Parâmetros ......................................................................................................................... 56 10.6.Recursividade .................................................................................................................... 60 10.7.Exercícios .......................................................................................................................... 60 11.Armazenamento de dados .................................................................................................... 67 11.1.Arquivos ............................................................................................................................ 67 11.2.Exercícios ..........................................................................................................................76 Referências ................................................................................................................................ 78 Apêndice A – Mensagens de erro do Turbo Pascal .................................................................. 79 Apêndice B – Tabela de códigos ASCII ................................................................................... 82 2 ENG06842 – Programação I 7. Linguagens de programação e execução de programas 7.1. Introdução A linguagem de programação é o meio pelo qual se pode indicar os “passos” que devem ser realizados pelo computador para resolver problemas. Utilizando as linguagens de programação, pode-se colocar os algoritmos numa forma que o computador possa interpretá-los, ou seja, na forma de programas computacionais. Para que o computador execute o algoritmo proposto, as operações devem ser transcritas para uma linguagem que a máquina consiga compreender. Na realidade, os computadores só podem executar algoritmos expressos em linguagem de máquina, que se constitui de um conjunto de instruções capazes de ativar diretamente os dispositivos eletrônicos do computador. Características da Linguagem de Máquina: • diferente para cada tipo de computador, dependendo de sua arquitetura; • extremamente rudimentar, onde até as operações mais simples têm que ser expressas em termos de registros, acumuladores e outros dispositivos de máquina; • totalmente expressa em forma numérica - sistema de numeração binário (0s e 1s) ou hexadecimal. Conseqüentemente, é uma linguagem de difícil aprendizado e pouco expressiva para as pessoas. Para tornar a atividade de programação mais acessível, foram desenvolvidas outras linguagens, denominadas de “Linguagens de Programação”, que funcionam como uma forma alternativa de se comunicar com o computador. 3 ENG06842 – Programação I As linguagens de programação são compostas por um grupo de elementos e regras que permitem a construção das instruções utilizadas para resolver os problemas computacionais. Com elas, pode-se construir programas que devem ser, posteriormente, transformados em instruções em Linguagem de Máquina. Para realizar a transformação, cada linguagem de programação possui um programa-suporte denominado, genericamente, de tradutor. Linguagem de Programação de Baixo Nível: Conhecida como Linguagem Assembler ou Linguagem de Montagem, ou ainda, Linguagem Simbólica. Utiliza números binários, hexadecimais, alguns símbolos e letras para compor os programas. Está muito próxima da Linguagem de Máquina, onde cada instrução simbólica corresponde, praticamente, a uma instrução de máquina. Para transformar o programa escrito em Linguagem Assembler em código de máquina executável, é utilizado um programa- suporte denominado de MONTADOR. Linguagens de Programação de Alto Nível: São linguagens de programação que utilizam notações matemáticas e grupos de palavras para representar as instruções de máquina, tornando o processo de programação mais próximo do entendimento humano. Muitas destas linguagens foram desenvolvidas para atender os problemas de áreas de aplicação específicas, como, por exemplo, linguagens para aplicações comerciais, científicas, administrativas, de ensino, etc. A primeira linguagem de alto nível foi desenvolvida em 1957 - denominada de FORTRAN (Formula Translator) - e destina-se a aplicações científicas e de engenharia. Principais vantagens das linguagens de Alto Nível: • facilidade de entendimento e uso; • independência de máquina (é praticamente a mesma, não importando o computador utilizado). 4 ENG06842 – Programação I Para transformar os programas escritos com Linguagens de Alto Nível em códigos de máquina, é usado um programa-suporte denominado TRADUTOR (Compilador ou Interpretador). 7.2. Tradutores: compiladores e interpretadores Para executar um programa escrito numa linguagem de alto nível é preciso primeiro traduzir o código-fonte para código-objeto. O processo de tradução pode dar-se em tempo de execução caso a linguagem use um interpretador (traduz e executa instrução a instrução), ou todas as instruções podem ser traduzidas antes que se inicie a execução do programa, o que ocorre no caso de linguagens que usam tradutores do tipo compilador. Código-fonte: não é executável diretamente pelo processador - permite apenas que o programador consiga definir o programa em uma forma legível aos humanos. Código-objeto: é o código produzido pelo compilador; é uma forma intermediária, similar a linguagem de máquina do computador. Apesar de estar representado em binário, não é executável diretamente pelo processador, pois normalmente, o código-objeto referencia partes de programa que não estão necessariamente definidas no mesmo arquivo que o gerou, por exemplo, arquivos de bibliotecas de sub-rotinas. Editores de ligação (ou linkeditores ) : Um programa que reúne módulos compilados e arquivos de dados para criar um programa executável. Os linkeditores têm também outras funções, como a criação de bibliotecas. Compilador: No sentido mais geral, qualquer programa que transforme um conjunto de símbolos em outro obedecendo a uma série de regras sintáticas e semânticas; no sentido mais comum, um programa que traduz 5 ENG06842 – Programação I todo o código-fonte de programas escritos numa linguagem de alto nível em código-objeto antes da execução do programa. Ou seja, traduz o programa escrito em linguagem de alto nível (código-fonte) para um programa equivalente escrito em linguagem de máquina (código-objeto). Interpretador: traduz e envia para execução, instrução por instrução e o programa permanece na forma fonte. 7.3. Compilador PASCAL O Turbo Pascal é um programa que contém, além do compilador PASCAL, um ambiente completo de programação, com editor de programa, depurador de erros, sistema de ajuda, etc. Existem diversos compiladores para a linguagem Pascal, porém para esse curso, será utilizado como padrão o compilador Borland Turbo Pascal 7.0, pois este é um programa gratuito e de simples utilização. Algumas dicas para aquisição e instalação deste programa são apresentadas no Erro: Origem da referência não encontrada. O ambiente de desenvolvimento do Turbo Pascal (ver figura abaixo) é composto de um editor de texto, um compilador, um programa ligador (linkeditor) e um depurador (debugger), harmonicamente integrados. 6 ENG06842 – Programação I Após editar um arquivo, é natural compilá-lo e rodá-lo, para ver os resultados do programa. Durante esse processo, o Turbo Pascal irá procurar erros em tempo de compilação. Senão houver erros, o programa rodará normalmente. Caso contrário, o processo de compilação será interrompido e o compilador indicará o erro e a sua posição. Os programas podem conter três tipos de erros: Erro de sintaxe: ocorre quando se viola uma regra da linguagem. Ao encontrar um destes erros, o Turbo Pascal interrompe a compilação do programa, dá uma mensagem com o número e a descrição do erro, e deixa o cursor piscando no item do programa que permitiu a detecção do erro. Deve-se observar que este item pode não estar errado, mas apenas permitiu detectaro erro. O Turbo Pascal não executa um programa enquanto houver erros de sintaxe. Erro de semântica: é um erro que o programa detecta durante a sua execução, interrompendo-a; por exemplo, quando o programa é levado a ler um arquivo inexistente, a tirar a raiz quadrada de um número negativo, a dividir por zero, etc. Ocorrendo um erro de semântica, o Turbo Pascal interrompe a execução do programa e mostra a descrição do erro, com o cursor piscando no início da linha em que ele foi detectado. 7 ENG06842 – Programação I Erro de lógica: aparece em programas, sintática e semanticamente corretos, que, apesar disso, não produzem os resultados desejados. São devidos a instruções corretas, para o computador, mas que não são apropriadas para a solução lógica do problema que motivou o programa. A correção dos erros de lógica é muitas vezes trabalhosa e demorada. Para ajudar a depuração de erros de lógica, o Turbo Pascal oferece diversos recursos que permitem ver e acompanhar o que ocorre durante a execução de um programa. Erros de sintaxe e semântica não são preocupantes, pois o próprio computador os localiza e os identifica. Uma lista com os principais erros apresentados no Turbo Pascal são descritos no Apêndice A – Mensagens de erro do Turbo Pascal. Para compilar um programa, deve-se utilizar a opção COMPILE (compilar) do Menu COMPILE ou pressione Alt+F9. Caso seja detectado algum erro (de sintaxe), este será exibido na tela, caso contrário, será exibida uma mensagem dizendo que o programa foi compilado com sucesso. A partir daí, basta pressionar qualquer tecla para fechar essa mensagem e executar o programa. Para executar um programa, deve-se utilizar a opção RUN (executar) do Menu RUN ou pressione Ctrl+F9. Ao terminar a execução, o Pascal volta para a janela de edição. Para ver os resultados do programa, basta pressionar Alt+F5. O Turbo Pascal 7.0 também oferece alguns recursos para depuração do programa. Um desses recursos é a utilização de break points (pontos de parada). Para sua utilização, basta clicar com o botão direito do mouse sobre a linha onde a execução do programa deverá parar, e selecionar a opção Toogle breakpoint (ou pressionar Ctrl+F8). A linha ficará vermelha, e quando o programa for executado, assim que seu fluxo de execução chegar nessa linha, será possível acompanhar passo-a-passo o restante da execução do programa. Para isso, basta pressionar a tecla F8, que cada instrução subseqüente será executada uma a uma. Para verificar o 8 ENG06842 – Programação I conteúdo das variáveis presentes na instrução atual, basta pressionar Ctrl+F4, ou clicar com o botão direito e selecionar a opção Evaluate/Modify. A seguir são descritos os menus do Turbo Pascal 7.0. File – esta opção possibilita executar operações de controle com arquivos. o New – criar um novo programa. o Open – abrir um programa existente. o Save – salvar um programa em disco. o Save as – salvar um programa em disco com outro nome. o Save all – salvar todos os programas modificados. o Change dir – mudar o diretório de trabalho. o Print – imprimir o programa da janela ativa. o Print setup – configurar o uso de outra impressora. o DOS shell – sair temporariamente para o sistema operacional (DOS). o Exit – finalizar a execução do Turbo Pascal. Edit – esta opção possibilita executar operações do editor do programa, sendo possível remover, movimentar e copiar textos que estejam selecionados. o Undo – desfazer uma operação com texto. o Redo – refazer uma operação com texto. 9 ENG06842 – Programação I o Cut – remover um texto previamente selecionado, enviando-o para área de transferência. o Copy – copiar um texto selecionado do editor para uma área de transferência. o Paste – copiar um texto da área de transferência para o editor. o Clear – remover o texto selecionado sem transferi-lo para a área de transferência. o Show Clipboard – apresentar o conteúdo existente na área de transferência. Search – esta opção possibilita executar operações de busca, troca e deslocamento dentro de um programa. o Find – localizar uma seqüência de caracteres em um programa. o Replace – substituir uma seqüência de caracteres por outra. o Search again – repetir a última busca. o Go to line number – posicionar-se em uma determinada linha do programa. o Show last compiler error – mostrar o último erro de compilação, quando ocorrer. o Find error – posicionar-se na última posição de erro encontrada pelo compilador. o Find procedure – localizar uma sub-rotina dentro do programa no momento de depuração de um programa. Run – esta opção possibilita colocar em execução o programa da janela ativa. 10 ENG06842 – Programação I o Run – compilar e executar o programa. o Step over – rodar o programa passo a passo com exceção das sub-rotinas existentes. o Trace into – rodar o programa passo a passo inclusive as suas sub-rotinas. o Go to cursor – rodar o programa até a posição em que está o cursor. o Program reset – interromper a execução de um programa durante sua depuração. o Parameters – efetuar a passagem de parâmetros. Compile – esta opção possibilita compilar o programa. o Compile – compilar o programa da janela ativa. o Make – recompilar apenas os programas alterados. o Build – recompilar todos os programas. o Destination – determinar se o programa será compilado somente em memória ou disco. o Primary file – determinar numa lista de arquivos qual será o arquivo principal que será carregado primeiro no processo de compilação. o Clear primary file – limpar o arquivo anteriormente configurado como o arquivo primário. o Information – obter informações a respeito da última compilação executada. 11 ENG06842 – Programação I Debug – esta opção possibilita depurar o programa para facilitar a localização de erros lógicos. o Breakpoint – colocar ou retirar um ponto de parada (exame) na depuração de um programa. o Call stack – apresentar uma janela com a seqüência de chamadas efetuadas de sub-rotinas. o Register – visualizar a janela de registradores da CPU. o Watch – abrir a janela de acompanhamento de valores nas variáveis do programa. o Output – abrir uma janela para apresentar as telas de saída do programa em execução ou depuração. o User Screen – exibir na sua totalidade a tela do usuário. o Evaluate/modify – permite efetuar a avaliação de expressões, constantes ou variáveis. o Add watch – possibilidade de incluir expressões na tela de vigia. o Add breakpoint – permite a inclusão de um ponto de parada quando for executado o programa. Tools – esta opção possibilita a utilização de ferramentas configuradas pelo usuário. o Messagens – abrir uma janela para a apresentação de mensagens. o Go to next – visualizar a próxima mensagem da janela de mensagens. 12 ENG06842 – Programação I o Go to previous – visualizar a mensagem anterior da janela de mensagens. o Grep – efetuar a busca de seqüências de caracteres em programas gravados através do utilitário GREP.EXE. Options – esta opção permite configurar a forma de trabalho do ambiente do Turbo Pascal. o Compiler – alterar o estado das diretivas de compilação. o Memory sizes – definir o tamanho de memória. o Linker – a possibilidade de usar ou não o recurso de link. o Debugger – estabelecer critérios de depuração. o Directories – determinar os diretórios de trabalho. o Browser – especifica configurações globais do visualizador.o Tools – efetuar a manutenção do menu de ferramentas. o Environment – efetuar mudanças no ambiente de trabalho (Preferências, Editor, Mouse, Inicialização e Cores) do Turbo Pascal conforme necessidade do usuário. o Open – a abertura do arquivo de configuração. o Save – gravar o arquivo de configuração. o Save as – gravar o arquivo de configuração com outro nome. Window – esta opção possibilita o controle das janelas que estejam abertas. o Tile – ordenar as janelas lado a lado. o Cascade – ordenar as janelas em cascata. 13 ENG06842 – Programação I o Close all – fechar todas as janelas. o Refresh display – redesenhar a janela ativa. o Size/Move – movimentar ou alterar o tamanho de uma janela. o Zoom – alterar o tamanho de uma janela para o tamanho máximo ou para o tamanho preestabelecido. o Next – selecionar a próxima janela como ativa. o Previous – selecionar a janela anterior como ativa. o Close – fechar a janela ativa. o List – apresentar a listagem das janelas que estejam abertas. Help – esta opção permite executar o modo de ajuda do Turbo Pascal. O modo de ajuda poderá ser executado de qualquer parte do programa com a tecla de função F1 ou Ctrl+F1 para visualizar explicações de instruções que estejam marcadas com o posicionamento do cursor sobre elas. o Contents – apresenta o sumário. o Index – apresenta todas as instruções em ordem alfabética. o Error messages – apresenta uma lista de erros de execução e de compilação. o About – informações sobre o Turbo Pascal 7.0. 7.4. Exercícios 1. Defina, com suas palavras, os seguintes termos: a) programa b) linguagem de programação 14 ENG06842 – Programação I c) tradutor 2. Qual a diferença entre linguagem de baixo nível e linguagem de alto nível? 3. Qual a diferença entre código-fonte e código-objeto? 4. Explique a diferença entre compilador e interpretador. 5. Diferencie com suas palavras os três tipos de erros encontrados em programas. 15 ENG06842 – Programação I 8. A Linguagem Pascal 8.1. Introdução A linguagem de programação PASCAL foi criada para ser uma ferramenta educacional, isto no início da década de 70 pelo Prof. Niklaus Wirth da Universidade de Zurique. Foi batizada pelo seu idealizador em homenagem ao grande matemático Blaise Pascal, inventor de uma das primeiras máquinas lógicas conhecidas. Foi baseada em algumas linguagens estruturadas existentes na época, ALGOL e PLI. O próprio Niklaus Wirth diz que esta linguagem foi criada simultaneamente para ensinar programação estruturada e para ser utilizada em sua fábrica de software. A linguagem é extremamente bem estruturada e muito adequada para ensino de linguagens de programação. É provavelmente uma das linguagens mais bem resolvidas entre as linguagens estruturadas, e certamente um dos exemplos de como uma linguagem especificada por uma pessoa pode ser bem melhor do que uma linguagem especificada por um comitê. Apesar de seu propósito inicial, o PASCAL começou a ser utilizado por programadores de outras linguagens, tornando-se, para surpresa do próprio Niklaus, um produto comercial. Comercialmente, a linguagem foi sucedida pela criação da linguagem Object Pascal, atualmente utilizada nas IDEs Borland Delphi, Kylix e Lazarus. Academicamente, seus sucessores são as linguagens subseqüentes de Niklaus Wirth: Modula-2 e Oberon. 8.2. Tipos de dados simples integer - Envolve os números inteiros. A partir da versão 5.0 do Turbo Pascal passaram a existir também outros tipos de números inteiros: shortint, byte, word e longint. 16 ENG06842 – Programação I Exemplos: -45, 1, 138, 0, -2. Tipo Valor mínimo Valor máximo Bytes ocupados shortint -128 127 1 byte 0 255 1 integer -32768 32767 2 word 0 65535 2 longint -2147483648 2147483647 4 real - abrange os números reais. A partir da versão 5.0 passaram a existir também outros tipos de números reais: single, double, extended e comp. Exemplos: 4.5, -32.0, .5, 7.8E3, 21E+3, -315E-3. Tipo Valor mínimo Valor máximo Bytes ocupados Dígitos significativo s real +-2.9 x 10-39 -+1.7 x 1038 6 11-12 single +-1.5 x 10-45 +-3.4 x 1038 4 7-8 double +-5.0 x 10-324 +-1.7 x 10308 8 15-16 extended +-3.4 x 10- 4932 +-1.1 x 104932 10 19-20 comp -263 + 1 263 - 1 8 19-20 boolean - representa um valor lógico (booleano). Utiliza apenas duas constantes lógicas: true (verdadeiro) e false (falso). char - representa um único caractere, escrito entre apóstrofos ( ‘ ’ ). A maioria dos computadores utiliza a tabela de códigos ASCII (ver Apêndice B – Tabela de códigos ASCII) para representar todos os caracteres disponíveis. Qualquer caractere poderá ser representado pelo seu código ASCII em decimal, precedido por #, ou em hexadecimal, precedidos por # e $. Exemplos: ‘A’, ‘B’, ‘a’, ‘1’, ‘@’, ‘ ’, #65 (é o caractere A). 17 ENG06842 – Programação I string - formado por um conjunto de elementos do tipo char. O tamanho máximo é de 255 caracteres. Também pode apresentar um tamanho pré- definido: string[5], por exemplo (máximo de 5 caracteres). Exemplos: ‘CPU’, ‘Processamento de Dados’, ‘123’. 8.3. Mapeamento Portugol x Pascal A passagem de um código em Portugol para a linguagem Pascal é praticamente direta, como se fosse uma simples tradução de português para inglês. Entretanto, algumas estruturas devem ser cuidadosamente observadas. A seguir são apresentadas as principais regras para realizar o mapeamento de Portugol para Pascal. PORTUGOL PASCAL algoritmo CALCULA_MEDIA; var P1, P2, P3, P4, MEDIA: real; in icio leia (P1); leia (P2); leia (P3); leia (P4); MEDIA (P1 + P2 + P3 + p4) / 4; escreva (MEDIA); se MEDIA ≥ 7,0 então escreva (APROVADO); senão escreva (REPROVADO); fim-se; fim. program CALCULA_MEDIA; var P1, P2, P3, P4, MEDIA: real; begin read (P1); read (P2); read (P3); read (P4); MEDIA := (P1 + P2 + P3 + p4) / 4; write (MEDIA); if MEDIA ≥ 7,0 then write (‘APROVADO’) else write (‘REPROVADO’); end. No exemplo acima, nota-se claramente que é feita um tradução português-inglês do algoritmo. Entretanto, deve-se observar as equivalências definidas na tabela abaixo: PORTUGOL PASCAL algoritmo program inicio begin fim end leia read escreva write 18 ENG06842 – Programação I := se if então then senão else caso case enquanto ... faça while ... do repita ... até repeat ... until para ... até ... faça for ... to ... do Como pode ser observado no exemplo anterior, a palavra fim-se não é usada em Pascal, pois deve-se entender que apenas uma instrução será executada após o if e o else. Caso seja necessária a execução de mais de uma instrução dentro do if, por exemplo, deve-se definir um “bloco” (conjunto de comandos delimitados pelas palavras begin e end) através dos comandos begin e end. Exemplos: if condição1 then begin comando 1; if condição2 then comando 2; end else comando 3; Obs.: O comando anterior ao “else” nunca terminará com “;”. No caso acima o “end” anterior ao “else” não termina com “;”. Exemplos: if condição then comando 1 else comando 2; if condição then begin comando 1; comando 2; ... end else begin comando 3; comando 4; ... end; 19 ENG06842 – Programação I Resumindo então, utiliza-se a definição de blocos apenas nos casos onde mais de uma instrução deverá ser executada. Esse conceito de blocos também é usado nas estruturas de repetição. Os comandos read e write podem ser substituídos pelos comandos readln e writeln, respectivamente.Esses novos comandos saltam uma linha após sua execução. Ex: writeln(‘teste’); Esse comando escreve teste e pula para a linha abaixo na tela. No comando write, pode-se definir o formato de saída das variáveis numéricas (casas decimais, com arredondamento), pois no seu modo padrão, os valores aparecerão em notação científica. Ex: Seja a variável a = 2.36780984. write(a); { Será mostrado o valor: 2.3678098400E+00 } write(a:3:2); { Será mostrado o valor: 2.37 } No caso do comando for (para), o contador é atualizado, por padrão, de 1 em 1. Entretanto, esse comando pode ser usado com TO, onde a variável de controle assume valores crescentes e com DOWNTO, onde a variável assume valores decrescentes. Exemplos: for identificador := valor1 to/downto valor2 do { escolher entre to e downto } comando ; { ou bloco de comandos, usando begin e end } Exemplo: fatorial de N (inteiro maior que 1). … readln(N); fat := 1; for I := N downto 1 do fat := fat * I; writeln(‘O fatorial de ’, N:5, ‘ é ’, fat:5); ... 20 ENG06842 – Programação I 8.4. Unidades pré-definidas O Turbo Pascal possui diversas unidades predefinidas: system, printer, crt, dos, overlay e graph são as principais. Os identificadores usados nestas unidades geralmente são formados por palavras compostas em inglês que lembram seu significado. Uma unidade (unit) nada mais é que um conjunto de procedimentos e funções que trabalham sob um mesmo objetivo. É uma coleção de declarações de constantes, tipos, variáveis, funções e procedimentos, compilada separadamente. Algumas destas declarações são de uso interno da unidade, enquanto outras são visíveis, isto é, podem ser usadas por programas ou outras unidades. Por exemplo, a unit graph possui comandos para criação de desenhos, figuras, barras, entre outros; a unit crt possui os procedimentos básicos de entrada e saída de dados e comandos de controle do monitor. Dessa forma, para utilizar uma função criada dentro de uma unidade, deve-se declarar o uso dessa unidade no início do código-fonte (após a definição do nome do programa). Ex: uses crt; A cláusula uses permite que uma unidade faça uso de outras unidades. Para usar uma ou mais unidades, um programa deve conter a cláusula uses antes das declarações de variáveis. A seguir são apresentadas algumas das principais unidades disponíveis no Pascal. system – é a única unidade que não necessita estar na cláusula uses dos programas ou das outras unidades que a utilizarem. Ex.: tipos de constantes e variáveis; comentários; expressões aritméticas, lógicas e literais; funções numéricas predefinidas; funções literais predefinidas; comandos de entrada e saída; comandos de estrutura condicional e de repetição. printer – define um arquivo lst do tipo texto, associado à impressora do computador, permitindo a sua utilização com os comandos write(lst, ...) e writeln (lst, ...). 21 ENG06842 – Programação I crt – oferece diversos recursos para utilizar o vídeo no modo texto, o teclado e o som do computador. Essa unidade é usada em praticamente todos os programas escritos em Pascal. dos – contém constantes, tipos, variáveis, funções e procedimentos relacionados com o sistema operacional. Ex.: obter data e hora; espaço no disco rígido; espaço livre no disco rígido, etc. graph – permite utilizar o vídeo em modo gráfico, define um grande número de constantes, tipos, variáveis, funções e procedimentos. 8.5. Palavras reservadas São palavras que fazem parte da estrutura da linguagem e têm significados pré-determinados. Elas não podem ser redefinidas e não podem ser utilizadas como identificadores. A tabela a seguir apresenta as palavras reservada da linguagem Pascal. absolute end inline procedure type and external interface program unit array file interrupt record until begin for label repeat uses case forward mod set var const function nil shl while div goto not shr with do if of string xor downto implementati on or then else in packed to 8.6. Funções pré-definidas A seguir, são apresentadas algumas funções matemáticas pré-definidas na linguagem Pascal. Função Finalidade Tipo do argumento Tipo do resultado abs(X) valor absoluto integer, real o mesmo do argumento frac(X) parte fracionária real real trunc(X) parte inteira real integer round(X) valor arredondado real integer 22 ENG06842 – Programação I sqr(X) eleva ao quadrado integer, real o mesmo do argumento sqrt(X) raiz quadrada integer, real real ln(X) logaritmo natural real real exp(X) exponencial real real Como não existe em Pascal um operador nem uma função específica para a operação de potenciação, pode-se consegui-la utilizando as funções ln(X) e exp(X). Para calcular o valor de XN é suficiente usar: exp(ln(X)*N) Exemplos: Expressão Resultado abs(-2.5) 2.5 abs(8) 8 frac(5.234) 0.234 trunc(2.78) 2 round(2.78) 3 sqr(2) 4 sqr(1.5) 2.25 sqrt(4) 2 sqrt(2.25) 1.5 exp(ln(2)*3) 8 A seguir, são apresentadas outras funções interessantes disponíveis na linguagem Pascal. val(atr,num,code): a função val tentará converter a string informada na variável atr em um valor numérico (que será armazenado na variável num), seja real ou integer. Caso não seja possível, a variável inteira code retornará a posição de erro encontrada. Exemplo: val(str_idade,val_idade,code); { se str_idade tiver “12a”, code terá 3, ou seja, erro } val(str_idade,val_idade,code); { se str_idade tiver “12”, code terá 0, ou seja, sem erros } str(num,str): a função str converterá o valor numérico informado em uma string. Exemplo: str(val_idade,str_idade); 23 ENG06842 – Programação I keypressed: a função keypressed retornará true caso haja alguma informação no buffer do teclado, ou seja, caso alguma tecla seja pressionada. Caso contrário retornará false. Exemplo: repeat until keypressed; {dará uma pausa no programa até que se pressione alguma tecla} readkey: a função readkey pára a execução do programa até que alguma tecla seja pressionada. É muito utilizada como última instrução de um programa, pois assim o usuário pode ler o que está escrito na tela com calma, e quando terminar, pressiona uma tecla e o programa é encerrado. Exemplo: readkey; odd(num): a função odd retornará true se o valor informado for ímpar (inteiro). Caso contrário retornará false. Exemplo: if odd(num) then write(‘é ímpar’); inc(num,val): a função inc irá incrementar o número informado em 1 (um), caso o segundo parâmetro não seja informado. Se o mesmo for informado, o incremento será de seu valor. Exemplos: inc(x); {o mesmo que x := x+1;} inc(y,5); {o mesmo que y:=y+5;} dec(num,val): a função dec irá decrementar o número informado em 1 (um), caso o segundo parâmetro não seja informado. Se o mesmo for informado, o decremento será de seu valor. Exemplos: dec(x); {o mesmo que x:=x-1;} dec(y,5); {o mesmo que y:=y-5;} ord(car): a função ord retornará o código ASCII (em decimal) da variável car (do tipo char). Exemplo: write(ord(‘a’),ord(‘A’)); {mostrará 97 65, os respectivos códigos ASCII} 24 ENG06842 – Programação I upcase(char): a função upcase retornará o caractere informado em formato maiúsculo. Caso o caractere informado não seja alfabético, o mesmo será retornado como foi informado. Exemplo: write(upcase(‘a’)); {mostrará A} Obs.: para converter um caractere em maiúsculo basta diminuir 32 de seu código ASCII. Exemplo: … write(letra); {‘a’} dec(letra,32); write(letra); {‘A’} … chr(code): a função chr retornará o caractere correspondente ao código ASCII informado.Exemplo: write(chr(97)); {mostrará ‘a’} insert(str,str_destino,pos_inicio): a função insert irá inserir a string str na string str_destino a partir da posição pos_inicio. Somente a variável str_destino será alterada. Exemplo: msg := ‘O Brasil foi penta!’; adic := ‘não’#32; insert(adic,msg,10); write(msg); {‘O Brasil não foi penta!’} delete(str,pos_inicio,quant): a função delete irá eliminar uma string interna a outra string. O primeiro parâmetro é a string, o segundo é a posição inicial, e o terceiro e último a quantidade de caracteres a remover. Somente o primeiro parâmetro será alterado. Exemplo: msg := ‘O Brasil não foi penta!’; delete(msg,10,4); write(msg); {‘O Brasil foi penta!’} concat(str1,str2,...,strN): a função concat retornará a concatenação (união) de todas as strings informadas como parâmetros. O resultado da 25 ENG06842 – Programação I concatenação não pode ultrapassar os 255 caracteres permitidos. Utilize o operador “+” ao invés de concat, pois “+” é mais veloz. Exemplo: msg1:= ‘Linguagem’; msg2:=#32; msg3:= ‘Pascal’; write(concat(msg1,msg2,msg3)); {‘Linguagem Pascal’} É mais rápido usar: write(msg1 + msg2 + msg3); copy(str,pos_inicio,quant): a função copy retornará uma substring a partir de uma string original. A string original é o primeiro parâmetro, a posição inicial de cópia é o segundo e a quantidade de caracteres a serem copiados é o terceiro. Exemplo: msg := ‘A Linguagem Pascal’; write(copy(msg,13,6)); {Pascal} length(str): a função length retornará o comprimento da string, ou seja, seu número de caracteres. Exemplo: msg := ‘A Linguagem Pascal’; write(length(msg)); {18} clrscr: a função clrscr limpará toda a tela; Exemplo: clrscr; textbackground(c): altera a cor de fundo da tela. O parâmetro c pode variar de 0 a 7, e também pode-se usar o nome da cor em inglês. Para alterar a cor de toda a tela deve-se usar o comando clrscr em seguida. Exemplo: textbackground(1); clrscr; { toda a tela ficará azul } textcolor(c): altera a cor do texto. O parâmetro c pode variar de 0 a 15, e também pode-se usar o nome da cor em inglês.. Exemplo: textcolor(10); 26 ENG06842 – Programação I clreol: a função clreol limpará parte da tela, apenas da posição do cursor até o final da mesma linha. Exemplo: clreol; delline: a função delline limpará toda a linha onde estiver o cursor, sem movê-lo. Exemplo: delline; insline: a função insline irá inserir uma linha onde estiver o cursor, sem movê-lo. Todos os dados que estiverem abaixo da posição do cursor serão deslocados para baixo. Caso se queira inserir mais de uma linha, basta colocar essa função dentro de um laço (loop). Exemplo: for x := 1 to 10 do insline; {irá inserir10 linhas a partir da posição do cursor} sound(freq): a função sound irá ativar o auto-falante do micro, bastando apenas informar no parâmetro a freqüência do som desejado. Normalmente utiliza-se esse procedimento com os procedimentos delay e nosound, já que sound sozinho irá ativar o som e o mesmo ficará tocando o tempo todo. Exemplo: sound(200); nosound: a função nosound irá desligar o som do auto-falante do micro. Exemplo: nosound; delay(ms): O procedimento delay irá dar uma pausa na execução do programa, só que diferentemente dos procedimentos já citados, essa pausa se dará por um tempo informado no parâmetro em milisegundos (10-3s). Exemplo: sound(240); delay(1000); {equivale a 1s} nosound; random(num): a função random retornará um valor randômico (aleatório) a partir do número informado. Esse número randômico será um número qualquer na faixa de 0 <= a < num. Caso não seja informado um número, o valor randômico estará na faixa 0 <= a < 1. Normalmente esta função é utilizada com o procedimento randomize. Exemplo: 27 ENG06842 – Programação I random(300); {através de fórmulas internas, será gerado um número entre 0 e 300} randomize: a função randomize irá fazer apenas um pequeno diferencial no uso da função random. Toda vez que se utiliza random, o valor inicial das fórmulas é o mesmo. Portanto, os valores randômicos sempre serão os mesmos. Para que isto não aconteça, basta utilizar o procedimento randomize, o mesmo irá fazer com que o valor inicial das fórmulas de randomização seja baseado na hora do sistema, o que sabemos que muda constantemente. Exemplo: randomize; repeat write(random(500)); delay(50); until keypressed; exit: a função exit irá fazer com que a execução do programa saia do procedimento atual e vá para o seu chamador. Caso o procedimento atual seja o programa principal, exit terminará a execução do programa. Exemplo: if tecla = #27 then exit; { Pressionou ESC, fim } Exemplo: Um programa para ler um número e mostrar se é igual a zero, positivo ou negativo. O fundo de tela deve estar em azul e as letras em amarelo. program teste; uses crt; var num: real; begin textbackground (blue); clrscr; 28 ENG06842 – Programação I textcolor (yellow); write (‘Digite um numero: ’); readln (num); if num = 0 then writeln (‘Igual a zero.’) else if num > 0 then writeln (‘Numero positivo.’) else writeln (‘Numero negativo.’); readkey; end. 8.7. Tipos definidos pelo usuário Os tipos byte, integer, real, boolean, char, etc são pré-definidos em Pascal e constituem conjunto de valores inteiros, reais, lógicos, caractere, etc. O Pascal permite a criação de novos tipos. Um novo tipo é criado através de uma definição que determina um conjunto de valores associados a um identificador. Uma vez definido, o tipo passa a ser referenciado pelo seu identificador. O novo tipo criado pelo usuário também é denominado tipo enumerado. Os identificadores que criamos para um tipo enumerado não representam mais nenhum valor, exceto seus próprios. Os tipos enumerados constituem ferramentas extremamente úteis na criação de programas limpos e auto-documentados, podendo ser referenciados em qualquer parte do programa. Um tipo enumerado é uma seqüência ordenada de identificadores definidos pelo usuário, que forma um tipo ordinal. A palavra reservada para criação de tipos enumerados é type. Exemplo: type semana = (segunda, terça, quarta, quinta, sexta, sábado, domingo); 29 ENG06842 – Programação I Uma das mais importantes características de um tipo enumerado é a ordem na qual os valores são ordenados. Além de estabelecer os próprios identificadores, a declaração do mesmo define a ordem dos identificadores no tipo. Diversas operações são válidas usando os tipos enumerados. Exemplo: program cores; uses crt; type cores = (preto, azul, vermelho, amarelo, verde, rosa, branco, roxo, lilas); var uma_cor: cores; begin clrscr; uma_cor := roxo; {atribuir um identificador a variável de tipo} uma_cor := succ(uma_cor); {receber lilás, o sucessor} uma_cor := pred(uma_cor); {receber roxo novamente, o antecessor} uma_cor := succ(azul); {receber vermelho, sucessor de azul} if succ(uma_cor)>=lilas then uma_cor := preto; writeln(ord(uma_cor)); {escrever 2, a ordem do vermelho} uma_cor := preto; writeln(ord(uma_cor)); {escrever 0, a ordem do preto} for uma_cor := preto to rosa do writeln(ord(uma_cor)); {escrever as posições, do preto ao rosa} end. As variáveis de tipos enumerados não podem ser lidas ou escritas. Não é válida nenhuma operação aritmética com os elementos de um tipo enumerado, como somar 1, diminuir 2 ou somar duas constantes ou mais constantes do tipo. 30 ENG06842 – Programação I Pode-se usar as constantes dos tipos enumerados para servir de índice de vetores/matrizes e também no laço (loop) for. A ordem do primeiro elemento do tipo tem valor0. Um tipo pode ser definido como uma parte de um dado tipo escalar. Esta parte ou faixa define o domínio de um tipo escalar que está associado a um novo tipo, que é chamado de tipo escalar. A definição de uma faixa (subrange) indica quais os valores mínimo e máximo que podem ser assumidos. A descrição de uma faixa se faz com a indicação dos seus limites separados por dois pontos (..), onde o limite inferior deve ser menor que o limite superior. Exemplo: program dias; uses crt; type semana = (seg, ter, qua, qui, sex, sab, dom); {tipo enumerado} coluna = 1..80; {tipo escalar associado: byte} maius = ‘A’..’Z’; {tipo escalar associado: char} d_util = seg..sex; {tipo escalar associado: semana} num = -128..130; {tipo escalar associado: integer} var letra: maius; dia: d_util; begin clrscr; for letra := ‘J’ to ‘P’ do write(letra:2); for dia := seg to sex do case dia of seg: writeln(‘Segunda’); ter: writeln(‘Terça’); qua: writeln(‘Quarta’); qui: writeln(‘Quinta’); other writeln(‘Sexta’); end; readkey; end. 8.8. Exercícios 1. Transforme os algoritmos elaborados nas questões 24 e 25 do Capítulo 4 para a linguagem Pascal. Execute esses algoritmos no computador. 31 ENG06842 – Programação I 2. Transforme os algoritmos elaborados nas questões 1, 2, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 24, 25, 26, 27, 28, 29, 30 e 31 do Capítulo 5 para a linguagem Pascal. Execute esses algoritmos no computador. 3. Transforme os algoritmos apresentados ou elaborados nas questões 1, 2 e 3 do Capítulo 6 para a linguagem Pascal. Execute esses algoritmos no computador. 32 ENG06842 – Programação I 9. Estruturas de dados 9.1. Introdução Os tipos estruturados são compostos por múltiplos elementos relacionados entre si. Cada grupo de elementos está relacionado a um identificador. Os elementos do grupo podem estar também relacionados a identificadores individuais, representando vários locais de memória que guardam vários valores, e que podem ser acessados em conjunto ou individualmente. 9.2. Variáveis compostas homogêneas Correspondem a posições de memória, identificadas por um mesmo nome, individualizadas por índices e cujo conteúdo é de mesmo tipo. O conjunto de 10 notas dos alunos de uma disciplina pode constituir uma variável composta. A este conjunto, associa-se o identificador NOTA, que passará a identificar não uma única posição de memória, mas 10. A referência ao conteúdo do n-ésimo elemento do conjunto será indicada pela notação NOTA[n] onde n é um número inteiro ou uma variável numérica contendo um valor inteiro. Exemplo: Supondo que a variável composta NOTA contivesse os seguintes valores: 6 0 7 0 9 0 6 0 5 5 9 1 10 0 4 7 7 4 8 6 1 2 3 4 5 6 7 8 9 10 NOTA[3] estaria referenciando o terceiro elemento do conjunto cujo conteúdo é 90. Vetores (array): definem conjuntos de dados homogêneos (todos os elementos são do mesmo tipo). Cada elemento ocupa uma posição definida no conjunto e pode ser referenciado através dela. Esses conjuntos 33 ENG06842 – Programação I necessitam de apenas um índice para endereçar seus elementos. São conhecidos como Variáveis Compostas Unidimensionais. Declaração de vetores: <identificador>: array [tipo_índice] of tipo_elemento; tipo_índice: é um tipo simples ordenado (inteiro, caractere, booleano, enumerado). É formado por: [li..ls] , onde li: limite inferior e ls: limite superior. Este tipo pode ser utilizado tanto na declaração de variáveis como também na definição de novos tipos. Ex1: var lista: array [1..100] of real; { o identificador do vetor é lista e ele poderá conter 100 elementos do tipo real } Ex2: type indice = 1..100; { tipo definido pelo usuário - tipo subrange } var lista: array [indice] of real; Ex3: type max = 300; vetor = array[1..max] of string[20]; var endereco: vetor; { a variável endereço está associada ao tipo vetor } Ex4: var dados: array[‘A’..’Z’] of integer; Definição de Vetores como constantes: sintaxe geral: 34 ENG06842 – Programação I <identificador_constante>: tipo_array = (lista de valores); Ex1: const vetconst: array [1..3] of integer = (0, 1, 2); Ex2: type vetsemana = array [1..7] of string [3]; const dias_semana: vetsemana = (‘DOM’, ‘SEG’, ‘TER’, ‘QUA’, ‘QUI’, ‘SEX’, ‘SAB’); Obs: Os valores das constantes array de tipo char podem ser especificados ou como valores de caracteres simples ou como um string. Ex: const digito: array [0..9] of char = (‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’); ou const digito: array [0..9] of char = ‘0123456789’; A manipulação de vetores nos programas Pascal pode ser expressa com uma constante, variável ou expressão, devendo ser do tipo correto (correspondente à definição do array) e estar dentro do intervalo pré- definido. Ex: lista[5] lista[i], onde i é uma variável inteira com valores variando de 1 a 100. lista[i+j], onde i e j são variáveis inteiras cuja soma não ultrapassa 100. Os elementos do ARRAY podem ser usados em expressões, instruções de atribuição, instruções read e write, etc. Exemplo: program exVetor; type vetorNotas = array [1..40] of real; 35 ENG06842 – Programação I var nota: vetorNotas; i: integer; begin i := 1; media := 0; repeat begin write (‘Digite a nota :’); read(nota[i]); media:= media + nota[i]; i:= succ(i); { função que incrementa a variável ⇒ i := i + 1 } end; until i > 40; writeln (‘Notas dos alunos ’); for i:= 1 to 40 do writeln (nota[i]); writeln (‘Media da turma:’, media/40:5:2); end. Matrizes (vetores multidimensionais): também definem conjuntos de dados homogêneos (todos os elementos são do mesmo tipo), entretanto, esses conjuntos necessitam de mais de um índice para endereçar seus elementos. São conhecidos como Variáveis Compostas Multidimensionais (matrizes). Exemplo de matriz bidimensional: 1 2 3 1 1 0 4 7 9 4 2 6 7 9 8 7 4 3 1 6 2 1 3 2 Declaração de matrizes: 36 ENG06842 – Programação I <identificador>: array [dim1,dim2,...] of tipo_elemento; As dimensões são definidas como: dim1 = li1..ls1, dim2 = li2..ls2, etc. Exemplo de declaração de uma matriz TRIDIMENSIONAL: mat3D: array [1..10, 1..20, 1..40] of real; A 1ª dimensão tem 10 elementos, a 2ª tem 20 elementos e a 3ª tem 40 elementos. Todos os elementos são números reais. Matriz BIDIMENSIONAL: mat2D: array [1..5,1..9] of char; É uma matriz bidimensional com 5 elementos do tipo char na 1ª dimensão e 9 na 2ª dimensão. A manipulação de matrizes nos programas em Pascal pode ser expressa com constantes, variáveis ou expressões, devendo ser do tipo correto (correspondente à definição do array) e estar dentro do intervalo pré- definido. Exemplo: mat3D[5,4,8], mat2D[i,9], onde i é uma variável inteira com valores variando de 1 a 5. Os elementos da matriz podem ser usados em expressões, instruções de atribuição, instruções read e write, etc. Exemplo: program Matrizes; var matriz: array [1..20, 1..10] of integer; lin, col: integer; begin for lin := 1 to 20 do for col := 1 to 10 do read (matriz[lin,col]); ... 37 ENG06842 – Programação I Uma matriz também pode ser definida como uma constante, e nesse caso, essa matriz deve ser definida da seguinte forma: type apart = array[1..5,1..2] of string[3]; const num: apart = ((‘101’,’102’), (‘103’,’104’), (‘105’,’106’), (‘107’,’108’), (‘109’,’110’)); { 1ª linha 2ª linha 3ª linha 4ª linha 5ª linha } ... write(num[3,2]); {106} write(num[1,1]);{101} Exemplo: program matriz; uses crt; const alunos: array[1..3,101..103] of string[10] = ((‘Cenira’,’Joana’,’Marcia’), {primeira linha} (‘Lourdes’,’Nágyla’,’Luciana’), {segunda linha} (‘Patrícia’,’Marcos’,’Angélica’)); {terceira linha} var i,j: integer; begin clrscr; for i:=1 to 3 do for j:=101 to 103 do writeln(‘Aluno(a)’,I,’ da turma ‘,j,’: ‘,alunos[i,,j]); {listará por linha} writeln; 38 ENG06842 – Programação I for j:=101 to 103 do for i:=1 to 3 do writeln(‘Aluno(a)’,I,’ da turma ‘,j,’: ‘,alunos[i,,j]); {listará por coluna} readkey; end. Cuidados ao utilizar arrays: Caso o seu limite seja ultrapassado, o programa pode travar e junto com ele o sistema. O Pascal só acusará erro se você tentar atribuir a um vetor um dado qualquer com índice fora da faixa escrita no programa. Mas isso não acontecerá se a origem do índice for alguma expressão. Os tipos array em Pascal são estáticos, ou seja, o comprimento e as dimensões alocadas são fixas em tempo de compilação e não podem ser redefinidas durante a execução do programa. 9.3. Variáveis compostas heterogêneas O principal tipo de variáveis compostas heterogêneas é o registro, que consiste em conjuntos de dados logicamente relacionados, mas de tipos diferentes (numéricos, lógicos, literais, etc). Pode-se definir registros em Pascal na sessão type ou diretamente declarar variáveis do tipo record. a) Declaração na sessão TYPE: type <nome_novo_tipo> = record campo 1: tipo 1; campo 2: tipo 2; … campo n: tipo n; end; 39 ENG06842 – Programação I var <identificador_variavel>: <nome_novo_tipo>; Exemplo: type { Atencao para a indentacao dos campos do registro} funcionario = record nome: string[40]; idade: integer; funcao: string[30]; salario: real; end; var funcionarioUFES: funcionario; b) Declaração na sessão VAR: var <identificador_registro>: record campo 1: tipo 1; campo 2: tipo 2; … campo n: tipo n; end; Ex emplo : var funcionarioUFES: record nome: string[40]; idade: integer; funcao: string[30]; salario: real; end; 40 ENG06842 – Programação I Os campos dos registros podem ser por sua vez de tipos simples ou estruturados (array, registros, etc.). Ex emplo : type estadosBrasil = (AC,AL,AM,AP,BA,CE,DF,ES,GO,MA,MG,MS,MT,PA,PB,PE, PI,PR,RJ,RN,RO,RR,RS,SC,SE,SP,TO); var cliente: record nome: string[50]; endereco: record rua: string [30]; numero: integer; complemento: string [40]; cep: string [10]; cidade: string[20]; estado: estadosBrasil; end; valoresUltimasCompras: array [1..10] of real; end; O acesso aos campos de um registro pode ocorrer de duas formas: a) uso da notação <identifRegistro>.<campo>. Ex: write(‘Digite o nome do funcionario: ’); readln(funcionarioUFES.nome); {acesso ao campo nome } write(‘Digite a funcao do funcionario: ’); readln(funcionarioUFES.funcao); {acesso ao campo funcao } ... b) uso da estrutura with <identif_Registro> do. Ex: with funcionarioUFES do 41 ENG06842 – Programação I begin writeln(‘Dados do funcionario cadastrado’); writeln(‘Nome: ’, nome); writeln(‘Idade: ’, idade); writeln(‘Funcao: ’, funcao); writeln(‘Salario: ’, salario:5:2); end; Exemplo: program exRegistro; var aluno : record { variável aluno do tipo registro } matricula: string[6]; {definição dos campos do registro } nome: string[15]; serie: integer; turma: char; { cada campo tem um nome e um tipo } end; begin write('Numero de matricula: '); readln(aluno.matricula); write('Nome: '); readln(aluno.nome); {acesso ao campo nome do registro aluno} write('Serie: '); readln (aluno.serie); write ('Turma: '); readln (aluno.turma); { comando with indica o registro que será usado - não há necessidade de se colocar begin e end quando se tem apenas um comando na estrutura with } with aluno do write (‘O aluno ’, nome , ‘ estuda na ’, serie, ‘serie!’); 42 ENG06842 – Programação I end. Conjunto de registros: utilizado para armazenar n informações referentes ao mesmo tipo de registro, como, por exemplo, informações de vários funcionários ou vários alunos. Em Pascal, esse tipo de conjunto é definido por um array unidimensional (vetor) de registros. A declaração é dada da seguinte forma: type <tipo_registro> = record campo 1: tipo 1; … campo n: tipo n; end; var <identif_vetor>: array[n..m] of <tipo_registro>; Exemplo: type aluno = record matricula: string[6]; nome: string[15]; serie: integer; end; var vetAlunos: array [1..45] of aluno; A manipulação de conjuntos de registros é dada da seguinte forma: <identif_vetor>[posicao].campo. Ex: for i:= 1 to 45 do begin readln(vetAlunos[i].matricula); readln(vetAlunos [i].nome); readln(vetAlunos [i].serie); 43 ENG06842 – Programação I end; Também pode-se usar a estrutura with. Ex: for i:=1 to 45 do with vetAlunos[i] do begin readln(matricula); readln(nome); readln(serie) end; Exemplo: 44 ENG06842 – Programação I program produtos; uses crt; type produto = record ident: string[3]; descr: string[10]; preco: real; quant: integer; end; var vet_prod: array [1..3] of produto; i: integer; begin clrscr; writeln (‘*** CADASTRO DE PRODUTOS ***’); for i:=1 to 3 do with vet_prod[i] do { vet_prod[i] representa cada elemento do vetor } begin write(‘identificação: ’); readln(ident) ; write(‘descrição: ’); readln(descr) ; write(‘preco: ’); readln(preco) ; write(‘quantidade: ’); readln(quant) end; writeln (‘***** Produtos no Estoque *****’) ; writeln (‘---Identif.----Descricao----Preco----Quantidade---’) ; for i:=1 to 3 do with vet_prod[i] do if quant > 0 then 45 ENG06842 – Programação I write(‘ ’, ident, ‘ ’, descr, ‘ ’, preco:6:2, ‘ ’, quant); end. 9.4. Algoritmos de classificação e busca Algoritmos de classificação : existem diversos métodos para classificar (ou ordenar) uma estrutura de dados. Os mais conhecidos são o “Método da Bolha”, o “Método da Seleção Direta” e o “Método Quick Sort”, porém o mais comum desses é o Método da bolha (Bubble Sort). Exemplo: Método da Bolha para ordenação de um vetor de “nomes de objetos”. program BubbleS; uses crt; const N=5; type letras = string[10]; vet_letras = array[1..N] of letras; var objetos: vet_letras; aux: letras; i, j, cont: integer; begin clrscr; write('>>> Exercicio - Ordenacao de Vetores com metodo da Bolha<<<'); write('Digite ',N,' nomes de objetos para compor o conjunto'); for i:=1 to N do begin write ('Digite o elemento objetos(',i,'): '); readln(objetos[i]); write(' '); end; 46 ENG06842 – Programação I { ***************** Ordenação do Vetor ******************* } for i:= 2 to N do for j:= N downto i do if objetos[j] < objetos[j-1] then begin aux := objetos[j]; objetos[j] := objetos[j-1]; objetos[j-1] := aux end; { ********************* Saida Ordenada ****************** } writeln ('Vetor Ordenado: '); for i:=1 to N do writeln(objetos[i]); end. Algoritmos de busca : também existem diversos métodos para procurar (ou buscar) um valor dentro de uma estrutura de dados. Os mais conhecidos são o “Busca Seqüencial” e o “Busca Binária”, porém o mais comum desses é o Seqüencial. Exemplo: Considere um vetor A com 50 elementos. Verificar se existe um elemento igual a K no vetor. Se existir mostrar a posição em que se encontra, senão imprimir “não encontrei K no vetor”. program Procura_K; uses crt; const max = 10; { Indica onumero maximo de elementos do array num } var i, k: integer; achou: boolean; num: array[1..max] of integer; begin clrscr; writeln('Digite ',max,' numeros inteiros!'); for i:=1 to max do begin write('Digite o elemento (',i,'): '); readln(NUM[i]); 47 ENG06842 – Programação I end; write('Digite o numero que deseja procurar no conjunto: '); readln(k); achou := false; i:=1; while (not achou) and (i<=max) do if num[i]=k then achou := true else i := i+1; if achou then write('Achei o numero ',k,' na posicao (',i,') do vetor !!!') else write('Nao achei o numero ',k,' no vetor !!!'); end. 9.5. Exercícios 1. Elabore um programa que leia dois vetores inteiros de 20 elementos cada, depois some seus elementos, gerando um terceiro vetor. Ao final, mostre o novo vetor gerado. 2. Considere um vetor VET com 30 elementos. Verificar se existe um elemento igual a K no vetor. Se existir mostrar a posição em que se encontra, senão imprimir “não encontrei K no vetor”. 3. Faça um programa para ler um conjunto de 10 inteiros e escreve-los na ordem inversa à ordem de leitura. 4. Faça um programa para ler um conjunto de 10 inteiros e escreve-los na ordem crescente. 5. Elabore um programa que leia um conjunto A com 50 números reais e construa um conjunto B, onde os elementos de ordem (posição) par são os elementos correspondentes de A divididos por 2, e os de ordem (posição) ímpar correspondem aos elementos de A multiplicados por 3. Ao final, mostre os dois conjuntos de números. 6. Fazer um programa Pascal que, ao ser fornecida uma data no formato DD/MM/AA, mostre-a por extenso. Ex: Entrada: 12/06/95; Saída: 12 de junho de 1995. 48 ENG06842 – Programação I 7. Elabore um programa que utilize dois vetores V1 e V2, formados de números reais com 20 posições cada um, e efetue neles as operações indicadas no vetor OP, cujos elementos são caracteres que indicam as quatro operações aritméticas básicas (+, -, *, /) . O resultado obtido das operações devem ser colocados num vetor resultante VR e mostrado ao final do programa. 8. Escreva um programa que leia duas matrizes bidimensionais reais MAT1 e MAT2 de dimensões 3x5 cada, calcule e imprima a matriz soma MSOMA. 9. Calcule e imprima a soma dos elementos situados abaixo da diagonal principal da matriz A (dimensões 10x10), incluindo os elementos da própria diagonal. 10. Escreva um programa que leia duas matrizes reais A e B de dimensões 3x5 e 5x3, respectivamente, calcule e imprima o produto delas. 11. Dada uma matriz A de dimensões 5x4 formada de elementos numéricos reais, calcule e mostre sua matriz transposta T. 12. Dada uma matriz B formada por números inteiros com 10 linhas por 15 colunas, determinar o elemento de maior valor algébrico. Mostre tal elemento e sua posição na matriz (linha e coluna). 13. Faça um programa para ler 2 vetores a e b, de inteiros, e montar o vetor soma = a + b. 14. Faça um programa para multiplicação de matrizes: leia a e b (4x4), crie C = A*B, escreva C. 15. Loteria esportiva. Faça um programa para ler um "gabarito" com os resultados dos jogos da loteria esportiva (coluna 1, coluna2, coluna do meio, 13 jogos), armazenando em um vetor. Depois leia um conjunto indeterminado de jogos e verifique se ganhou o prêmio. Ao final da 49 ENG06842 – Programação I verificação, pergunte se o usuário quer entrar mais jogos. Ao final do programa, informe quantos ganharam o prêmio. 50 ENG06842 – Programação I 10. Modularização 10.1. Introdução Dentre as técnicas de programação estruturada, encontra-se a modularização. Esta técnica consiste em decompor um programa em uma série de subprogramas individuais. A modularização é um método utilizado para facilitar a construção de grandes programas, através de sua divisão em pequenas etapas (dividir para conquistar), que são os módulos ou subprogramas. A primeira delas, por onde começa a execução do trabalho, recebe o nome de programa principal, e as outras são os subprogramas propriamente ditos, que são executados sempre que ocorre uma chamada dos mesmos, o que é feito através da especificação de seus nomes. A modularização permite o reuso de partes do programa num mesmo programa ou mesmo em novos programas, exemplo: imagine um trecho de programa que verifica se uma data é valida ou não. Este módulo pode ser usado várias vezes num mesmo programa que leia várias datas diferentes e pode ser reaproveitado em novos programas que serão escritos. Outras conseqüências positivas do uso de modularização é o aumento de clareza e concisão do programa, pois o comprimento do programa diminui com o uso de módulos. Em Pascal existem dois tipos de módulos de programas: Procedimentos e Funções. Vantagens da utilização de subprogramas: Economia de código: escreve-se menos; Desenvolvimento modularizado: pensa-se no algoritmo por partes; Facilidade de depuração (correção/acompanhamento): é mais fácil corrigir/detectar um erro apenas uma vez do que dez vezes; Facilidade de alteração do código: se é preciso alterar, altera-se apenas uma vez; 51 ENG06842 – Programação I Generalidade de código com o uso de parâmetros: escreve-se algoritmos para situações genéricas. 10.2. Procedimentos Um subprograma do tipo PROCEDIMENTO é, na realidade, um programa com vida própria, mas que, para ser processado, tem que ser solicitado pelo programa principal que o contém, ou por outro subprograma, ou por ele mesmo. Declaração: procedure nome; declaração dos objetos (constantes, variáveis, etc.) locais ao procedimento begin comandos do procedimento; end; Onde: nome é o identificador associado ao procedimento. Exemplo: O programa abaixo calcula a média aritmética entre duas notas, sem o uso de procedimentos. program CALCULA_MEDIA; {sem o uso de procedimentos} var NOTA1,NOTA2,MEDIA : real; begin {lê as notas} write('Digite a primeira nota: '); readln(NOTA1); write('Digite a segunda nota: '); readln(NOTA2); {calcula a media} MEDIA := (NOTA1 + NOTA2) / 2; {escreve o resultado} 52 ENG06842 – Programação I writeln('Media = ',MEDIA,4:1) end. Agora, o mesmo programa, utilizando um procedimento. program CALCULA_MEDIA; {usando procedimento} var NOTA1,NOTA2,MEDIA : real; { declaração do procedimento } procedure LER_NOTAS; begin write('Digite a primeira nota: '); readln(NOTA1); write('Digite a segunda nota: '); readln(NOTA2); end; { programa principal } begin LER_NOTAS; {ativação do procedimento LER_NOTAS} MEDIA := (NOTA1 + NOTA2) / 2; {calcula a media} Writeln('Media = ',MEDIA,4:1) {escreve o resultado} end. 10.3. Funções As funções, embora bastante semelhantes aos procedimentos, têm a característica especial de retornar ao programa que as chamou um valor associado ao nome da função. Esta característica permite uma analogia com o conceito de função da Matemática. Declaração: function nome: tipo; 53 ENG06842 – Programação I declaração dos objetos locais à função begin comandos da função; end; Onde: nome é o identificador associado à função; e tipo é o tipo da função, ou seja, o tipo do valor de retorno. Exemplo: O programa abaixo calcula a média dos elementos de um vetor, sem uso de procedimentos ou funções. program SOMA_VETOR; {sem o uso de procedimentos ou funções} const N = 30; var VETOR: array[1..N] of integer; I,SOMA,MEDIA: integer; begin {lê os valores do vetor} for I:=1 to N do readln(VETOR[I]); {calcula a media} SOMA := 0; for I:=1 to N do SOMA := SOMA + VETOR[I]; MEDIA := SOMA div N; {escreve o resultado} writeln(MEDIA);end. Agora, o mesmo programa, porém utilizando um procedimento para ler os valores do vetor e uma função para efetuar o cálculo da média. program SOMA_VETOR; {usando uma função e um procedimento} 54 ENG06842 – Programação I const N = 30; var VETOR: array[1..N] of integer; { declaração do procedimento } procedure LER_DADOS; var I: integer; begin for I := 1 to N do readln(VETOR[I]); end; { declaração da função } function MEDIA: integer; var I, SOMA: integer; begin SOMA := 0; for I := 1 to N do SOMA := SOMA + VETOR[I]; MEDIA := SOMA div N; end; { programa principal } begin LER_DADOS; {ativa o procedimento LER_DADOS} writeln(MEDIA); {escreve o resultado, chamando a função MEDIA} end. 55 ENG06842 – Programação I 10.4. Escopo de variáveis Observe que, no exemplo anterior, foi declarada uma variável no programa principal e outras nos subprogramas. Pode-se dizer que a variável VETOR, que foi declarada no programa principal é uma variável global aos subprogramas, enquanto que a variável I é dita variável local ao procedimento LER_DADOS e as variáveis I e SOMA são locais à função MEDIA. É importante ressaltar que a variável I do procedimento LER_DADOS é diferente da variável I da função MEDIA, embora possuam o mesmo identificador. O uso de variáveis globais dentro de procedimentos e funções serve para implementar um mecanismo de transmissão de informações de um nível mais externo para um mais interno. As variáveis locais dos procedimentos e funções são criadas e alocadas quando da sua ativação e automaticamente liberadas quando do seu término. A utilização de variáveis globais não constitui, no entanto, uma boa prática de programação. Assim, todos os subprogramas devem apenas utilizar as variáveis locais, conhecidas dentro dos mesmos, e a transmissão de informações para dentro e fora dos subprogramas deve ser feita através dos parâmetros de transmissão, que serão apresentados a seguir. 10.5. Parâmetros Quando se deseja escrever um subprograma que seja o mais genérico possível, deve-se usar a passagem de parâmetros. A passagem de parâmetros formaliza a comunicação entre os módulos. Além disto, permite que um módulo seja utilizado com operandos diferentes, dependendo do que se deseja do mesmo. Dá-se a designação de parâmetro real ou de chamada ao objeto utilizado na unidade chamadora/ativadora, e de parâmetro formal ou de definição ao recebido como parâmetro no subprograma. Dentre os modos de passagem de parâmetros, destaca-se a passagem por valor e a passagem por referência. 56 ENG06842 – Programação I P assagem de parâmetros por valor : as alterações feitas nos parâmetros formais, dentro do subprograma, não se refletem nos parâmetros reais. O valor do parâmetro real é copiado no parâmetro formal, na chamada do subprograma. Assim, quando a passagem é por valor, isto significa que o parâmetro é de entrada. P assagem de parâmetros por referência : toda alteração feita num parâmetro formal corresponde a mesma alteração feita no seu parâmetro real associado. Assim, quando a passagem é por referência, isto significa que o parâmetro é de entrada-saída. Na linguagem Pascal, a declaração dos procedimentos e funções com parâmetros se diferencia da forma já apresentada apenas pela inclusão da lista de parâmetros formais no cabeçalho. Esta deve vir entre parênteses e cada parâmetro deve ter o seu tipo especificado. A forma geral é: procedure nome (lista de parâmetros formais) function nome (lista de parâmetros formais): tipo A lista de parâmetros formais tem a seguinte forma: parâmetro1: tipo; parâmetro2: tipo; ...; parâmetro n: tipo Exemplos da lista de parâmetros: procedure PROC (X, Y, Z: integer; K: real); function FUNC (A, B: real; C: string): integer; Na forma apresentada, a passagem dos parâmetros será por valor. Para se utilizar a passagem por referência, deve-se acrescentar a palavra VAR antes do nome do parâmetro. Exemplo: procedure PROC(A: integer; var B, C: integer); 57 ENG06842 – Programação I Na chamada de procedimentos ou funções utilizando parâmetros, devemos acrescentar após o nome do procedimento ou função uma lista de parâmetros reais (de chamada), os quais devem ser do mesmo tipo e quantidade dos parâmetros formais declarados. O exemplo a seguir demonstra a diferença entre a passagem de parâmetros por referência e a passagem de parâmetros por valor. program EXEMPLO_PASSAGEM_PARAMETROS; var N1, N2 : integer; procedure PROC(X: integer; var Y: integer); begin X := 1; Y := 1; end; begin N1:=0; N2:=0; PROC(N1,N2); writeln(N1); {será exibido o valor 0} writeln(N2); (será exibido o valor 1} end. Exemplo: Escrever um procedimento chamado DOBRA que multiplique um número inteiro (recebido como parâmetro) por 2. Escrever um programa para ler um valor inteiro e, utilizando o procedimento DOBRA, calcular e exibir o dobro do mesmo. program CALCULA_DOBRO; var X: integer; 58 ENG06842 – Programação I procedure DOBRA (var NUM: integer); begin NUM := NUM * 2 end; begin readln(X); DOBRA(X); writeln(X); end. Exemplo: Escrever uma função chamada MAIOR que receba dois números inteiros e retorne o maior deles. Escrever um programa para ler dois números inteiros e, utilizando a função MAIOR, calcular e exibir o maior valor entre os números lidos. program CALCULA_MAIOR; var X, Y, M: integer; function MAIOR (NUM1, NUM2: integer): integer; begin if NUM1 > NUM2 then MAIOR := NUM1 else MAIOR := NUM2; end; begin readln(X,Y); M := MAIOR(X,Y); writeln(M); end. 59 ENG06842 – Programação I Exemplo: Escreva um procedimento que receba uma string S e converta o mesmo para letras maiúsculas. procedure MAIUSC (var S: string); var I, TAM: byte; begin TAM := length(S); for I := 1 to TAM do S[I] := upcase(S[I]); end; 10.6. Recursividade Existem casos em que um procedimento ou função chama a si próprio. Diz-se então que o procedimento ou função é recursivo. Por exemplo, o fatorial de um número n pode ser definido recursivamente, ou seja: = >− = 0 n se1 0 n se1)!(nn !n Dessa forma, pode-se escrever uma função recursiva em Pascal que traduz esta definição matemática: function FAT(n: integer): integer; begin if n = 0 then FAT := 1 else FAT := N * FAT(N-1); end; 10.7.Exercícios 1. Cite as principais vantagens da utilização de subprogramas. 60 ENG06842 – Programação I 2. Conceitue procedimento e função. Em que eles são semelhantes e em que eles são diferentes? 3. Que tipo de informação deve ser incluído na declaração de um procedimento? E na declaração de uma função? Se houver diferenças, explique o motivo. 4. Qual a diferença entre variável global e variável local? 5. Como deve ser feita a transmissão de informações entre um subprograma e o programa principal? 6. Qual a diferença entre parâmetro real e parâmetro formal? 7. Cite os modos de passagem de parâmetros, explicando como funciona cada um deles. 8. Escreva um procedimento que limpe a tela do micro e exiba o seu nome. 9. Escreva um procedimento que receba uma string S e um inteiro positivo N e exiba a string S por N vezes seguidas na tela. 10. Escreva uma função chamada CUBO que receba um valor do tipo real e retorne a potência elevado a 3 do mesmo. 11. Escreva um procedimento chamado TROCA que receba duas variáveis inteiras (X e Y) e troque o conteúdo entre elas; 12. Escreva uma função que receba uma string S e retorne o número de espaços existentes na mesma.13. Escreva uma função que receba uma string S e um valor inteiro N e retorne os N primeiros caracteres da string S. 14. Escreva um procedimento chamado SINAL que receba como parâmetro um valor N inteiro e escreva a palavra POSITIVO se N for um número 61 ENG06842 – Programação I maior que zero, NEGATIVO se N for menor que zero, ou ZERO se N for igual a zero. 15. Escreva um programa que leia um número inteiro e, usando o procedimento SINAL (criado na questão anterior), mostre se ele é maior, menor ou igual a zero. 16. Escreva um procedimento chamado METADE que divida um valor do tipo real (passado como parâmetro) pela metade. 17. Escreva um programa que leia um vetor A de 30 elementos reais e, usando o procedimento METADE (criado na questão anterior), divida todos seus elementos pela metade. 18. Escreva uma função chamada MEDIA que retorne a média aritmética de três valores reais (X, Y e Z) passados como parâmetros. 19. Escreva um programa que, para um número indeterminado de alunos, faça para cada uma deles: ler o nome e as três notas do aluno (a leitura do nome FIM indica o fim dos dados - flag); calcular a média do aluno (usando a função MEDIA criada na questão anterior); exibir o nome e a média do aluno. 20. Quantos números o programa abaixo imprimirá na tela? program pares; var contador: integer; function NumeroPar(numero: integer): Boolean; begin NumeroPar := (numero mod 2) = 0; end; begin for contador := 1 to 100 do if (NumeroPar(contador)) then writeLn(contador); 62 ENG06842 – Programação I end. 21. O que o programa abaixo imprimirá na tela? program Linhas; var contador: Integer; procedure ImprimeLinha(linha: integer); var contador: integer; begin for contador := 1 to linha do write(contador); writeLn; end; begin for contador := 1 to 10 do ImprimeLinha(contador); end. 22. Descreva uma função POTENCIA que realize a operação de potenciação e que contenha os seguintes parâmetros formais: VALOR: número inteiro que se deseja elevar à potência. POT: potência elevada Ex: Na chamada da função POTENCIA(5,3), o resultado seria 125. Na chamada da função POTENCIA(2,0), o resultado seria 1. 23. Escrever uma função DIGITO(N,K) que determine o valor do k-ésimo dígito da direita para a esquerda de um número N inteiro. Ex: DIGITO(379836,3) = 8 DIGITO(567,8) = 0. 24. Escreva uma função chamada SEG para receber uma medida de tempo expressa em Horas, Minutos e Segundos e retornar esta medida convertida apenas para segundos. 25. Escreva um procedimento chamado HMS para receber uma medida de tempo expressa apenas em segundos em retornar esta medida convertida para horas, minutos e segundos. 63 ENG06842 – Programação I 26. Faça um programa que leia duas medidas de tempo (expressas em horas, minutos e segundos) e, usando a função SEG e o procedimento HMS, calcule e exiba a diferença (também em horas, minutos e segundos) entre elas. 27. Escreva uma função chamada NOME_MES que receba um valor inteiro N (de 1 a 12) e retorne uma string contendo o nome do mês correspondente a N. 28. Escrever um procedimento para leitura de um valor inteiro entre 1 e 100. Se o usuário fornecer um valor fora desta faixa, deve-se repetir o processo até que seja fornecido um valor válido. 29. Fazer um programa para ler duas matrizes e apresentar a soma. Utilize subprogramas (procedimentos e/ou funções) para ler, somar e escrever as matrizes. 30. O que o programa abaixo faz? Quantas vezes o procedimento AcertaPosicao será executado? Quantas vezes o procedimento Troca será executado? program Numeros; const LIMITE = 5; var contador: integer; numeros: array[1..LIMITE] of integer; procedure Troca(x, y: integer); var temporario: integer; begin temporario := numeros[x]; numeros[x] := numeros[y]; numeros[y] := temporario; end; procedure AcertaPosicao(posicao: integer); var indice: integer; begin for indice := posicao + 1 to LIMITE do 64 ENG06842 – Programação I if (numeros[indice] < numeros[posicao]) then Troca(posicaoindice); end; procedure LeNumeros; var indice: integer; begin writeln('Digite ', LIMITE, ' numeros: '); for indice := 1 to LIMITE do readln(numeros[indice]); end; procedure MostraNumeros; var indice: integer; begin write('O resultado e: '); for indice := 1 to LIMITE do write(numeros[indice]:6); writeln; end; begin LeNumeros; for contador := 1 to 4 do AcertaPosicao(contador); MostraNumeros; end. 31. Leia 50 valores do tipo (nome, P1, P2, Nota_trabalhos, Percentual_de_presença), e determine quantos alunos foram aprovados e quantos foram reprovados. Para aprovação é preciso ter média maior ou igual a 6 e 75% de presença. A média é calculada pela expressão: Media = (P1 + P2) * 70% + Nota_trabalhos * 30%. Use uma função para calcular a média. Utilize pelo menos um procedimento ou função. 32. Fazer uma função para multiplicar 2 matrizes A (MxN) e B (NxK) e retornar a matriz resultado (MxK). 33. Escreva uma função recursiva FIB(n) que receba o inteiro n e devolva o n-ésimo terma da seqüência de Fibonacci, definida recursivamente por: 65 ENG06842 – Programação I << ≥+ = 3 n 0 se1 3 n se2)-FIB(n1)-FIB(n FIB(n) 66 ENG06842 – Programação I 11. Armazenamento de dados A manipulação de dados apresentada nos capítulos anteriores estavam em memória, ou seja, após a execução dos programas os dados se perdiam. Para resolver esse problema, deve-se começar a trabalhar com discos (HDs, disquetes, etc.), onde os dados poderão ser armazenados e manipulados por um ou vários programas, pois ficarão armazenados em algum local dos discos existentes no computador. Geralmente, o armazenamento de dados é realizado através de um banco de dados ou de um simples arquivo. A utilização de bancos de dados é baseada na utilização de um Sistema Gerenciador de Banco de Dados (SGBD), que oferece recursos para uma adequada e eficiente manipulação dos dados. Entretanto, para utilização de um SGBD, deve-se inicialmente compreender os conceitos para criação e utilização de um banco de dados, e isso leva tempo. Normalmente, os bancos de dados são tratados em uma disciplina única e exclusiva, cuja finalidade é trabalhar diretamente nos seus principais conceitos. Dessa forma, será tratado neste capítulo apenas o armazenamento de dados via arquivos, cuja manipulação é menos eficiente, porém significativamente mais simples. 11.1. Arquivos Um arquivo de dados tem a propriedade de ser independente dos programas. É separado de qualquer programa e pode ser acessado e usado por muitos programas diferentes. Na maioria dos casos, usa-se um único programa para introduzir as informações no arquivo de dados e gravá-lo em disco. A partir deste momento, pode-se ler as informações daquele arquivo de dados usando muitos programas diferentes, cada um executando uma atividade diferente com o arquivo. Suponha que você tenha necessidade de criar um arquivo de dados, para guardar os nomes, endereços e telefones de seus amigos. Inicialmente, você precisará de um programa para introduzir as informações no arquivo 67 ENG06842 – Programação I e adicionar novos dados ao mesmo. Um outro programa poderá ser criado para listar as informações do arquivo. Outro permitirá você selecionar um número de telefone do arquivo usando o nome do amigo como critério de seleção. Você pode criar outro programa para mudar os endereços e os telefones. Outropara imprimir etiquetas contendo as informações do arquivo. As possibilidades continuam... O arquivo de dados é gravado no disco, separadamente dos programas, num lugar específico, e pode ser acessado por muitos programas diferentes. Cada programa descrito acima, copia as informações gravadas no disco para memória do computador e esses dados são manuseados em memória de acordo com as necessidades de cada programa. Alternativamente, o programa poderá transferir as informações da memória do computador para serem gravadas no disco. O Turbo Pascal admite três tipos de arquivos: Arquivo typed (arquivo tipado): pode conter praticamente todos os tipos de dados, menos o tipo FILE. Isto quer dizer que pode-se criar um arquivo para guardar reais, arrays, records, mas não se pode criar um arquivo de arquivo. Cada elemento pertencente ao arquivo tipado pode ser acessado diretamente pelo número, isto é, um registro pode ser acessado imediatamente sem que tenhamos que acessar todos os registros anteriores. Esse tipo de acesso é denominado randômico ou direto. Um arquivo tipado é um arquivo randômico. Arquivo text (arquivo texto): pertence a um tipo predefinido do Pascal denominado text. Os arquivos text são armazenados no disco como linhas de caracteres ASCII e só podem ser acessados de forma seqüencial, isto é, só podem ser lidos ou escritos do início para o fim do arquivo. Um arquivo seqüencial em disco está projetado para ser lido do início ao fim, toda vez que for aberto. Em outras palavras, 68 ENG06842 – Programação I não existe uma forma de pular diretamente de um determinado registro para outro num ponto qualquer do arquivo. Por essa razão, os arquivos seqüenciais são melhor usados em aplicativos que executam tarefas sobre todo um conjunto de dados ao invés de executá-las sobre um determinado registro. Arquivo untyped (sem tipo): pode ser associado a qualquer arquivo de disco, sendo que o tamanho do registro seja de 128 bytes. As operações de entrada e saída usando um arquivo sem tipo transferem dados diretamente de um arquivo em disco para uma variável de memória e vice-versa, sem passar pela memória temporária (buffer), o que, além de economizar espaço na memória, também torna a operação ligeiramente mais rápida. Seu uso é muito limitado. Quando um arquivo é aberto apenas para uma operação de remoção ou troca de nome, é aconselhável usar um arquivo sem tipo. Os procedimentos para manipulação de qualquer arquivo são: Definir uma variável de arquivo e associar a variável ao nome do arquivo no disco. Abrir o arquivo, para leitura ou para escrita ou para ambos. Ler os dados do arquivo ou gravar dados no mesmo. Fechar o arquivo quando o processo terminar. O Pascal usa a palavra reservada text como identificador padrão de arquivos-texto. A sintaxe para definir variáveis desse tipo é: var arq_alunos: text; arq_func: text[512]; 69 ENG06842 – Programação I Os arquivos-texto são definidos inicialmente com memória temporária de 128 bytes. Isto quer dizer que o Pascal trabalha com 128 bytes de informações de cada vez. Esse tamanho de memória temporária é adequado para a maioria das aplicações. Entretanto, no caso de programas que utilizam repetidamente informações guardadas em disquetes, como é o caso de programas de banco de dados, pode ser conveniente aumentar a capacidade de memória temporária. Para estabelecer o tamanho da memória temporária, basta colocar o número de bytes desejado entre colchetes depois da palavra text, na declaração da variável de arquivo (como no exemplo acima). Normalmente, se declara uma variável de memória, do mesmo tipo de dados que vão ser gravados ou lidos no arquivo. É essa variável que guarda em memória os conteúdos dos registros que vão ser lidos do arquivo ou que vão ser gravados no arquivo. Todo o manuseio com os dados é feito em memória. O arquivo de dados é utilizado apenas para gravar ou ler informações. Exemplo: type dados = record nome: string[30]; tel: string[10]; end; var arq_alunos: text; registro: dados; Para utilizar uma variável de arquivo para acessar um arquivo-texto, deve- se associar a variável a um determinado nome de arquivo em disco. Denomina-se esse processo como assinalamento. A função predefinida que executa esta tarefa é assign. Assign associa o nome da variável de 70 ENG06842 – Programação I arquivo a um nome de arquivo em disco. Nunca deve ser usada em arquivos que já estejam em uso. Exemplo: assign(arq_alunos,‘alunos.dat’); A partir desse comando, toda referência a “arq_alunos” no programa será dirigida ao arquivo no disco chamado “alunos.dat”. Caso um programa tenha mais de uma variável de arquivo, teremos que assinalar individualmente cada variável, isto é, teremos tantos assign quanto forem as variáveis de arquivo. Assinalar uma variável a um arquivo é criar um buffer específico para aquela variável. Um buffer é uma parte da memória do computador, com determinada capacidade, que é criada para atuar como intermediário entre o programa e o arquivo de dados no disco. A informação que se encontra no disco, primeiro é copiada para buffer, uma determinada quantidade de bytes de cada vez, estando, portanto, disponível ao programa para manipulação. Do mesmo modo, as informações, para serem gravadas em disco, são primeiramente acumuladas no buffer. Quando o buffer está cheio, as informações são copiadas para o disco. Graças aos buffers, os dados são movimentados corretamente, para os arquivos especificados. O default (padrão) de arquivos que podem ser abertos simultaneamente no Pascal é 16. Exemplo: uses crt; type dados = record nome: string[30]; tel: string[10]; end; var 71 ENG06842 – Programação I arq_alunos: text; registro: dados; begin clrscr; assign(arq_alunos,‘alunso.dat’); Um determinado arquivo-texto pode ser aberto para leitura ou gravação, mas não para ambas operações ao mesmo tempo. O Pascal fornece três funções diferentes para abertura de um arquivo- texto: rewrite(var de arquivo): cria um novo arquivo e o abre para operações de escrita. Após a abertura, pode-se usar os comandos WRITE e WRITELN para escrever os dados e linhas de texto no arquivo. Caso o nome do arquivo já exista no disco, este procedimento destrói o arquivo antigo e cria outro vazio e com o mesmo nome, isto significa que todos os dados do arquivo existente serão perdidos. append(var de arquivo): abre um arquivo-texto já existente, de modo que podemos adicionar novos registros no fim do arquivo. Ocorre um erro de I/O (entrada e saída) se o arquivo não existir no disco. Após a abertura, pode-se usar as funções WRITE e WRITELN para escrever dados no arquivo. reset(var de arquivo): abre um arquivo já existente para leitura. Após a abertura do arquivo, pode-se usar as funções READ e READLN para ler dados e linhas de texto do arquivo. Em contraste com a função REWRITE que cria um arquivo novo destruindo o antigo, caso exista, os comandos APPEND e RESET assumem a existência de um arquivo nomeado no disco. Se o arquivo não puder ser localizado, em ambos os casos, resultarão em erros de I/O em tempo de execução. 72 ENG06842 – Programação I Exemplo: uses crt; type dados = record nome: string; tel: string; end; var registro: dados; arq_reg: text; begin clrscr; assign(arq_reg,‘alunos.dat’); rewrite(arq_reg); write(‘Arquivo ALUNOS.DAT criado’); readkey; close(arq_reg); end.Exemplo: uses crt; type dados = record nome: string; tel: string; end; var registro: dados; arq_reg: text; conf: char; begin clrscr; 73 ENG06842 – Programação I assign(arq_reg,‘alunos.dat’); rewrite(arq_reg); write(‘Arquivo ALUNOS.DAT criado’); readkey; repeat write(‘Entre com um nome: ’); readln(registro.nome); write(‘Seu telefone: ’); readln(registro.tel); write(‘Confirma gravação? <S/N>: ’); conf := upcase(readkey); if conf = ‘S’ then writeln(arq_reg,registro.nome,#32,registro.tel); until conf=‘N’; close(arq_reg); end. Obs.: podem ser usados como caracteres delimitadores de campos: espaço (#32) e tabulação (#9). Para fechar qualquer arquivo aberto, o Pascal dispõe do comando CLOSE, como foi visto nos exemplos anteriores de programas. Se vários arquivos foram abertos simultaneamente, teremos que fechá-los individualmente, usando um comando close para cada um. O comando CLOSE fecha o arquivo externo em disco, mas não termina com o assinalamento feito pelo comando ASSIGN. Isto significa que o programa pode usar um comando REWRITE, RESET ou APPEND após o comando CLOSE se necessário. CLOSE é um comando muito importante, pois é usado para manter a integridade e exatidão dos arquivos de dados. Relembre que o buffer atua como um intermediário entre o programa e o arquivo em disco. Quando se executa uma operação de gravação, os dados são enviados 74 ENG06842 – Programação I primeiramente para o buffer. Quando o buffer está cheio, os dados são gravados em disco. Freqüentemente essa operação é chamada de atualização de arquivos em disco. O que acontece quando o buffer só está parcialmente cheio e não existem mais dados para preenchê-lo. Se você está esperando que o buffer semi- cheio simplesmente transfira seu conteúdo para o disco quando o programa termina a sua execução, você está enganado. Os dados de um buffer semi-cheio não são necessariamente gravados no arquivo. O comando CLOSE força o buffer a transferir o seu conteúdo para o arquivo de disco, mesmo que o buffer não esteja cheio. Exemplo: uses crt; type dados = record nome: string; tel: string; end; var registro: dados; arq_reg: text; conf: char; begin clrscr; assign(arq_reg,‘alunos.dat’); reset(arq_reg); with registro do begin repeat readln(arq_reg,nome,tel); {lendo do arquivo} write(nome,‘ ’,tel); {listando na tela} 75 ENG06842 – Programação I until eof(arq_reg); {repita até que o final do arquivo seja atingido} end; close(arq_reg); readkey; end. Quando o programa está lendo uma seqüência de valores de um arquivo texto, o comando READ reconhece os caracteres delimitadores usados durante o processo de gravação. O arquivo-texto foi projetado para conter só caracteres ASCII. Mesmo assim, os comandos READ e READLN podem ler apropriadamente valores de dados numéricos ou strings. É evidente que durante um processo de leitura, não se pode colocar valor de uma variável string numa variável numérica. Já foi dito que um arquivo-texto é um arquivo seqüencial, por isso é necessário sabermos quando o fim de arquivo foi atingido. A quantidade de linhas gravadas pode ser controlada pelo programador, através de técnicas, porém, o modo mais prático para se descobrir o fim do arquivo é usar a função booleana EOF, como foi aplicado no exemplo acima. A função EOF retorna true se o ponteiro estiver no final do arquivo. Caso contrário, a função retornará false, indicando que o fim do arquivo não foi atingido. 11.2. Exercícios 1. Dado um arquivo existente, com registros com os dados: nome, sexo, endereço e idade. Criar 2 arquivos, um só com os homens e outro só com as mulheres. 2. Criar um arquivo de alunos (nome, nro, p1, p2, media) para armazenar elementos (quantos o usuário quiser). Abrir o arquivo e atualizá-lo com as médias dos alunos. A seguir, liste nome e média de cada aluno. 76 ENG06842 – Programação I 3. Estoque de supermercado. Faça um programa para controlar o estoque de um supermercado. Para cada produto armazene (em arquivo): nome, estoque, preço, e estoque mínimo. Leia os dados para o estoque e guarde em um vetor. Depois percorra o vetor e escreva o nome e as demais informações de todos os produtos que estão com estoque abaixo do estoque mínimo. 4. Folha de pagamentos. Monte um vetor para armazenar o nome, cargo, salário bruto de cada funcionário de uma empresa. Depois execute a folha de pagamentos da seguinte forma: para cada funcionário, imprima nome, salário bruto e salário líquido (para salários menores que 1000 o salário líquido é o próprio salário bruto; para salários maiores ou iguais a 1000 o salário líquido é cerca de 87% do salário bruto). 77 ENG06842 – Programação I Referências [1] COLLINS, W. J. Programação estruturada com estudos de casos em Pascal. McGraw-Hill. (1988) São Paulo. 1988. 712p. [2] FARRER, H. et al. Algoritmos estruturados. Livros Técnicos e Científicos. 3a ed. Rio de Janeiro. 1999. [3] FARRER, H. et al. Pascal estruturado. Livros Técnicos e Científicos. 3a ed. Rio de Janeiro. 1999. 278p. [4] FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação: a construção de algoritmos e estruturas de dados. Pearson Education do Brasil. 2a ed. São Paulo. 2000. [5] GUIMARÃES, A. M.; LAGES, N. A. C. Algoritmos e Estruturas de Dados. Rio de Janeiro, LTC, 1994. [6] MANZANO, J. A. N. G. Algoritmos: lógica para desenvolvimento de programação. Erica. 10a ed. São Paulo. 2000. 78 ENG06842 – Programação I Apêndice A – Mensagens de erro do Turbo Pascal A seguir são apresentados os principais “possíveis” erros de compilação do Turbo Pascal 7.0. ERRO DESCRIÇÃO TRADUÇÃO 1 Out of memory Não existe espaço em memória 2 Identifier expected Identificador esperado 3 Unknown identifier Identificador desconhecido 4 Duplicate identifier Identificador já existente 5 Syntax error Erro de sintaxe 6 Error in real Constant Erro na constante real 7 Error in integer Constant Erro na constante inteira 8 String Constant exceeds line Constante string excede a linha 9 Too many nested files Muitos arquivos aninhados 10 Unexpected end of file Fim de arquivo não esperado 11 Line too long Linha muito longa 12 Type identifier expected Espera a identificação do tipo 13 Too many open files Muitos arquivos abertos simultaneamente 14 Invalid file name Nome de arquivo inválido 15 File not found Arquivo não encontrado 16 Disk full Disco cheio 17 Invalid file name Diretiva de compilação inválida 18 Too many files Excesso de arquivos 19 Undefined type in pointer def Ponteiro nunca antes declarado 20 Variable identifier expected Identificador de variável esperado 21 Error in type Erro de tipo 22 Structure too large Estrutura muito larga 23 Set base type out of range Faixa de valores inválida para a faixa 24 File components may not be files or objects Componentes do arquivo não devem ser arquivos ou objetos 25 Invalid string length Tamanho de string inválido 26 Type mismatch Tipos misturados / incompatível 27 Invalid subrange base type Faixa de valores inválida 28 Lower bound > than upper bound Limite inferior > limite superior 29 Ordinal type expected Tipo escalar esperado 30 Integer Constant expected Constante inteira esperada 31 Constant expected Constante esperada 32 Integer or real Constant expected Constante inteira ou real esperada 33 Pointer type identifier expected Identificador de tipo ponteiro esperado 34 Invalid function result type Tipo de resultado da função inválido 35 Label identifier expected Identificador Label esperado 36 Begin expected Begin esperado 37 End expected End esperado 38 Integer expression expected Expressão inteira esperada39 Ordinal expression expected Expressão ordinal esperada 40 Boolean expression expected Expressão booleana esperada 41 Operand types do not match Operando incompatível com o operador 42 Error in expression Erro na expressão 43 Illegal assignment Associação ilegal 44 Field identifier expected Identificador de campo esperado 45 Object file too large Arquivo objeto muito grande 46 Undefined extern Extern indefinido 47 Invalid object file Record Objeto de registro de arquivo inválido 48 Code segment too large Segmento de código muito grande 49 Data segment too large Segmento de dados muito grande 79 ENG06842 – Programação I 50 Do expected Do esperado 51 Invalid public definition Definição public inválida 52 Invalid extern definition Definição extern inválida 53 Too many extern definitions Excesso de definições extern 54 Of expected Of esperado 55 Interface expected Interface esperada 56 Invalid relocatable reference Referência relocável inválida 57 Then expected Then esperado 58 To or Downto expected To ou Downto esperado 59 Undefined forward Forward indefinido 60 Too many procedures Excesso de procedures 61 Invalid typecast Tipo de resultado inválido 62 Division by zero Divisão por zero 63 Invalid file type Tipo de arquivo inválido 64 Cannot read or write vars of this type Variáveis desse tipo não podem ser lidas / escritas 65 Pointer variable expected Variável do tipo ponteiro esperada 66 String variable expected Variável do tipo String esperada 67 String expression expected Expressão string esperada 68 Circular unit reference Referência circular da unit 69 Unit name mismatch Nome da unit incompatível 70 Unit version mismatch Versão da unit incompatível 71 Duplicate unit name Nome da unit duplicada 72 Unit file format error Erro no formato do arquivo unit 73 Implementation expected Implementation esperado 74 Constant and case types don’t match Constante e expressão do case incompatíveis 75 Record variable expected Variável do tipo Record esperada 76 Constant out of range Constante fora de faixa 77 File variable expected Variável de arquivo esperada 78 Pointer expression expected Expressão tipo ponteiro esperada 79 Integer or real expression expected Expressão inteira ou real esperada 80 Label not within current block Label for a do bloco atual 81 Label already defined Label já foi definido 82 Undefined label in stmt part Label não declarado 83 Invalid @@ argument Argumento @@ inválido 84 Unit expected Unit esperado 85 “;” expected “;” esperado 86 “:” expected “:” esperado 87 “,” expected “,” esperado 88 “(“ expected “(” esperado 89 “)” expected “)” esperado 90 “=” expected “=” esperado 91 “:=” expected “:=” esperado 92 “[“ or “(“ expected “[” or “(” esperado 93 “]” or “)” expected “]” or “)” esperado 94 “.” Expected “.” Esperado 95 “..” expected “..” esperado 96 Too many variables Variáveis demais 97 Invalid for control variable Variável de controle loop for inválida 98 Integer variable expected Variável do tipo integer esperada 99 Files and procedure types are not allowed here Arquivos e procedimentos não permitidos aqui 100 String length mismatch Comprimento da string incompatível A seguir é apresentada uma tabela com uma relação dos principais erros em tempo de execução (run-time errors) do Turbo Pascal 7.0. 80 ENG06842 – Programação I ERRO DESCRIÇÃO TRADUÇÃO 1 Invalid function number Função numérica inválida 2 File not found Arquivo não encontrado 3 Path not found Caminho não encontrado 4 Too many open files Muitos arquivos abertos 5 File Access denied Acesso ao arquivo negado 6 Invalid file handle Arquivo handle inválido 12 Invalid file Access code Código de acesso de arquivo inválido 15 Invalid drive number Número do drive inválido 16 Cannot remove current directory Impossível remover diretório atual 17 Cannot rename across drives Impossível renomear diretório 18 Não há mais arquivos 100 Disk read error Erro de leitura do disco 101 Disk write error Erro de gravação do disco 102 File not assigned Arquivo não assinalado 103 File not open Arquivo não aberto 104 File not open for input Arquivo não está aberto para entrada 105 File not open for output Arquivo não está aberto para saída 106 Invalid numeric format Formato numérico inválido 150 Disk is write-protect Disco protegido 151 Erro interno do dispositivo DOS 152 Drive not ready Drive não pronto para leitura 154 CRC error in data Erro de CRC nos dados 156 Disk seek error Erro de pesquisa no disco 157 Unknown media type Tipo de mídia desconhecida 158 Sector not found Setor não encontrado 159 Printer out of paper Impressora sem papel 160 Device write fault Falha no dispositivo de escrita 161 Device read fault Falha no dispositivo de leitura 162 Hardware failure Falha no hardware 200 Division by zero Divisão por zero 201 Range check error Erro de faixa 202 Stack overflow error Erro de estouro de pilha 203 Heap overflow error Erro de estouro de heap 204 Invalid pointer operation Operação de ponteiro inválida 205 Floating point overflow Estouro de ponto flutuante 207 Invalid floating point operation Operação de ponto flutuante inválida 208 Overlay manager not installed Gerenciador de overlay não instalado 209 Overlay file read error Erro na leitura de arquivo overlay 210 Object not initialized Objeto não inicializado 211 Call to abstract method Chamada a um método abstrato 213 Collection index out of range Índice de coleção fora da faixa 214 Collection overflow error Erro de estouro da coleção 215 Arithmetic overflow error Erro de estouro aritmético 216 General protection fault Falha de proteção geral 81 ENG06842 – Programação I Apêndice B – Tabela de códigos ASCII ASCII (acrônimo para American Standard Code for Information Interchange) é um conjunto de códigos para o computador representar números, letras, pontuação e outros caracteres. É uma padronização da indústria de computadores, onde cada caractere é manipulado na memória, discos, etc. O código ASCII representa uma maneira de codificar caracteres na forma de valores inteiros. Neste código, os caracteres são mapeados para valores numéricos representáveis por 8 bits. Este código abrange 95 caracteres passíveis de impressão e 33 caracteres especiais utilizados, entre outros, no controle de comunicação entre computadores ou um computador e seus periféricos. Os 33 caracteres de controle são os de código 0 a 31 (NUL a US) e o de código 127 (DEL). A tabela abaixo descreve o padrão ASCII. Código Valor Comentário 0 NUL Caracter Nulo 1 SOH Começo de cabeçalho de transmissão 2 STX Começo de texto 3 ETX Fim de texto 4 EOT Fim de transmissão 5 ENQ Interroga 6 ACK Confirmação 7 BEL Sinal sonoro 8 BS Volta um caracter 9 HT Tabulação Horizontal 10 LF Próxima linha 11 VT Tabulação Vertical 12 FF Próxima Página 13 CR Início da Linha 14 SO Shift-out 15 SI Shift-in 16 DLE Data link escape 17 D1 Controle de dispositivo 18 D2 Controle de dispositivo 19 D3 Controle de dispositivo 20 D4 Controle de dispositivo 21 NAK Negativa de Confirmação 22 SYN Synchronous idle 23 ETB Fim de transmissão de bloco 24 CAN Cancela 82 ENG06842 – Programação I 25 EM Fim de meio de transmissão 26 SUB Substitui 27 ESC Escape 28 FS Separador de Arquivo 29 GS Separador de Grupo 30 RS Separador de registro 31 US Separador de Unidade 32 Espaço 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 83 ENG06842 – Programação I 79 O 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91 [92 \ 93 ] 94 ^ 95 _ 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 DELETE 84 7. Linguagens de programação e execução de programas 7.1. Introdução 7.2. Tradutores: compiladores e interpretadores 7.3. Compilador PASCAL 7.4. Exercícios 8. A Linguagem Pascal 8.1. Introdução 8.2. Tipos de dados simples 8.3. Mapeamento Portugol x Pascal 8.4. Unidades pré-definidas 8.5. Palavras reservadas 8.6. Funções pré-definidas 8.7. Tipos definidos pelo usuário 8.8. Exercícios 9. Estruturas de dados 9.1. Introdução 9.2. Variáveis compostas homogêneas 9.3. Variáveis compostas heterogêneas 9.4. Algoritmos de classificação e busca 9.5. Exercícios 10. Modularização 10.1. Introdução 10.2. Procedimentos 10.3. Funções 10.4. Escopo de variáveis 10.5. Parâmetros 10.6. Recursividade 10.7. Exercícios 11. Armazenamento de dados 11.1. Arquivos 11.2. Exercícios Referências Apêndice A – Mensagens de erro do Turbo Pascal Apêndice B – Tabela de códigos ASCII