Baixe o app para aproveitar ainda mais
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 2 Sumário Sumário ..................................................................................................................................... 2 7. Linguagens de programação e execução de programas ....................................... 3 7.1. Introdução .............................................................................................................. 3 7.2. Tradutores: compiladores e interpretadores ..................................................... 4 7.3. Compilador PASCAL .............................................................................................. 6 7.4. Exercícios .............................................................................................................. 13 8. A Linguagem Pascal .................................................................................................. 15 8.1. Introdução ............................................................................................................ 15 8.2. Tipos de dados simples ...................................................................................... 15 8.3. Mapeamento Portugol x Pascal ......................................................................... 17 8.4. Unidades pré-definidas ....................................................................................... 19 8.5. Palavras reservadas ............................................................................................ 20 8.6. Funções pré-definidas ........................................................................................ 21 8.7. Tipos definidos pelo usuário .............................................................................. 27 8.8. Exercícios .............................................................................................................. 30 9. Estruturas de dados .................................................................................................. 31 9.1. Introdução ............................................................................................................ 31 9.2. Variáveis compostas homogêneas .................................................................... 31 9.3. Variáveis compostas heterogêneas .................................................................. 37 9.4. Algoritmos de classificação e busca ................................................................. 43 9.5. Exercícios .............................................................................................................. 45 10. Modularização ............................................................................................................ 47 10.1. Introdução ............................................................................................................ 47 10.2. Procedimentos ..................................................................................................... 48 10.3. Funções ................................................................................................................. 49 10.4. Escopo de variáveis ............................................................................................. 51 10.5. Parâmetros ........................................................................................................... 52 10.6. Recursividade ....................................................................................................... 56 10.7. Exercícios .............................................................................................................. 56 11. Armazenamento de dados ....................................................................................... 62 11.1. Arquivos ................................................................................................................ 62 11.2. Exercícios .............................................................................................................. 71 Referências ............................................................................................................................. 72 Apêndice A – Mensagens de erro do Turbo Pascal .......................................................... 73 Apêndice B – Tabela de códigos ASCII .............................................................................. 76 ENG06842 – Programação I 3 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. 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 ENG06842 – Programação I 4 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ênciade máquina (é praticamente a mesma, não importando o computador utilizado). 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 ENG06842 – Programação I 5 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 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). ENG06842 – Programação I 6 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! Fonte de 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. ENG06842 – Programação I 7 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 detectar o 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. 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 ENG06842 – Programação I 8 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 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. ENG06842 – Programação I 9 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. 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. oFind – 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. ENG06842 – Programação I 10 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. 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. ENG06842 – Programação I 11 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. 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. ENG06842 – Programação I 12 o Go to next – visualizar a próxima mensagem da janela de mensagens. 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. ENG06842 – Programação I 13 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 c) tradutor ENG06842 – Programação I 14 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. ENG06842 – Programação I 15 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. Exemplos: -45, 1, 138, 0, -2. ENG06842 – Programação I 16 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 significativos 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). 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’. ENG06842 – Programação I 17 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; inicio 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 := 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 ENG06842 – Programação I 18 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; 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. ENG06842 – Programação I 19 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); ... 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. ENG06842 – Programação I 20 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, ...). 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 ENG06842 – Programação I 21 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 implementation 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 integersqr(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 ENG06842 – Programação I 22 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); 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: ENG06842 – Programação I 23 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} 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!’; ENG06842 – Programação I 24 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 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: ENG06842 – Programação I 25 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); 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; ENG06842 – Programação I 26 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: 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 procedimentoatual seja o programa principal, exit terminará a execução do programa. Exemplo: if tecla = #27 then exit; { Pressionou ESC, fim } ENG06842 – Programação I 27 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; 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 ENG06842 – Programação I 28 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); 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. ENG06842 – Programação I 29 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. 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 valor 0. 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. ENG06842 – Programação I 30 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. 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. ENG06842 – Programação I 31 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: 60 70 90 60 55 91 100 47 74 86 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 necessitam de apenas um índice para endereçar seus elementos. São conhecidos como Variáveis Compostas Unidimensionais. Declaração de vetores: ENG06842 – Programação I 32 <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: <identificador_constante>: tipo_array = (lista de valores); Ex1: const vetconst: array [1..3] of integer = (0, 1, 2); ENG06842 – Programação I 33 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; var nota: vetorNotas; i: integer; begin i := 1; media := 0; repeat ENG06842 – Programação I 34 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 10 47 94 2 67 98 74 3 16 21 32 Declaração de matrizes: <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. ENG06842 – Programação I 35 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]); ... 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 } ... ENG06842 – Programação I 36 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; 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. ENG06842 – Programação I 37 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; 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; ENG06842 – Programação I 38 b) Declaração na sessão VAR: var <identificador_registro>: record campo 1: tipo 1; campo 2: tipo 2; … campo n: tipo n; end; Exemplo: var funcionarioUFES: record nome: string[40]; idade: integer; funcao: string[30]; salario: real; end; Os campos dos registros podem ser por sua vez de tipos simples ou estruturados (array, registros, etc.). Exemplo: 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]; ENG06842 – Programação I 39 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 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; ENG06842 – Programação I 40 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!’); 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 ENG06842 – Programação I 41 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); 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: ENG06842 – Programação I 42 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 ENG06842 – Programação I 43 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; { ***************** Ordenação do Vetor ******************* } ENG06842 – Programação I 44 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 o numero 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]); end; write('Digite o numero que deseja procurar no conjunto: '); ENG06842 – Programação I 45 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. ENG06842 – Programação I 46 ENG06842 – Programação I 47 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; ENG06842 – Programação I 48 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} writeln('Media = ',MEDIA,4:1) end. ENG06842 – Programação I 49 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; declaração dos objetos locais à função begin comandos da função; ENG06842 – Programação I 50 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} constN = 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} const N = 30; var ENG06842 – Programação I 51 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. 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 ENG06842 – Programação I 52 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. Passagem 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. Passagem 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, ENG06842 – Programação I 53 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); 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 ENG06842 – Programação I 54 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; procedure DOBRA (var NUM: integer); begin NUM := NUM * 2 end; begin readln(X); DOBRA(X); writeln(X); ENG06842 – Programação I 55 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. 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]); ENG06842 – Programação I 56 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; ENG06842 – Programação I 57 ENG06842 – Programação I 58 ENG06842 – Programação I 59 ENG06842 – Programação I 60 ENG06842 – Programação I 61 ENG06842 – Programação I 62 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-seinicialmente 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 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 ENG06842 – Programação I 63 endereços e os telefones. Outro para 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, 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 ENG06842 – Programação I 64 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]; 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). ENG06842 – Programação I 65 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 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 ENG06842 – Programação I 66 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 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 ENG06842 – Programação I 67
Compartilhar