Pré-visualização parcial do texto
Baixe Lógica de programação parte II e outras Notas de estudo em PDF para Introdução à Programação de Computadores, somente na Docsity!
100 Lógica de Programação Cap, & Podemos observar que os algoritmos apresentados são muito semelhantes, que tanto o leitor (que consulta o arquivo) quanto o funcionário (que manipula as informações) atuam de forma muito parecida. Mesmo as diferentes operações que o funcionário pode desempenhar (inserir, eliminar ou modificar dados) também são muito similares. Percebemos, também, que os passos 1 e 4 são sempre idênticos em todos os casos, enquanto o passo 2 está sempre relacionado a uma pesquisa. Entretanto, o passo 3 é o que parece diferenciar realmente cada uma delas, Muito embora ainda seja possível perceber algo de comum entre as atividades do passo 3 - todas estão relacionadas ao fluxo das informações -, em alguns casos o fluxo é da pessoa pata O arquivo e em outros é do arquivo para a pessoa, ou seja, a diferença está apenas no sentido em que os dados trafegam. Abrindo um Arquivo Não se pode obier alguma informação contida em uma gaveta sem antes abri-la. Em nossos algoritmos. isto será feito através do seguinte comando: E — DER] (1) AD Idarquivo: representa o identificador da variável arquivo previamente definida. Exemplo: abra (BIBLOS); Após a execução do comando de abertura, a ficha que está à disposição será sempre a primeira que nele foi armazenada. Fechando um Arquivo Não devemos manter uma gaveta aberta depois de usá-la, pois isso deixaria seu conteúdo exposto a agentes externos que poderiam danificar sua integridade. Por isso, convém sempre fechar os arquivos após sua utilização. Para tal, usaremos: 5) — —+( fecho )——H(0)-—— IdaArquivo = 0) e Em que: zdarquivo: representa o identificador da variável arquivo previamente definida. j | | i RE RO Ea RR Cap. 5 Arquivos 101 Exemplo: feche (BIBLCS); Copiando um Regisiro Em um arquivo não se devem retirar informações desnecessariamente, pois, se assim fosse, este se tornaria vazio rapidamente. Devemos enfatizar que, via de regra, um arquivo não deve ser “consumido” e sim consultado. Para tal, precisamos copiar o conteúdo que nos interessa em algum lugar. Utilizamos então: Em que: Iáarquivo: representa o identificador da variável arquivo previamente definida. IdRegistro: representa o identificador da variável registro de formato igual aquele que compõe o arquivo. Exemplo: copie (BIBLOS, AUX); Quem copia, copia de um lugar para outro diferente. Nesse comando, copiam-se as informações da posição do arquivo para o registro especificado no comando, o qual possui um formato idêntico ao do registro que compõe o arquivo. Ressaltamos que todos os campos do registro do arquivo são copiados para os respectivos campos (por correspondência unívoca) do registro estabelecido no comando. Observamos que o fluxo dos dados nesse comando é sempre da variável arquivo para a variável registro, ou seja, é à variável registro que efetivamente recebe o resultado da operação. ' Guardando um Regisiro Para guardarmos um registro no arquivo, faz-se necessário que este possua estruturação de campos idêntica à dos registros já armazenados, e ao mesmo tempo esteja completamente preenchido. Para efetuar esta operação, temos o comando: — (guardo) Ds] Tãaremivo O TdRegistro ] - +01) (+ Em que: Idarquivo: representa o identificador da variável árguivo previamente definida. IcRegistro: representa o identificador da variável registro de formato igual àquele que compõe o arquivo. Exemplo: guarde (BIELOS, AUX); Quem guarda, guarda alguma coisa em algum lugar; nesse comando guarda-se sempre alguma informação de dado registro (definido no comando) para a posição atual do arquivo. Observamos que o fluxo dos dados nesse comando é sempre da variável registro para a variável arquivo, ou seja, é a variável arquivo que efetivamente recebe o resultado da operação. Eliminando um Regisiro Algumas informações contidas em um arquiva podem eventualmente se tornar indesejadas por diversos motivos: por exemplo, a desatualização de um dado (tal como um telefone de alguém com quem não se tem contato há mais de 5 anos) ou a perda da relação entre a representação e o objeto representado (tal como um livro extraviado em uma biblioteca). Para podermos eliminar as inforrmações indesejadas, utilizamos; Em que: Ldarquivo: representa o identificador da variável de arquivo previamente definida. Exemplo: elimina (Bibios); Quem elimina, elimina algo de algum lugar; nessa comando elimina-se sempre o registro da posição corrente do arquivo especificado (definido no comando). É Cap.5 Arquivos 103 Convepção Seguencial Quando criamos um arquivo, utilizamos determinado padrão de comportamento que estabelece o modo pelo qual os registros são armazenados no arquivo, isto é, o algoritmo estabelece a estruturação do arquivo. Caso a gravação dos registros (que não estão em ordem) no arquivo seja feita de forma contínua, um após o outro, teremos estabelecido uma circunstância de seqiiência no armazenamento dos registros ubtendo um arquivo cuja concepção é dita segiencial. , Nestas circunstâncias, discorremos que a localização de qualquer um dos registros que foi armazenado é indeterminada, ou seja, para acessar um registro específico precisamos obedecer a sua ordem de gravação, o que implica percorrer todos os registros que o antecedem. aa Como exemplo de um arquivo de concepção sequencial, podemos utilizar uma lista particular de telefones, na qual o usuário armazenou nomes e telefones das pessoas à medida que as conhecia, Supondo que o usuário tenha conhecido mais uma pessoa, precisa, portanto, armazenar mais um telefone em sua lista. Uma vez que a lista já possui alguns nomes, que devido às circunstâncias foram gravados um após o outro, só é possível armazenar um novo telefone após o último registro (nome + telefone) armazenado, o que nos leva a ter de descobrir onde está o último registro. Para tal, será necessário percorrer todos os registros do arquivo, a partir do primeiro, até encontrar o fim do arquivo, o que pode ser feito com o auxílio do comando: aa Tm —— pl avance ——— Tá A ivo je ( vence ; * Ota rquivo Em que: IGArquivo: representa o identificador da variável de arquivo previamente definida. . Esse comando coloca o arquivo na posição consecutiva, ou seja, no próximo registro. Se utilizado repetidas vezes permits percorrer o arquivo passando por uma série consecutiva de registros. E também com o auxílio de: Lógica de Programação Cap & Algo: tmo 5.3 Alteração de dados. início poderá ser eliminado, mas para tanto será nece: tipo pessca = tipo pes pessoa: pessoal: caracter: inteiro: novcFone; abra (agenda); leia copie enquanto (aux. nome<>nemeProcuradoje (não fdatagenda)) faça registro caracter: inteiro; fimregistro; s081 = arquivo composto de pessoa; aux; agenda; nomeProcurado ; nome; fone; inomeProcurado) ; (agenda, aux); avance copie (agenda tagenda, aux) ; fimenquanto; se (aux.nome = nomeProcurado) então início escreva (aux, nome, “possui escreva ("Novo telefona”); leia (novoFane) ; aux. fone +- novoFone; guarde (agenda, aux); Fim; senão escreva fone”, aux. fone) ; ("Telefone não registrado!"); Eimse; feche fim. (agenda) ; Observamos que: a é preciso ter cuidado de não avançar a posição corrente depois de ter encontrado o registro, pois temos, após a atualização, de regravá-lo na mesma posição; a é útil mostrar ao usuário quais eram as informações anteriores, visto que outra pessoa ou ele mesmo já pode ter atualizado o telefone anteriormente. Se, por qualquer motivo, algum telefone arquivado não for mais desejado, ele rio primeiro localizar o registro, para em seguida eliminá-lo após uma confirmação. Algoritmo 5.4 Exclusão de registros. Cap. 5 Arquivos 107 início tipo pessoa - registro caracter: Nome; inteiro: Fone; fimregistro; tipo pessoal = arquivo composto de pessoa; pessoa: aux; pessoal: agenda; caracter: nomeProcurado, confirmação; abra (agenda); leia (nomeProcurado); repita copie (agenda, aux); avance na) ; até (aux.nome « romeProcurado) ou (fdalagenda)); se aux. nome nomeProcurado, fim: fim. então início escreva (aux.nome, aux. fone); escreva (“Confirma ex leia (confirmação) ; se confirmação = “8” então elimine (agenda); fimse; Fim; senão escreva (“Nome não encontrado”); fecha (agenda); se ; Observamos que: é importante certificar-se de que a posição corrente no arquivo é a correta, apresentando os dados que nela constam; sempre é recomendável solicitar uma confi exclusão, porque depois de executada não have: nação para uma operação de mais volta. o de Fixação 1 1.1 Utilizando o problema da biblioteca apresentado na introdução deste capítulo, elabore um algoritmo destinado: a) ao usuário da categoria leitor, que almeja obter uma relação dos livros que a biblioteca dispõe sobre determinado assunto; 108 Lógica de Programação Cap. 5 b) ao usuário da categoria funcionário, que precisa exercer qualquer espécie de manipulação dos dados a partir de um código de livro. 1.2 Imagine dois arguívos de nomes e telefones que são inicialmente idênticos, e são entregues a pessoas diferentes, as quais fregiientemente vão atnalizando-os, porém Ê ções em registros diferentes. Resultado; pouco tempo depois cada uma faz atual os arquivos estão diferentes, mas deseja-se unificar as alterações, gerando um novo arquivo que contemple as alterações mais recentes. A estrutura do registro é a que se segue: Neme : . o ” em Telefone; Data Ga alteração: po de operação: o Observamos que existe um campo Tipo de Operação, que vale À para uma Alteração, E para uma Exclusão e [ para uma Inserção. Consideremos também que os registros excluídos não são eliminados (são apenas marcados). Essa categoria de algoritmo, que visa sincronizar alterações feitas em arquivos seglienciais de forma independente, também é conhecida por Balance Line. O Balance ou seja, na ausência de linhas de comunicação que permitissem atualizar diretamente o arquivo principal. Utilizavam-se arquivos secundários, oriundos de diversas localidades, contendo alterações que seriam submetidas através de um algoritmo de Balance Line ao arquivo principal, Concepção Direta Ao-criar um arquivo, podemos utilizar um algoritmo que expresse um padrão de comportamento rígido, com o objetivo de estruturar o arquivo para facilitar sua mani- pulação. A circunstância de armazenamento que perfaz esse algoritmo é a da localização do registro dentro do arquivo ficar diretamente relacionada a uma informação constituinte deste, ou seja, através de um dos campos do registro podemos determinar o lugar onde este está guardado, podendo acessá-lo de modo instantâneo. Obtemos, então, nessas circunstâncias, um arquivo de concepção direta (ou randômica). Quando utilizamos um arquivo de concepção randômica, podemos acessar um registro específico diretamente, sem nos preocuparmos com seus antecessores, utilizando nesse acesso o mesmo campo que determinou sua posição no arquivo no instante da gravação. O campo que determina a posição do registro no arquivo é denominado chave, pois é a informação capaz de acessar o registro. A chave determinada no algoritmo Cap. 5 Arquivos 109 deve ser única, pois nunca podemos armazenar dois registros diferentes em uma mesma localização. Em um arquivo de concepção direta, ao contrário de em um de concepção seguencial, os registros não ficam localizados na ordem em que são gravados, o que leva a entender que cada registro possui um lugar “reservado” para ser guatdado lugar este identificado através da chave. “o Para exemplificar um arquivo de concepção direta, imaginemos a situação de um professor que deseja armazenar informações referentes a uma de suas turmas, como o nome do aluno e suas quatro notas (bimestrais). Para tal, ele utiliza como chave o código de chamada do aluno, informação que também é parte integrante do registro e é única ou seja, cada aluno possui seu número, não havendo possibilidade de números iguais. Na medida em que o professor possua a nota de um aluno, precisa cadastrá-la no arquivo, guardar suas informações no lugar “reservado” para esse registro. A posição é conhecida pela chave de acesso (código do aluno) e, para que a posição corrente do arquivo passe a ser a indicada pela chave, utilizamos o comando: E —»( posicione) Us] TaRrquiva + cenve HO Em que : Idarquivo: representa o identificador da variável de arquivo previamente definida; CHAVE: é um inteiro (constante ou variável) que indica a posição corrente desejada, Construindo o algoritmo para fazer O cadastramento dos alunos, obtemos: Algoritmo 5.5 Cadastro para concepção direta. início tipo aluno « registro caracter: nome; inteiro: número; real: N1, N2, N3, Na; fimregistro; tipo sala - arquivo composto de aluno; aluro: aux; sala: diário; abra (diário); Ífi2 Lógica de Programação Cap 6 escreva (aux.nome, “possui nota”, qualNota, “=”, nota); escreva (“Nova nota:"); leia (nota); escolha qualNota caso 1: aux.Ni — nota; caso 2: aux.N2 + nota; caso 3: aux.N3 + nota; caso 4d: aux.N4 + nota; Fimescolha; guarde (diário, aux); feche (diário); Observamos que: = gcorreu a Hberdade de escolha em relação a qual nota seria alterada/cadastrada, o que levou à utilização de duas seleções de múltipla escolha no instante da leitura do registro e no instante da gravação. Exercício de Fixação 2 2.1 Possuindo as mesmas informações utilizadas no exemplo desenvolvido em Arquivos de Concepção Direta, temos que o professor necessita de um algoritmo que lhe mostre as seguintes informações, definidas em seu esquema particular: Nº aluno Nome Média anual Aprovado Recuperação 99998 [ XRRKRAX 0...10 (Sim ou Não) | (Sim ou Nãc) Levando em consideração as seguintes normas escolares: e Um aluno é reprovado sem recuperação quando não atinge média 5. = Tem a oportunidade de recuperação se mantiver uma média anual entre 5 e 7. a Está aprovado se atingir média final maior ou igual à 7. Ao fim da relação devem ser mostrados qual a melhor e a pior média entre os alunos da turma e os respectivos nomes dos alunos. Es a Estudo de Concepções Vimos que, dependendo das circunstâncias de criação, um arquivo pode ser concebido direta ou segúencialmente, o que não obriga necessariamente que ele seja sempre manipulado como foi concebido; em outras palavras, um arquivo concebido rando- Cap. 5 Arquivos ..113 micamente pode ser acessado sequencialmente, sob certas condições especiais; assim como um arquivo concebido seguencialmente pode ser acessado diretamente, sé for necessário. Qualquer arquivo concebido diretamente passa por um certo planejamento, que antecede sua criação, onde se detine a chave de acesso do arquivo. Caso esse planejamento tenha sido inadequado, pode surgir a necessidade de obter informação do arquivo a partir de um campo não-chave, o que, nesta circunstância, implica a impossibilidade de acessar diretamente o registro procurado por não saber onde ele se encontra, e então forçar uma busca sequencial no arquivo de concepção randômica. Como exemplo, imaginemos uma faculdade que foi inaugurada em 1980 e que utiliza como chave o Registro Geral (da Carteira de Identidade) de seus alunos em um registro: dencialne Figura 55 Ficha de cadastro de aluno. Rc Número de matrícula: | Nome: Curso: Nacionalidade: Naturalidade: Data de nascimento: Ê FA , Se & arquivo foi corretamente concebido, permitirá o acesso através de um Posicionamento com o auxílio da chave RG, Porém, a coordenação dessa entidade somente identifica seus alunos através de seus respectivos números de matrícula e, nessa circunstância, caso queira obter informações sobre algum aluno a partir de seu número de matrícula, terá de fazer uma busca segiencial no arquivo concebido Tandomicamente. E 114 Lógica de Programação Cap. 5 oritmo 5.8 Exemplo de arquivo randômica acessado sequencialme início tipo aluno registro caracter: nome, curso, nac, nat; inteiro: RG, mat, dataNasc; fimregistro; arguivo composto de aluno; tipo faculdade aluro: aux; faculdade: flog; inteiro: matProcurada; abra (flog); leia (matProcurada); copie (flog, aux); enquanto (aux mate>matProcurada) e (não fda(flog)) faça avance (flog); copie (flog, aux); fimenquanto; se aux.mat ralprocurada então escreva (aux.mai, aux.nome); senão ascreva (“Aluno não registrado!) : fimse; feche (flog); fim. Com o decorrer do tempo, pode-se tornar mais usual q acesso à esse arquivo via número de matrícula, quando cairia em desuso seu acesso direto do modo como fora planejado. Nessa ocasião, seria melhor “converter” o arquivo concebido da forma antiga para outro concebido randomicamente através da chave número de matrícula. Nessa faculdade, os códigos de matrícula são estruturados de modo que, dos sete dígitos desse cádigo, os quatro primeiros representem o ano de matrícula (1990, 1995, 1998) c os três restantes, um número segiiencial para as 900 matrículas de cada ano. Se fôssemos armazenar o primeiro aluno matriculado, ele seria registrado na posição 1.990.001 do arquivo, fazendo-se necessário deixar inutilizadas as 1.990.000 primeiras posições. Podemos otimizar este espaço de armazenamento, subtraindo 1.990.000 do número de matrícula, como vemos em parte do algoritmo de “conversão”: Algoritmo 5.9 Conversão de chave de arquivos. . inicio tipo aluno = registro caracter: nome, curso, nac, nat; inteiro: RG, mat, dataNasc; Cap 5 Arquivos 115 a fimregistro; Ene anride = arquivo composto de aluno; faculdade: flog, novo; inteiro: pos; abra (flog); abra (novo); repita copie (flog, aux); pos + aux.mat - 1959000; posicione (novo, pos); guarde (novo, aux); avance (flog): até fdaiflog); feche (flog); feche (novo); Exercício de Fixação & 31 Com base no arquivo da faculdade (“convertido”) desenvolvido no Estudo de Concepções, respectivo ao item Arquivo Direto Acessado Sequêncialmente, construa os seguintes algoritmos para: , a) imprimir uma relação de alunos por curso; b) imprimir uma relação de alunos estrangeiros; o imprimir uma relação de alunos estrangeiros por curso; 4) permitir alteração no registro de um aluno, sendo que esta deve possibilitar a mudança de todas as informações do aluno (exceto o número de matrícula) ou seja, serão lidos dados para cada um dos campos, porém, se o conteúdo de alguns destes for nulo, deve-se manter o antigo valor daquele cai ; e) permitir a matrícula de um novo aluno. ves Arquivo Sequencial Acessado Randomicamente: Arquivo indexado Um arquivo concebido seglienciaimente foi preenchido na mesma segiência em que as informações foram surgindo. Isto, por definição, condena-o a gravar ou ler piormações sequencialmente, o que se tornaria inconveniente se o arquivo crescesse E ração untado fnssem muito frequentes, porque a cada operação de inclusão, para Lelis são, seria necessário realizar uma busca exaustiva em todo o arquivo pe izar O ponto desejado, e somente então fazer a alteração. siiação à Pustrar como o problema pode ser contornado, tomemos como exemplo a e uma empresa fundada em 1985, que registra seus funcionários à medida 18 Lógica de Programação Cap. 5 inteiro: codProcurado; nc); abra (argCod); leia (codprocurado) ; se codbrocurado < 1990000 então escreva (“Código inválido”); senão início posicione (arqco&, Co&procurado - 1996000); copie (argCod, aux2); posicione (cadFurc, auxa posição) ; copie (cadrunc, auxl); escreva (auxi.nome, auxl.cargo); fim; fimse; feche (cadFunc); fache (araCod); fim. Exercício de Fixação 4 41 1. Utilizando o exemplo da empresa descrito no Estudo de Concepções, Arquivo Indexado, desenvolva um algoritmo que: q) gere o arquivo de índices; b) imprima uma relação de funcionários não-solteiros; c) imprima uma relação de funcionários por número de dependentes; d) imprima uma relação de funcionários por faixas salariais, assim divididas: = Ja2 saláriosmínimos; 2a 4 salários mínimos; 4a 7 salários mínimos: 7a 10 salários mínimos; a acima de 10 salários mínimos; sendo que o valor do salário mínimo deve ser fornecido pelo usuário; e) permita a inclusão de um novo funcionário; f) possibilite a alteração das informações de um funcionário; 8) possa efetuar à demissão de um funcionário, sendo que a data corrente deve ser fornecida no ato da transação. Dados dois arquivos concebidos. sequencialmente, possuindo as informações descritas nas fichas esquematizadas, desenvolva um algoritmo que realize uma união destes. Essa união implica criar um terceiro arquivo no qual constem apenas Cap: 5 Arquivôs cita informações das pessoas que faziam parte de ambos os arquivos sequenciais; informações que não possuírem correspondência não deverão existir no terceiro arquivo. Noms : Endereço: Telefone: | Nome : Endereço: Bairro: Cidade: CRP: o Pata nasc.t ; - am ra A 2. A partir da estrutura dos registros, construa os algoritmos solicitados para administrar os problemas cotidianos de um clube: a Arquivo de Associados: randômico a Chave: Código Nº sócios. Nome:... Brdereço: Bairro: ni Cidade: Estado: . | Wº dependentes: | Data de associação: | s Arquivo de Mensalidades: sequencial Nº sócio; Data vencimento: valor: Data de pagamento: a) Calcular o número total de possíveis fregientadores do clube ttitulares + dependentes). b) Apresentar a relação dos associados que aniversatiam em determinado mês fornecido. 1a 0 Lógica de Programação Cap. 5 e) Construir um único algoritmo capaz de fazer inclusões, alterações e exclusões no arquivo de associados. d) Elaborar um algoritmo que crie uma nova mensalidade para cada sócio, na data e valor fornecidas. e) Apresentar a relação dos associados inadimplentes, junto com o tespectivo valor total da dívida, mostrando ao final o valor totalizado de todas as dívidas dos associados. Com o modelo dos registros a seguir, construa os algoritmos relacionados à administração de contas correntes em um banco. a Arquivo de Correntistas: randômico a Chave: Conta corrente Conta corrente: me . em Correntista: e Data abertura: — Agência: a Arquivo de agências: tandômico = Chave: Nº Agência f Nº Agência: Nome agência: = Arquivo de Lançamentos: sequencial Conta corrente: Data: meo Valor: pao DoGtO: mam Histórico! o a) Imprimir relação com o nome e a quantidade de correntistas de cada agência. b) Imprimir um ranking das dez agências com imaior montante de saldos. c) Calcular o saido de dado correntista em uma data fornecida. «) Emprimir um extrato para um período (data inicial e data final) e conta corrente fornecida. O extrato deve apresentar o saldo anterior e, para cada lançamento do período, deve apresentar a data, histórico, número do documento e valor. Ao final deve apresentar o saldo remanescente. Cap. 5 Arquivos 121 4. Dados dois arquivos concebidos randomicamente e um, segitencialmente, descritos através do diagrama representativo de seus respectivos registros, elabore os algoritmos especificados que têm por objetivo suprir as necessidades de uma videolocadora: » Arquivo de Clientes: randômico = Chave: Código Código: ” cam Velefone: Nome :. Endereço: B6t Crpr a s Arquivo de Fitas de Vídeo: randômico * Chave: Código da fita Código: . o Gecar (S/N): mítulo: . Assunto: Data de compra; f f m Arquivo de Movimento: segiúencial | Código fita: Códige cliente: Í | Qtde, dias fora: Preço: a) Consultar quais nomes e assuntos dos filmes um cliente, fornecido, já locou. &) Consultar quais clientes (com nome e telefone) locaram determinada fita. «) Enprimir relatório: s de gastos de cada cliente; a da relação das fitas que cada cliente locou mais de uma vez, com suas respectivas quantidades; a de fitas por assunto; a de fitas premiadas com um Oscar, d) Consultar quais filmes já premiados com o Oscar um determinado cliente já tocou. e) Imprimir uma relação com todas as fitas já locadas, e o total de tempo respectivo em que cada uma foi locada. 124 Lógicade Programação Cap. 8 Esse processo de decomposição contínua também é conhecido como Refinamentos Sucessivos, porque se parte de um problema complexo e abrangente, que é sucessi- vamente dividido até resultar em problemas mais simples e específicos. À técnica de Refinamentos Sucessivos também se dá o nome de Top-Down (de cima para baixo), uma vez que se parte de conceitos mais abrangentes (abstratos) até atingir o nível de detalhamento desejado. Também existe, apesar de menos difundida, uma técnica exatamente inversa, conhecida por Boitom-Up (de baixo para cima). Consiste em partir dos conceitos mais detalhados e ir agrupando-os sucessivamente em níveis mais abrangentes (abstratos), até atingir q nível de abstração desejado. O processo de compreensão é frequentemente mais natural quando sc usa a técnica Tep-Down. Por exemplo, é mais fácil compreender um automóvel partindo-se do todo até o úllimo parafuso do que do parafuso até o todo. Certamente existem exceções. Por exemplo, é mais [ácil entender operações aritméticas mais abstratas, como potenciação e radiciação, se antes soubermos somar & subtrair. Yléduios Depois de decompor um problema complexo em subproblemas, podemos construir um subalgoritmo ou módulo para cada subproblema. Passaremos a descrever de que forma isso poderá ser feito, mas antes apresentaremos o problema que será utilizado no decorrer do capítulo. Construir um algoritmo que calcule os atrasos e as horas trabalhadas de um dado funcionário, a partir do seguinte cartão de ponto. Figura 6.1 Cartão de ponto, Manhã tarãe Dia ” Entrada Saída Entrada Saida 1 2 . 31 I J o Ao final deverá ser impresso o total de atrasos e de horas trabalhadas no mês acompanhados das respectivas médias por dia. Cap. 6 Moduiarizando algoritmos. 125: Define-se como horas trabalhadas a soma das diferenças entre entrada e saída dos períodos de manhã e tarde & atraso como a soma dos tempos decorridos após as g horas (no período da manhã) e após as 14 (no período da tarde). Algorkmo 6.1 Cálculo dos atrasos e horas trabalhadas — versão 1 início tipo dia = registro inteiro: em, sm, et, st; fimyegistro; ia - registro inteiro: atraso, horas; fimregistro; tipo Vi = vetor [1..31] de dia; tipo VZ = vetor [1..3]] de tocpie; Vl: cartão; otalbia; inteiro: dia, a, b, c, d Toth, totarr; cont e Q; leia (dia); enquanto (dia > 0) e (dia « 32) faça leia (a, b, c, d); cartão[dia] .em «- a; cartão [dia]. em rrãoídial.et rão(diaj,st cont e- cont + leia (Gia fimenquanto; se cont » 0 então início para i de 1 até con: faça ofil em; me — (me div 100)*60 + me mos 109; ms e córtão[i].sm; ms e (ms div 100)*60 + ms mod 100; tm e ms — me; atrm e me — 480; me e cartãoiil et; me + (me div 100)*60 + me mod 100; ms €«- cartãoli].st; ms e (ms div 200)*60 + me mos 190; tr e-ms - ne; tipo tor 1, me, ms, cm, tt, atrm, atri, 1268 tógicade Programação Cap 6 fi] horas e ta + vt; atri e- me — 840; votalbiali) atraso €- atem + ab ioth e- toth + (Un + LL); totavr «- totatr + (atm + atri); fimpara; para i de 1 até cont faça escreva (cartão[i'.em, cartão[ii.em); escreva (cartão[ij.et, cartão[i].st); escreva ij.hores div 60); horas mod 60); aso div 50); escreva (totalbia[i].atraso mod 50); finmara; escreva ((toth/cont) div 60, (toth/cont) mod 40); escreva (tolh div €0, Lotk mod 60); escreva ((totatr/cont) div 69, ftotatz/cont) mod 66); escreva (totatr div 60, totatr mod 65); fim; fimse; Fim. Esta seria a construção de um algoritmo conforme vínhamos fazendo até agora, ou seja, um algoriimo que resolve diretamente o problema como um todo, por mais que para concebê-lo tenhamos decomposto o problema. Assim, ao lex o algoritmo, não conseguimos identificar qualquer decomposição feita, o que, por consegiiência, o tornou mais difícil de ler (menos legível), uma vez que seria necessário absorver toda a complexidade de uma única vez. No decorrer do capítulo, utilizamos os módulos para representar no algoritmo a decomposição do problema, Deciaração Para modularizar o algoritmo anterior necessitamos de uma sintaxe para expressar essa nova estrutura compreendida por módulos. De certo modo, precisamos uniformizar determinado conjunto de ações afins, que obedeçam à mesma estruturação de um algoritmo, com o objetivo de representar um bloco lógico em especial. Para delimitar um módulo, utilizamos os delimitadores módulo e £immádulo: TT o . Cap. 6 Modutarizando algoritmos 127 Exemplo: módulo « Identificador > // início do bloco '! declarações das variáveis ínrernas t! conjunto de ações fFimmódulo, // Fim lógico bleco légico Em que: Identificador: é o nome pelo qual o módulo será referenciado no algoritmo. Quando construímos um múdulo, estamos, na verdade, em instância menor, ou seja, um pequeno conjunto solução, praticamente independente. Esse subalgoritmo pode inclusive utilizar outros módulos. , Vejamos, então, como ficou i . 8, , a decomposição do problema de u forma gráfic. ilustrando os módulos: º Poá forma gráfica construindo um algoritmo Tustraçã o da decomposição do problema, , Problema . Cálculo Impressão] Hanhã Tarde Ho De] fi | Minutos entrada; fitimucos entrada] . i ! í | [ itinetos saida | Ditos saída ] | i [. dezaso APL rs 1 Podemos representar a mesma decomposição de outra forma: Figura 6.3 Representação hierárquica da decomposição. ana É Lianha | Minutos Minutos. e entrada saída Atraso . E —s 180 Lógica de Programação Cap 6 e Cap. 6 Modularizando algoritmos 181 enquanto (dia » 0) e (dia < 32) faça leia (u, E, c, &) cartãofdial.em € &; cartão [dial.sm — Dz cartão(dial et e c; cartão lGia!.st e cont e cont + Ly leia (dia); fimenquanto; fimódulo; móduloCálculo módulo Manhã módulo MinutoEntrada ne tãofi].em; me e (me div 100)*60 + me mod 190; fimmódulo; módulo Minutos. as e cartão[il.sm; ms e- (me Giv 100)+60 + ms mod 100; Fimmódulo; módulo Atraso atrm + me - 480; fimmódulo; Minulcêntrada; HinutoSaica; im eme - me; Atraso; Fimmódulo; módulo Tarde módulo Minulointrada me «- cartão[il.et; ne e (me div 100)*60 + me mod 109; firmódulo; módulo Minutosaida ms e cartão(il.st; me e (ms div 100)*60 + me mod 100; Eimmóduio ; módulo Arraso atrt e- me — 840; fimmódulo; MinutoEntrada; MinutosSaída; Lt e ms - me; Aixaso; Fimmóduio; 1 até cont faça Tarde; totalDiali).atraso e atrm totalnia[il. horas e im + toth e toth + (Em + ti); totair — totatr + (atrm fimpara; fimmódulo; módulo Impressão para i de 1 até cont faça arrt; atrt); escreva (cartãc[i?.em, cartão[il.sm); escreva ícartão[il.et, cartão[il.gsr); escreva (LolalDia[i!.horas Giv 60); escreva (totalDia[i escreva (totalDia[i escreva (totalDiaíi Eimpara ; oras mod 60); «atraso div 60); itraso mod 60); escreva ((toth/cont) div 60, coth/cont) mod 60); escreva (toth div 60, Loth mod 60); escreva ((totatr/cont) div 60, ttotatr/cont) moc 60); escreva tiotair div 60, totatr mod 60); fimmódulo; Entrada; se cont > 0 então início Cálculo; Impressão; 152 Lógica de Programação Cap 6 Escopo de 4 O dE Até este momento cuidamos da divisão e da estruturação dos conjuntos de ações afins que compuseram os módulos, porém, não nos preocupamos em agrupar às variáveis coerentemente, ou seja, de acordo com seu emprego na estrutura detinida. Todas as variáveis utilizadas no algoritmo encontram-se declaradas em seu início, o que as torna passíveis de aplicação por qualquer módulo integrante. Essas variáveis são denominadas glohais. Em alguns casos, uma determinada variável é utilizada apenas por um módulo específico, o que não justifica uma definição global, pois somente se fazem necessários o conhecimento e a utilização dessa variável dentro dos limites desse bloco lógico. Esta situação ocorre quando a variável é declarada internamente ao módulo e é denominada variável local. O escopo ou abrangência de uma variável, na realidade, denota sua visibi idade (conhecimento e aplicações) perante os diversos módulos integrantes do algoritmo. A visibilidade é relativa à hierarquia, podemos dizer, então, que uma variável é global a todos os módulos hicrarquicamente inferiores e é locaí quando é visível apenas em seu contexto e não aos módulos hierarquicamente superiores. Para visualizar melhor esses conceitos e analisar casos peculiares, vejamos um exemplo genérico: Figura 6.5 Escopo de var Cap. 8 — Modufarizando algoriimos 133 , Observamos que as variáveis K e J definidas no início do algoritmo são visíveis, a princípio, a todo e qualquer módulo, ou seja, são globais a todos. A variável M é k al ao módulo 3 e visível apenas a este, assim como a variável Y é local ao módulo 2 Em outra situação, temos a variável X, que é local ao módulo 1, sendo visível também ao módulo 2, podendo ser definida relativamente como global ao módulo 2. Em uma situação bastante particular, na qual ocorre um conflito na declara: ão da variável K (início do algoritmo e interior do módulo 1), assumiremos sempre A e a variável a ser utilizada no interior do módulo será a que foi definida neste, in ado a existência de outra variável de mesmo nome no âmbito global, Temos, então que ' módulos 1 e 2 não enxergam a mesma variável global K vista pelo módulo 3 e dim, à variável K definida localmente a 1 e globalmente a 2. + fd Refazendo o algoritmo do cartão di li I , le ponto, utilizando os conceitos de esc: variáveis, temos: “opa de Algoritmo 6.5 Cálculo dos airasos e horas trabalhadas — versão 3. início tipo dia = registro inteiro: em, em, et, st; fimregistro; tipo totDia - registro inteiro: atraso, horas; Fimregistro; tipo Vl = vetor [1..31] de dia; tipo V2 = vetor [1..31] de teria; Vi: cartão; V2: totalnia; inteiro: cont, i, tota, totatr; módulo Entrada inteiro: dia, a, Db «e, q cont e 0; leia (dia); enguanto (dia > 0J e (dia < 32) faça leia (a, b, c, d); cartão [dia] .em <- cartão [dia] .sm «- cartão [dial.et + cartão [dia] .st e cont e cont + leia dia); fimenquanto; fimmódulo; pose ] : É 136 Lógica de Programação Cap 8 b» início inteiro: A,B,C; módulo Um inteiro: à,8,D; inteiro: A.C; módulo Dois Ae B+d; inteiro: C,D,E; Ce A- módulo Três Eirnódulo; // Um inteiro: D,E; módulo Dois De 7; inteiro: A,D,E; E e 8; módulo Três Fimmódulo; // três inteiro: B,D; ces; Be c+*2; De 6; De E +; Ee H fimmódulo; // Três Três; fimmódulo; // Dois Aecio: ne 2 De A+ Be 3; Ee Bd De 5; Três; . Dois; fimmódulo; // Dois Fimmódulo; // Um Ae 5; Ae 1; Be A+ 5; Be 2; Ce R-3 Ce a; Dois: Un; Um; fim, fim. Passagem de Parâmetros Aprendemos a decompor um problema por refinamentos sucessivos e a representar essa decomposição através dos módulos ou subalgoritmos. Assim, cada subparte do problema interage apenas com algumas das demais partes, conforme a divisão que foi concebida. Acaba funcionando como um quebra-cabeças onde cada peça possuí apenas uma possibilidade de encaixe com algumas outras peças. Seria mais promissor se cada peça pudesse ser encaixada com qualquer outra peça, como em um bringuedo de montar, o que se torna possível quando cada peça é generalizada, ou seja, é projetada de forma que seu uso possa ser o mais genérico possível. Exemplificando, um módulo que calcula o valor de dois elevado ao cabo (2%) tem uma aplicação muito restrita. Porém, se generalizássemos o módulo de forma à torná-lo capaz de calcular o valor de qualquer base clevada a qualquer expoente, sua aplicação seria muito mais abrangente. Portanto, dizemos que um módulo é generalizado quando ele for parametrizado. . , | l é ' | Ê Cap. 6 — Modularizando algoritmos 137 A. utilização de parâmetros nos módulos funciona de forma muito similar às funções matemáticas, como podemos notar: f(x,y) = x”, em que x e y são parâmetros. Essa função em particular (f) foi definida em termos dos parâmetros x e y. Para calcularmos à fuução para algum valor particular de x e y, devemos substituí-los pelo valor dos argumentos desejados. p= P=9 H5,3) = 5 = 125 Uma correspondência é estabelecida entre os parâmetros da definição c os argumentos utilizados. No primeiro exemplo, o parâmetro x foi substituído pelo argumento 3, enquanto o parâmetro y foi substituído pelo argumento 2. É importante perceber que a ordem é crucial, pois f(3,2) não é o mesmo que f(2,3). Deciaração . A parametrização de um módulo deve evidenciar a interface módulo versus chamada, composta pela declaração dos parâmetros, através da seguinte sintaxe: —>(môâuio )-Hldentiticado: OE ipo (Pl variável É O) | ação |——Eiamiduão Pee) À +» Exemplo: módulo « Identificador » (tipo: Vi, Vv2, V3) 4! declaração das.variáveis internas 4! conjunto de ações fFimmódulo; Em que: Identificador: é o nome pelo qual o módulo será referenciado no algoritmo; V1, V2 e V3: são as variáveis declaradas como os parâmetros do módulo. Exemplificando, vejamos, então, a generalização dos módulos manhã e larde (pertencentes ao módulo Cálculo no Algoritmo 6.5), através do emprego de um Parâmetro que represente o período. i 4 ! 138 Lógica de Programação Cap. 8 módulo CalculaPeríodo (inteiro: HE, HS, período); inteiro: me, mS; módulo MinutcEnicada me — (HE div 100)+60 + EZ mod 100; fimmódulo; módulo MinutosSaída ns € (HS div 100)*60 + HS mod 100; Fimmódulo; módulo Atraso se período = 480 então início atrm e me - 480; um e ms — me; - Fim; senão início atrt e- me - 840; tt ema - Te; Eim; EFimas; fimmódulo; HKinutokntrada; MinutoSaída; Atraso; fimmódulo; Viilizamos um módulo CalculaPerícdo que unificou os módulos Manhã e tarde empregando para cálculo dos minutos de entrada e saída as variáveis HE é us, respeclivamente, sendo que estes parâmetros permitem o cálculo independente do período em questão, pois seus valores são passados como argumentos. O parâmetro período é utilizado para podermos verificar o valor a ser subtraído no cálculo do atraso (480 para manhã e 840 para tarde) e determinar qual total será calculado (tm ou tt) através dos argumentos que são enviados na chamada ao módulo. Manipulação A passagem de parâmetros ocorre à partir da correspondência argumento-parâmetro: Os argumentos, que podem ser constantes ou variáveis, presentes na chamada do módulo: serão correspondidos pelos parâmetros do módulo, na mesma ordem, ou seja, a0 | | | | | | | Cap 8 — Modularizando algoritmos 1392 primeiro argumento corresponde o primeiro parâmetro, ao segundo argumenti segundo parâmetro e assim por diante. Gumeno é Ilustremos isso através d a req s iss e um módulo que efetue a troca rec; ú é vaidade q íproca de conteúdo Algoritmo 6.7 Módulo Troca. módulo Troca (imteiro: X, Y) inteiro: aux; aux - &; Key; Ye aux; Eimmódulo; Supondo o seguinte trecho de algoritmo: Troca (a, Db); escreva (a, b); Temos que, ao ativar o módulo troca, o valor de A (7) é transferido para seu respectivo parâmetro x, assim como o de & (15) é transferido para Y. Após executad todas as ações do módulo, x valerá 15 e y, 7, e, ao retornar, os valores xeY o transferidos, respectivamente, para A é B, concretizando assim a troca de conte: sãos. Vejamos como ficaria a utilização do módulo cai do nú módulo Cálculo: laPperíodo inserido no Algoritmo 6.3 Acionamento do móduto CalcuiaPeríodo. T módulo Cálculo . inteiro: tm, tt, atrm, atrt; módulo CalculaPeríodo (intei ; ale a eiro: HE, HS, períc inteiro: me, ms; período) módulo MinutoEntrada me €- (EE div 200)+60 Hg 100; Eã dulo; + HE mod 190;