Baixe o app para aproveitar ainda mais
Prévia do material em texto
de pro te cni cas gra ma cao Cassiana Fagundes da Silva Cassiana Fagundes da Silva TÉCN ICA S DE PRO G RA M AÇÃO As técnicas de programação exercem papel fundamental na computação, pois possibilitam aos profissionais dessa área aprender e desenvolver uma programação. À medida que o conhecimento sobre os conceitos e as funcionalidades das linguagens de programação aumenta, o programador desenvolve, também, suas habilidades e passa a ter maior capacidade de entender o comportamento dos programas, bem como mais facilidade para aprender novas linguagens. Código Logístico 59310 Fundação Biblioteca Nacional ISBN 978-85-387-6614-8 9 7 8 8 5 3 8 7 6 6 1 4 8 Técnicas de Programação Cassiana Fagundes da Silva IESDE BRASIL 2020 Todos os direitos reservados. IESDE BRASIL S/A. Al. Dr. Carlos de Carvalho, 1.482. CEP: 80730-200 Batel – Curitiba – PR 0800 708 88 88 – www.iesde.com.br © 2020 – IESDE BRASIL S/A. É proibida a reprodução, mesmo parcial, por qualquer processo, sem autorização por escrito da autora e do detentor dos direitos autorais. Projeto de capa: IESDE BRASIL S/A. Imagem da capa: Rawpixel/Envato Elements CIP-BRASIL. CATALOGAÇÃO NA PUBLICAÇÃO SINDICATO NACIONAL DOS EDITORES DE LIVROS, RJ S579t Silva, Cassiana Fagundes da Técnicas de programação / Cassiana Fagundes da Silva. - 1. ed. - Curi- tiba [PR] : IESDE, 2020. 96 p. : il. Inclui bibliografia ISBN 978-85-387-6614-8 1. Linguagem de programação (Computadores). I. Título. 20-63503 CDD: 005.13 CDU: 004.43 Cassiana Fagundes da Silva Doutoranda em Engenharia da Produção e Sistemas, pela Pontifícia Universidade Católica do Paraná (PUCPR), é mestre em Computação Aplicada, pela Universidade do Vale do Rio dos Sinos (UNISINOS/RS), e graduada em Ciência da Computação, pela Universidade de Santa Cruz do Sul (UNISC/RS). Professora no ensino superior, ministrando disciplinas de Linguagens de Programação, Estrutura de Dados, Sistemas Operacionais, Engenharia de Software, Análise e Modelagem de Sistemas, Inteligência Artificial, Inteligência de Negócios, entre outras. Agora é possível acessar os vídeos do livro por meio de QR codes (códigos de barras) presentes no início de cada seção de capítulo. Acesse os vídeos automaticamente, direcionando a câmera fotográ�ca de seu smartphone ou tablet para o QR code. Em alguns dispositivos é necessário ter instalado um leitor de QR code, que pode ser adquirido gratuitamente em lojas de aplicativos. Vídeos em QR code! Agora é possível acessar os vídeos do livro por meio de QR codes (códigos de barras) presentes no início de cada seção de capítulo. Acesse os vídeos automaticamente, direcionando a câmera fotográ�ca de seu smartphone ou tablet para o QR code. Em alguns dispositivos é necessário ter instalado um leitor de QR code, que pode ser adquirido gratuitamente em lojas de aplicativos. Vídeos em QR code! SUMÁRIO 1 Introdução a linguagens de programação 9 1.1 Conceitos de linguagens de programação 9 1.2 Evolução das linguagens de programação 15 1.3 Razões para estudar linguagens de programação 20 1.4 Tradutores de linguagens de programação 23 2 Desenvolvendo um programa 29 2.1 Análise léxica e sintática 30 2.2 Nomes e variáveis 33 2.3 Tipos de dados 36 2.4 Expressões e sentenças de atribuição 45 3 Estruturas de seleção de controle 53 3.1 Sentenças de seleção 54 3.2 Sentenças de iteração 57 3.3 Desvio incondicional 61 3.4 Comandos protegidos 62 4 Modularização 66 4.1 Fundamentos de subprogramas 67 4.2 Métodos de passagem de parâmetros 70 4.3 Subprogramas sobrecarregados e genéricos 73 4.4 Semântica de chamadas e retornos 75 5 Orientação a objetos 80 5.1 Conceitos de abstração 80 5.2 Tipos abstratos de dados e encapsulamento 82 5.3 Implementação de construções orientadas a objetos 86 5.4 Metodologias de desenvolvimento top down e bottom up 89 Gabarito 94 As técnicas de programação exercem papel fundamental na computação, pois possibilitam aos profissionais dessa área aprender e desenvolver uma programação. À medida que o conhecimento sobre os conceitos e as funcionalidades das linguagens de programação aumenta, o programador desenvolve, também, suas habilidades e passa a ter maior capacidade de entender o comportamento dos programas, bem como mais facilidade para aprender novas linguagens. Considerando essa relevância, no primeiro capítulo, serão abordados os conceitos de linguagem de programação, de modo a entender sua evolução histórica e as razões pelas quais se deve estudar e compreender seus diversos tipos. Os domínios e métodos de implementação de linguagens também são discutidos para que o leitor entenda qual é o melhor paradigma a ser usado nos diversos ambientes. O segundo capítulo apresentará as estruturas básicas de um programa em desenvolvimento, destacando a importância da análise léxica e sintática, a declaração de variáveis e os tipos de dados. Também serão ilustradas as expressões e sentenças de atribuições usadas na criação de um programa. O terceiro capítulo propõe reflexões sobre as estruturas de seleção de controle e seus respectivos tipos, de maneira que o leitor saiba aplicar e identificar qual das estruturas é mais adequada no desenvolvimento de um programa. Diante da importância de aprimorar continuamente o desenvolvimento de programas, o quarto capítulo visa estabelecer os conceitos de subprogramas ou modularização nas linguagens de programação, ou seja, quando o programa é dividido em partes distintas, tornando-o mais legível e de fácil manutenção para os programadores. No último capítulo, as características principais do desenvolvimento de programas orientados a objetos são destacadas, além da modularização e do desenvolvimento por meio das metodologias top down e bottom up. Espera-se que este livro favoreça pesquisas e o aprofundamento nos conhecimentos das técnicas de programação. Boa leitura! APRESENTAÇÃO Introdução a linguagens de programação 9 1 Introdução a linguagens de programação Diariamente, vários programas são desenvolvidos e disponibi- lizados no mercado para uso geral ou específico. A criação desses programas somente torna-se possível por meio das linguagens de programação que, há décadas, vêm sendo usadas por profissionais de computação. É por meio das linguagens de programação que se pode fazer um computador seguir instruções para realizar qualquer processo. Vale lembrar que, inicialmente, as linguagens de programação eram bastante simples, uma vez que os computadores tinham limi- tações no que diz respeito a suas configurações físicas de proces- samento e memória. Porém, com os avanços tecnológicos, novas linguagens vêm sendo criadas para atender às necessidades dos usuários. Desse modo, o objetivo deste capítulo é apresentar uma reflexão sobre as linguagens de programação (conceitos, evolução e especificações) embasada em pesquisa bibliográfica da área, para favorecer uma compreensão abrangente sobre elas e os pa- radigmas que as classificam. 1.1 Conceitos de linguagens de programação Vídeo As linguagens de programação surgiram juntamente com os pri- meiros computadores e, ao longo dos anos, têm evoluído e melhorado em relação aos recursos e às formas de implementação. Sendo assim, tornaram-se amplamente conhecidas por profissionais da área da computação que são também, muitas vezes, usuários de linguagens e de ambientes de programação. É importante ressaltar que para utilizar uma linguagem, primeira- mente, ela necessita ter sido projetada e implementada. Por isso, para 10 Técnicas de Programação entender melhor os conceitos de uma linguagem de programação, con- vém, antes, compreender o que é um programa. Um programa se manifesta como um documento que especifica uma sequência de operações a serem executadas. Pode ocorrer, ainda, de ele efetivamente considerar as operações especificadas durante a sua execução. Nesse sentido, entende-seum programa como uma máquina abstrata que manipula e produz dados. Resumidamente, é a descrição da máquina, por meio do documento, e a própria máquina quando em execução. Portanto, todo programa deve ser implementado em deter- minado mecanismo físico (computador) para que sua execução possa ser simulada fisicamente. Assim, uma linguagem de programação define os recursos dispo- níveis e as formas de construir as máquinas abstratas específicas, de modo a serem simuladas corretamente nos computadores. Coerentes com essa perspectiva, De Melo e Da Silva (2003) defi- nem linguagem de programação como um conjunto de recursos que podem ser compostos para construir programas específicos ou, ainda, um conjunto de regras de composição que garantem que todos os pro- gramas possam ser implementados com qualidade nos computadores. Nesse contexto, para que linguagens de programação sejam projeta- das, características, como requisitos, expressividade, paradigma, im- plementação e eficiência, precisam ser respeitadas. No caso dos requisitos para a criação de uma linguagem, é impor- tante questionar a real necessidade dessa criação, bem como quais problemas serão resolvidos por meio dela. A expressividade irá tratar os elementos da linguagem que proverão os requisitos desejados. Da mesma forma, os paradigmas definem como resolver os problemas: algebricamente, logicamente, por uma sequência de operações, entre outros. Na implementação, é validado se os requisitos podem ser im- plementados. Por fim, esses requisitos são avaliados em sua eficiência. Além dos critérios descritos para a projeção de novas linguagens de programação, é importante entender quais os critérios relevantes para sua avaliação. Essa avaliação pode ser aplicada não apenas por progra- madores, mas também por usuários ao escolherem uma linguagem a ser estudada ou usada. Introdução a linguagens de programação 11 As linguagens de programação podem ser classificadas conforme seus níveis, isto é, níveis mais baixos e níveis mais altos interpretados pelo processador. As de baixo nível se caracterizam por um conjunto de circuitos, e as operações dos programas são controladas de forma mais primitiva, baseando-se no sistema binário de numeração para represen- tação e operação dos dados. São chamadas também de linguagens de máquina, principalmente por sua forma de representação e execução. As linguagens de alto nível são mais similares à linguagem natural, ou seja, aquela utilizada pelas pessoas na comunicação e na escrita. Po- rém adotam palavras reservadas – IF, WHILE etc. –, além de permitirem várias formas de manipulação de dados através dos tipos de dados existentes (inteiro, real, lógico etc.). Sebesta (2018) cita como critérios ou propriedades desejáveis para as linguagens de programação, independentemente de seu nível: legi- bilidade, redigibilidade, confiabilidade, eficiência, facilidade de aprendi- zado, ortogonalidade, reusabilidade, modificabilidade e portabilidade. A legibilidade de uma linguagem de programação diz respeito à facilidade da leitura e da compreensão de um programa. Quanto mais fácil o entendimento da estrutura de um programa, maior será o enten- dimento de suas instruções e, principalmente, a facilidade na correção de determinados erros. Linguagens como Basic e Fortran usavam em sua estrutura o co- mando goto 1 , que possibilitava a implementação das estruturas de se- leção e repetição. Por meio dele, tornava-se possível alternar os fluxos de comandos do programa, bem como desviar determinadas instru- ções. Porém, com o uso excessivo desse comando, a legibilidade do código tornava-se reduzida, devido à quantidade de desvios realizados. Não obstante, o uso de um mesmo vocabulário para determinar comportamentos distintos de instruções também prejudica a facilida- de de entendimento. Isso acontece na linguagem de programação Java com a utilização do comando this, o qual é usado como referência de um objeto ou como uma chamada a uma determinada função. É impor- tante observar, também, o uso de marcadores como o BEGIN-END, da linguagem Pascal, e o abre e fecha chaves { - }, da linguagem C. Esses marcadores podem causar confusões e dificultar o entendimento do programa quando, na implementação, existe uma grande quantidade O comando goto é usado em linguagem de programação para desvio de fluxos de comandos, isto é, com ele torna-se possível pular de um trecho de código para outro. 1 12 Técnicas de Programação de comandos de repetição e seleção aninhados. Isso ocorre porque a correspondência entre os marcadores torna-se difícil em relação à abertura e ao fechamento dos blocos de comandos. A redigibilidade, por sua vez, possibilita ao programador concentrar-se nos algoritmos centrais do programa, sem precisar se preocupar com as- pectos irrelevantes para a resolução do problema. Esse critério é o que mais permite diferenciar as linguagens de máquina e as linguagens de programação, pois, na primeira, era necessário que o programador se preocupasse com detalhes de implementação e, na segunda, com a des- crição do algoritmo para a resolução do problema em questão. Em determinadas linguagens de programação, como a C, a redi- gibilidade, muitas vezes, acaba sendo conflitante com a legibilidade. Isso ocorre principalmente na forma de descrever os incrementos e decrementos 2 de uma estrutura de repetição for e na utilização de ponteiros. A confiabilidade, outro item desejável em uma linguagem de pro- gramação, está relacionada à construção de programas aceitáveis e confiáveis computacionalmente. Um exemplo são as linguagens que se utilizam de declarações de tipos, ou seja, quando verificam automa- ticamente os tipos durante a compilação ou execução, as linguagens tendem a ter maior confiabilidade em relação aos erros de digitação. A eficiência relaciona-se com o tempo de execução de determinado programa. Em aplicações de automação e engenharia em tempo real, o tempo é um fator determinante, sendo necessária uma linguagem que permita maior otimização de acesso a periféricos e consumo de memória. Na atualidade, com os avanços tecnológicos de hardware e software, a eficiência torna-se responsabilidade do compilador, por meio da oti- mização automática do código. Linguagens que utilizam a verificação de tipos de dados no processo de execução tornam-se menos eficien- tes, se comparadas às que não utilizam essa requisição. Segundo o critério de facilidade de aprendizado, todo programa- dor deve ser capaz de aprender uma linguagem nova com facilidade. Nesse sentido, linguagens que necessitam de muitas características e várias formas de usar a mesma funcionalidade tornam-se mais difíceis de serem aprendidas. Além disso, nesses casos, a maioria dos usuários conhece uma parte da linguagem, dificultando o entendimento de códi- gos desenvolvidos por outros programadores ou usuários. Incrementos e decrementos em linguagens de programação são bastante usados em estruturas repetitivas como variáveis de controle. Um exemplo de um incremento, na linguagem de programação C, é c++, equivalente ao comando c:= c +1. O mesmo para o decremento, apenas diminuindo em 1 unidade. 2 Ponteiros são bastante usados em linguagens de programação estruturada, pois são variáveis que ocupam uma determinada posição de memória e, ao mesmo tempo, suportam armazenamento de ende- reços de outras variáveis. A notação para definição de uma variável do tipo ponteiro é por meio de um asterisco que traduz o que está sendo apontado, por exemplo: float *x é um ponteiro para um tipo de dado float. Saiba mais com a leitura a seguir, a partir da página 49: SAUTER, E.; AZEVEDO, F. S. de; KONZEN, P. H. de A. (orgs.). Computação científica em linguagem C: um livro colaborativo. Universidade Federal do Rio Grande do Sul, 9 jan. 2020. Disponível em: https://www.ufrgs.br/reamat/ ComputacaoCientifica/livro/livro. pdf. Acesso em: 11 mar. 2020. Saiba mais https://www.ufrgs.br/reamat/ComputacaoCientifica/livro/livro.pdfhttps://www.ufrgs.br/reamat/ComputacaoCientifica/livro/livro.pdf https://www.ufrgs.br/reamat/ComputacaoCientifica/livro/livro.pdf Introdução a linguagens de programação 13 A ortogonalidade está relacionada às combinações de conceitos básicos que o programador é capaz de criar, sem a produção de efei- tos anômalos nessa combinação. Segundo Varejão (2004), uma lingua- gem de programação é mais ortogonal quanto menor for o número de exceções aos seus padrões regulares. Outra propriedade considerada muito importante é a reusabi- lidade de código, ou seja, a possibilidade de reusar o mesmo códi- go fonte para mais de uma aplicação. Normalmente, diz-se que um código é reusável quando pode ser aproveitado em vários outros programas/códigos por meio de uma adaptação, sem a necessidade de construção do zero. Além disso, quando reusados, os códigos já foram testados e garantem menos tempo de depuração de erros. Por outro lado, a modificabilidade trata da facilidade de o pro- gramador alterar o programa em função de novos requisitos esta- belecidos no desenvolvimento. Não obstante, é necessário que essas alterações não influenciem modificações em outras partes do programa. Já a portabilidade possibilita que os programas desenvolvidos se comportem de modo independente em relação à ferramenta usada para sua tradução à linguagem de máquina ou da arquitetura com- putacional sobre a qual estão sendo executados. Entende-se, nesse contexto, que um programa pode ser usado em vários ambientes e em diferentes situações sem despender tempo de programação para reescrevê-lo ou adaptá-lo ao novo ambiente de tradução e execução. Além desses critérios, outro ponto a ser destacado ao se trabalhar com linguagens de programação são os paradigmas aos quais per- tencem. Paradigmas de programação são conjuntos de características que podem ser usados para categorizar determinado grupo de lin- guagens. São divididos em duas categorias: imperativo e declarativo. O paradigma imperativo aborda os conceitos da computação relativos às mudanças de estado, ou seja, esse paradigma foca a forma de processamento via computador de determinada funcio- nalidade/ação, através do uso de variáveis, atribuições etc. Ainda, uma vez que sua programação está vinculada a uma sequência de comandos e desvios, encontra-se nesse paradigma uma subdivi- são: paradigma estruturado, paradigma orientado a objetos (OO) e paradigma concorrente. 14 Técnicas de Programação O paradigma estruturado foi bastante usado, principalmente, para melhorar a comunicação com a linguagem de máquina, uma vez que faz uso de desvios e fluxos condicionais que possibilitam o controle da execu- ção do programa. O paradigma orientado a objetos, por sua vez, surgiu com o intuito de trazer mais rapidez ao processo de desenvolvimento de software, devido às suas características de portabilidade e reuso. No paradigma OO, o foco está na abstração de dados como ele- mentos básicos de programação, diferentemente do paradigma estru- turado, em que o foco estava nas abstrações de controle da execução dos programas. Dentre as linguagens mais conhecidas e usadas no pa- radigma OO estão a Smalltalk (totalmente OO), C++, Java, C#, VB.NET, Python, entre outras. O paradigma concorrente, última subdivisão do paradigma impera- tivo, se caracteriza por executar vários processos compartilhando recur- sos simultaneamente. Nele, são desenvolvidos sistemas que permitem compartilhar dados ou dispositivos periféricos e, para isso, são usadas as linguagens Ada e Java, por oferecerem maior suporte à concorrência. Em contrapartida ao paradigma imperativo, o paradigma declarativo é definido como as especificações sobre as quais é deter- minada a tarefa. Nesse paradigma, o programador não precisa ter co- nhecimento sobre como o computador é implementado, assim como sobre a melhor forma de realizar a tarefa. Cabe ao programador ape- nas descrever claramente a tarefa que será resolvida. O paradigma declarativo pode ser subdivido em outros dois, cha- mados de paradigmas funcional e lógico. O paradigma funcional ope- ra apenas sobre funções, que recebem listas de valores e retornam um determinado valor. Varejão (2004, p. 19) diz que esse paradigma “visa definir uma função que retorna um valor como a resposta do proble- ma”. Como exemplos desse paradigma de programação, citam-se as linguagens Lisp, ML e Haskell. Por outro lado, os paradigmas definidos como lógicos são baseados em cálculos de predicados. Nesse sentido, ao se desenvolver um pro- grama no paradigma lógico, esse é sempre composto por cláusulas que definem os predicados e as suas relações (VAREJÃO, 2004). A linguagem de programação mais conhecida, no paradigma lógico, é chamada de Prolog – bastante utilizada na construção de programas de Inteligência Artificial. Para saber mais sobre os paradigmas de programa- ção, sugere-se a leitura do capítulo 3, da obra a seguir: BARANAUSKAS, M. C. C. Procedimento, função, objeto ou lógica? Linguagens de programação vistas pelos seus paradigmas. In: VALENTE, J. A. (org.). Computadores e conhecimento: repensando a educação. 2. ed. Campinas: Unicamp, 1998, cap. 3, p. 55-76. Disponível em: https://www.nied.unicamp. br/biblioteca/computadores- e-conhecimento-repensando- educacao/. Acesso em: 5 mar. 2020. Leitura predicado: é toda a relação existente entre as constantes ou variáveis de um programa. Glossário Introdução a linguagens de programação 15 1.2 Evolução das linguagens de programação Vídeo Antes das linguagens de programação, a programação era realiza- da através da linguagem de máquina. Assim, os programadores pre- cisavam entender exatamente cada um dos comandos referentes à arquitetura da máquina para que determinada tarefa pudesse ser ini- ciada e executada. Nota-se que a quantidade de conhecimento para a programação era bastante alta, e a programação em si tornava-se pouco produtiva devido a essas dificuldades com instruções e coman- dos de máquina. Como linguagem de máquina, entende-se a representação de todas as instituições ou operações que compõem determinado programa. A base da linguagem de má- quina é o sistema binário, pois é por meio dele que o hardware do sistema entende as instruções a serem executadas. As primeiras linguagens de programação surgiram no final da dé- cada de 1950 e eram diretamente influenciadas pelas linguagens de máquina e pela arquitetura dos computadores de John Von Neumann, conforme ilustrado na Figura 1. Figura 1 Arquitetura de Von Neumann Unidade lógica e aritmética Unidade de controle Resultados de operações Instruções e dados Dispositivos de entrada e saída Memória (armazena tanto instruções quanto dados) Fonte: Sebesta, 2018, p. 39. 16 Técnicas de Programação Nessa época, o foco das linguagens era a eficiência computacio- nal devido à escassez dos recursos de memória e processamento dos computadores. As linguagens de programação mais conhecidas e usadas foram Fortran e Cobol. Para compreender a contribuição de Von Neumann às arquiteturas digitais dos computadores e aos princípios da programação, recomenda-se a leitura do artigo Von Neumann: suas contribuições à Computação, de Tomasz Kowal- towski, publicado na revista Estudos Avançados, em 1996. Acesso em: 5 mar. 2020. https://www.scielo.br/scielo.php?script=sci_arttext&pid=S0103-40141996000100022 Artigo À medida que novos recursos computacionais (hardware) eram desenvolvidos, os computadores tornavam-se mais úteis e com me- lhor desempenho na execução de suas atividades. Nesse período, as linguagens de programação começaram a ser classificadas conforme seu paradigma e eram divididas em: imperativa (estruturada, orien- tada a objetos ou concorrente) e declarativa (lógica ou funcional). Ao final da década de 1950, paralelo ao paradigma estruturado da época, criou-se o paradigma imperativo, por meio da linguagem de programação Lisp. Ao final dos anos 1960, por sua vez, as lingua- gens de programação apresentaram-semais produtivas e eficientes aos programadores, em decorrência da utilização de um paradigma estruturado, isto é, de uma linguagem de alto nível como Pascal e C. Vale ressaltar que muitas linguagens criadas nas décadas de 1950 e 1960 foram evoluindo e incorporando novas características, conforme as necessidades encontradas no desenvolvimento de pro- gramas. Assim, linguagens de programação, como Fortran e Cobol, passaram a ser usadas também no paradigma estruturado. Introdução a linguagens de programação 17 Por outro lado, com o desenvolvimento dos sistemas computa- cionais ao final da década de 1970 e início da década de 1980, as linguagens de programação apresentaram aumento em sua comple- xidade de resolução de problemas. O paradigma declarativo, com a linguagem Prolog, também era bastante utilizado na resolução de problemas que envolviam Inteligência Artificial. Nessa época, por- tanto, as linguagens de programação já permitiam o uso de modu- larizações e bibliotecas nos programas desenvolvidos, bem como já começavam a aparecer os conceitos de abstrações de dados. São exemplos de linguagens da época a Modula-2 e ADA. Por sua vez, nas décadas de 1980 e 1990, os computadores pas- saram a ser categorizados como de uso pessoal ou estações de trabalho, atingindo um número maior de pessoas. A indústria de software então começou a ser difundida, uma vez que existiam de- mandas para sua criação e manutenção. Através dessa indústria, tornou-se possível a aplicação dos conceitos de reuso de softwa- res, aplicados às linguagens de programação orientadas a objetos, como Smalltalk, Eiffel, C++ e Java. O reuso de software tornava pos- sível aumentar a produtividade e eficiência no desenvolvimento dos softwares. A partir de 2000, as linguagens de programação aderiram a um paradigma mais voltado à orientação a objetos. Expansões da lin- guagem Java foram desenvolvidas, assim como novas linguagens (Ruby, Lua, Phyton, C#...) passaram a fazer parte da vida de muitos programadores, primeiro, por suas facilidades de aprendizado e, se- gundo, por questões de desempenho nas instruções a serem execu- tadas (SEBESTA, 2018). A Figura 2, a seguir, demonstra a evolução histórica das lingua- gens, segundo o autor, e demonstra como suas expansões vêm sen- do aprimoradas a partir da década de 1950. 18 Técnicas de Programação Figura 2 Evolução histórica das linguagens de programação 1957 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 Fortran I Fortran II ALGOL 58 ALGOL 60 APL FLOW-MATIC COBOL ALGOL W ALGOL 68 Pascal MODULA-2 SIMULA 67 SIMULA I BASIC PL/I CPL LISP SNOBOL Fortran IV Prolog Fortran 77 Fortran 90 MODULA-3 Obero n Ada 83 Eiffel Per I QuickBASIC COMMON LISP Miranda ICON Haskell ANSI C (C89) Python C9 9 C# Java 5.0 Python 2.0 Python 3.0 C# 2.0 C# 3.0 C# 4.0 C# 5.0 Java 6.0 Java 7.0 Java 8.0 awk BCPL B C Scheme ML Smalltalk 80 C++ Visual BASIC Lua Ada 95 PHP Javascript Ruby Java Ruby 1.8 Ruby 1.9 Visual Basic.NE T Ada 2005 Fortran 95 Fortran 2003 Fortran 2008 Fonte: Sebesta, 2018, p. 35. Introdução a linguagens de programação 19 Na figura, nota-se que Fortran, desenvolvida por John W. Backus, em 1957, para computadores da International Business Machines Corporation (IBM) 4 , foi uma das primeiras linguagens de programa- ção criada. Apresentava como característica a eficiência computacional, pois não usava alocação dinâmica de memória. Posteriormente, nos anos 1958 e 1959, surgiram as linguagens de programação Algol e Lisp. Algol foi considerada a primeira linguagem a utilizar uma sintaxe formalmente definida. Lisp, por sua vez, criada por John McCarthy, no Massachusetts Institute of Technology (MIT), através do seu paradigma funcional e com processamento simbólico, era mais usada na área de Inteligência Artificial, assim como ocorre atualmente. A linguagem de programação Cobol, na década de 1960, foi desen- volvida para ser usada em aplicações comerciais e se caracterizava por ter muitos dados e pouca computação. Os princípios de legibilidade foram implantados em sua criação, porém acabaram afetando sua redigibilidade e comprometendo seu entendimento. No ano de 1964, na Universidade de Darmouth, foi desenvolvida a linguagem Basic por John Kemeny e Thomas Kurtz. Essa linguagem apresentava um fácil aprendizado e era muito usada por estudantes dos cursos de Ciências Humanas e Artes. Há também linguagens usadas por muitos anos, que servem como base para outras linguagens, como C e Pascal, criadas em 1971. A lingua- gem C surgiu com o propósito de ser utilizada no desenvolvimento de sistemas de programação, em particular na criação do sistema operacio- nal Unix, desenvolvido por Dennis Ritchie. A linguagem Pascal, por sua vez, foi desenvolvida para ser uma das linguagens de programação es- truturada; suas sintaxe e semântica eram bastante simples e intuitivas. Em 1973, a linguagem declarativa Prolog surgiu para ser aplicada, através do paradigma lógico, aos problemas de Inteligência Artificial. Já, em 1980, os conceitos de orientação a objetos e as interfaces gráficas de usuários (GUI) começaram a ser inseridos por meio da linguagem Smalltalk, criada por Alan Key e Adele Goldberg. A linguagem Ada surgiu para atender às demandas de uma lingua- gem de programação de alto nível, em 1983. Era bastante complexa e apropriada para a programação concorrente e sistemas de tempo real. Continuando com a orientação a objetos, em 1985, a linguagem C++, projetada para ser uma expansão da linguagem C, foi desenvolvi- JavaScript é uma lingua- gem de programação que permite implementar itens complexos em páginas web. É utilizada sempre que uma página web faz mais do que sim- plesmente mostrar uma informação estática, com conteúdo que se atualiza a cada intervalo, mapas interativos ou gráficos 2D/3D animados etc. Saiba mais em: https://developer. mozilla.org/pt-BR/docs/Learn/ JavaScript/First_steps/O_que_e_ JavaScript. Acesso em: 12 mar. 2020. Curiosidade A IBM, empresa dos Estados Unidos atuante na área da tecnologia da informação, é re- conhecida por sua longa história iniciada desde 1911. Atualmen- te, desenvolve e comercializa hardware e software. 4 20 Técnicas de Programação da por Bjarne Stroustrup. Foi através dessa linguagem que a orientação a objetos passou a ser aceita no mercado. Na sequência, a linguagem Java passou a ser adotada, em 1995, na construção de sistemas de controle embutido, embora seu fim tenha sido diretamente aplicado a sistemas corporativos e comerciais. Sua base de criação foi a linguagem C++ e apresentava muita confiabilidade e portabilidade, principalmente pelo uso da Internet já neste período. Após o surgimento da linguagem Java, outras linguagens como Lua, PHP e Ruby foram desenvolvidas. Lua, por ser uma linguagem de script, possibilita maior integração com aplicações industriais e outros tipos de linguagens – uma delas é a Ruby, por exemplo, considerada uma linguagem interpretada multiparadigma e de tipagem dinâmica. Já a linguagem PHP é bastante atuante no desenvolvimento de aplicações com conteúdos dinâmicos na web, ao lado do servidor. Nota-se que, com o passar dos anos, principalmente após 2000, poucas foram as linguagens criadas. Surgiram, sim, expansões e me- lhorias das linguagens já existentes, tais como Java 6 – 7, entre outras. Assim, dentro do leque de linguagens de programação existentes, é necessário o entendimento do programa a ser desenvolvido para, então, escolher qual melhor paradigma e linguagem a serem usados. A linguagem de programação Lua é bastante usada no desenvolvimento de jogos. Por ser baseada em scripts, traz benefícios na criação do script do jogo. Para saber mais, recomenda-se ler: https://www. lua.org/doc/wjogos04.pdf. Acesso em: 6 mar. 2020. Saiba mais 1.3 Razões para estudarlinguagens de programação Vídeo As linguagens de programação devem servir para que o trabalho dos programadores seja realizado de modo mais produtivo e eficaz. Assim, entende-se que, através das linguagens de programação, o pro- cesso de desenvolvimento de software torna-se mais efetivo e produ- tivo, uma vez que possibilita aos programadores e demais envolvidos uma padronização de desenvolvimento e fácil manutenção dos pro- gramas quando necessário. Nesse sentido, entende-se que essas lin- guagens são fundamentais dentro da sua especialidade e vários são os benefícios de estudá-las. Varejão (2004, p. 3) cita como razões para o estudo das linguagens de programação: • Maior capacidade de desenvolver soluções computacionais para problemas. Introdução a linguagens de programação 21 • Maior habilidade ao usar uma linguagem de programação. • Maior capacidade para escolher linguagens de programação apropriadas. • Maior habilidade para aprender novas linguagens de programação. • Maior habilidade para projetar novas linguagens de programação. A capacidade de desenvolver soluções computacionais ou, como afirma Sebesta (2018), de aumentar a expressão de ideias é decorrente da compreensão e profundidade intelectual utilizadas na comunicação. Isso implica dizer que quanto menor as limitações de pensamento, maior será a facilidade de abstração e interpretação de problemas do mundo real para o mundo computacional. Em relação às habilidades adquiridas, ao se utilizar uma linguagem de programação, é importante frisar que quanto mais experiência o programador adquirir no processo de desenvolvimento, maior será sua capacidade na construção de códigos-fonte com modularização, recursividade e outros recursos que a maioria dos programadores ex- perientes adota para melhor desempenho do código. Assim, esse benefício acaba auxiliando na escolha de linguagens de programação apropriadas para a resolução de determinados pro- blemas. Em muitos casos, quando lhes é permitido escolher qual lin- guagem utilizar em um novo projeto de criação, os programadores continuam a usar aquela com a qual estão mais acostumados, mesmo que seja pouco adequada à necessidade. Diante disso, entende-se que quanto mais os programadores estiverem familiarizados com outros tipos de linguagem, mais acertada será a escolha. Sobre o uso do paradigma de orientação a objetos, os programado- res que já dominam seus conceitos são capazes de aprender, mais rapi- damente, outras linguagens nesse mesmo formato. Além disso, segundo Sebesta (2000 apud SCHÜTZ, 2003, p. 2), “programadores que entendem o conceito de abstração de dados terão mais facilidade para aprender como construir tipos de dados abstratos em Java do que aqueles que não estão absolutamente familiarizados com tal exigência”. Ainda, para o autor, é primordial que os programadores saibam o vocabulário e os conceitos fundamentais das linguagens, pois, assim, é possível ler e entender os manuais e sua literatura de venda de lingua- gens e de compiladores (SEBESTA, 2018, p. 17). 22 Técnicas de Programação Outro ponto a ser destacado é a possibilidade de participação ou de criação de uma nova linguagem de programação de propósito geral. Ao se desenvolver as interfaces gráficas com o usuário de sistemas, por exem- plo, muitas vezes, é necessário projetar e implementar uma linguagem de comandos para comunicação entre os envolvidos – no caso, o usuário e o sistema. Dessa forma, o conhecimento das linguagens de programação tanto por parte dos programadores como dos usuários torna-os mais ca- pazes de entender e utilizar os recursos disponíveis. Sugere-se a leitura do artigo Análise comparativa de linguagens de programação, dos autores Rodrigo Duarte Seabra, Isabela Neves Drummond e Fernando Coelho Gomes, publicado em 2018, na Revista de Sistemas e Computação, que trata sobre uma análise comparativa das linguagens de programação em relação aos seus paradigmas, a partir de problemas clássicos da área. Acesso em: 6 mar. 2020. https://revistas.unifacs.br/index.php/rsc/article/download/5133/3488 Artigo Além das cinco razões para o estudo das linguagens de progra- mação citadas por Varejão (2004), outras duas são apresentadas por Sebesta (2018), a saber: entender melhor a importância da implemen- tação e o avanço global da computação. A primeira pode ser aborda- da pelo princípio de que o aprendizado dos conceitos de programação é fundamental e necessário para discutir as questões envolvidas em suas implementações. Outro ponto a destacar por agregar esse conhe- cimento é que determinados erros de programação somente são iden- tificados e corrigidos por programadores que dominam os detalhes da linguagem. Programadores que pouco sabem a respeito de recursão, por exemplo, não imaginam que um algoritmo recursivo é muito mais lento do que um interativo equivalente. A segunda razão, sobre o avanço global da computação, envolve assumir que nem sempre é possível entender e identificar que as lin- guagens de programação mais populares são as melhores disponíveis. Muitos usuários, por exemplo, acreditam que seria melhor que a lin- guagem Algol 60 tivesse substituído a Fortran na década de 1960, devi- do à sua elegância e ao melhor controle de suas instruções. De modo geral, se os programadores forem mais bem informados, maior será a probabilidade de escolherem, para seu projeto, melhores linguagens sobrepostas às linguagens ruins. recursividade: “recursividade ou função recursiva significa a invocação de si mesmo. Ou seja, é uma função que após executar o seu bloco de instrução invoca a si mesma novamente” (RECURSIVIDADE..., 2020). Glossário Introdução a linguagens de programação 23 1.4 Tradutores de linguagens de programação Vídeo Os tradutores de linguagens de programação são fundamentais no desenvolvimento de um programa. Isso porque a linguagem escolhida pelo programador, independentemente de qual seja, geralmente precisa ser traduzida para uma linguagem de máquina e, consequentemente, ser entendida e executada pelo computador. A transformação de uma lingua- gem de programação em linguagem de máquina acontece pela submissão do código-fonte desenvolvido para tradução. Posteriormente, esse código é transformado em linguagem de máquina, possibilitando o entendimen- to, por parte do computador, das instruções que precisam ser executadas. A forma como os programas serão implementados nas linguagens de programação está relacionada à determinação do programa tradutor, isto é, como o código-fonte traduzido se comportará efetivamente quando executado no computador. Para Sebesta (2018), os métodos de imple- mentação e tradutores de linguagens de programação são divididos em: compilação, interpretação pura e sistemas de implementação híbridos. Programa-fonte Analisador léxico Unidades léxicas Árvores de análise sintática Código intermediário Linguagem de máquina Dados de entrada Resultados Analisador sintático Analisador sintático Gerador de código Computador Otimização (opcional) Tabela de símbolos Figura 3 Processo de compilação Fonte: Sebesta, 2018, p. 47. 1.4.1 Compilação O método de compilação consiste no processo em que os programas são traduzidos para a linguagem de máquina e, então, executados diretamente no computador. Esse método realiza a tradução integral do programa-fonte ou código-fonte para o código da máquina, de modo que o programa passa a ser exe- cutado diretamente após esse processo. Segundo Sebesta (2018), o processo de compila- ção e a execução do programa ocorrem em fases di- ferentes, conforme ilustrado na Figura 3. As principais fases do processo de compilação são analisador léxico, analisador sintático e gerador de código. O primeiro é responsável por verificar os caracteres escritos no código-fonte e transformá- -los em unidades léxicas, que são representados por identificadores, palavras reservadas, operadores e símbolos de pontuação usados na linguagemde pro- gramação. Além disso, os comentários existentes no código-fonte são ignorados nesta fase. 24 Técnicas de Programação O analisador sintático, segundo Branco e Tamae (2008, p. 3), “é responsável por verificar se a sequência de símbolos contida no código-fonte compõe um programa válido ou não”. O gerador de código intermediário, por sua vez, “é responsável por gerar uma representa- ção intermediária ao código final, a partir da árvore sintática e da tabela de símbolos, tal que essa representação se aproxime do código-alvo” (FOLEISS, 2009, p. 17). A vantagem desse método é a otimização da eficiência na execu- ção dos programas. A velocidade na execução é decorrente das veri- ficações de erro serem efetuadas durante a tradução do programa. O tradutor também apresenta maior autonomia para trazer otimizações na geração dos códigos executáveis, pois considera o código-fonte de forma global. Além disso, quando se trata do método de compilação também é possível que um código seja executado apenas com o seu executável, ou seja, não é necessário que o código-fonte do programa esteja junto para funcionamento. No entanto, a execução de um programa apenas por um código executável pode apresentar desvantagens, pois nem sempre será compatível com a plataforma, arquitetura de hardware, que irá exe- cutá-lo. Caso o programador tenha escrito um programa em linguagem C, e esse código tiver sido compilado em um ambiente de software livre, sistema operacional Linux, pode não ocorrer a sua execução em um am- biente proprietário, sistema operacional Windows, ou vice-versa. 1.4.2 Interpretação pura Na interpretação pura, um programa interpretador age como si- mulador de um computador virtual que compreende as instruções da linguagem de programação. Assim, cada instrução do código-fonte é traduzida para a linguagem de máquina para ser executada. Posterior- mente, a tradução do código é executada. Nesse método, em comparação à compilação, as traduções e execu- ções dos programas interpretados ocorrem de forma única, e não em fases separadas. Essa interpretação é a única possibilidade de maior facilidade na prototipação, pois todas as mensagens de erro podem referenciar unidades de código-fonte. Outras vantagens desse méto- do são as facilidades da depuração e escrita de programas flexíveis. A Figura 4 ilustra esse método: Introdução a linguagens de programação 25 Figura 4 Processo de interpretação pura Programa-fonte Interpretador Dados de entrada Resultado Fonte: Sebesta, 2018, p. 49. Nota-se, na Figura 4, que o programa-fonte submete os dados de entrada, inseridos pelo usuário, para que o interpretador realize as validações de sintaxe dos comandos e, então, apresente o resultado do processamento do código-fonte. Entre as desvantagens do método de interpretação pura há a ve- locidade de execução do programa. Esse problema é decorrente da necessidade de o interpretador decodificar determinados comandos complexos, verificando os possíveis erros e aumentando o consumo de memória. 1.4.3 Sistemas de implementação híbridos Para Sebesta (2018), vários sistemas de implementação híbridos são uma junção entre a compilação e interpretadores puros. Nesse método, é feita uma tradução dos programas em linguagem de alto nível para uma linguagem intermediária criada a fim de facilitar a interpretação. No método de sistemas de implementações híbridas, são con- sideradas duas etapas: compilação para o código intermediário e interpretação do código. Sobre elas, Varejão (2004, p. 16) explica: a interpretação do código intermediário é muito mais rápida que a interpretação pura do código-fonte, porque as instruções 26 Técnicas de Programação do código intermediário são muito mais simples que as do códi- go-fonte e porque a maior parte das verificações de erro é reali- zada já na etapa de compilação... Como o código intermediário não é específico para uma plataforma, os programas já compi- lados para esse código podem ser portados para as mais dife- rentes plataformas sem necessidade de adaptação ou mesmo recompilação, bastando que exista um interpretador do código intermediário instalado na plataforma em que se deseja execu- tar o programa. Para melhor entendimento de como funcionam esses sistemas, pode-se considerar o fato de que as primeiras implementações de Java eram todas híbridas. O formato intermediário bytecode permite maior portabilidade para qualquer máquina que tenha um interpre- tador de bytecodes e um sistema de tempo de execução associado. A figura a seguir ilustra esse raciocínio: Figura 5 Sistemas de implementação híbridos Programa-fonte Resultado Unidades léxicas Árvores de análise sintática Código intermediário Dados de entrada Analisador léxico Analisador sintático Gerador de código intermediário Interpretador Fonte: Adaptada de Sebesta, 2018, p. 50. A figura mostra o funcionamento de um sistema de implementação híbrido, onde o código-fonte é submetido ao analisador léxico que ve- rifica a sintaxe da linguagem de programação e cria unidades léxicas para os caracteres escritos no código. Posteriormente, essas unidades são submetidas ao analisador sintático que a representa através de uma árvore de análise sintática para, então, através do gerador de códi- go intermediário, ser criado um código reconhecido pelo interpretador para a leitura dos dados e o processamento deles. Nesse sentido, toda plataforma computacional necessita ter a sua própria máquina virtual Java para que a execução do programa seja realizada. Introdução a linguagens de programação 27 CONSIDERAÇÕES FINAIS As linguagens de programação encontram-se presentes no cotidiano, seja através dos softwares utilizados na realização de determinadas tare- fas no computador ou em programas embutidos em aparelhos eletroele- trônicos ou industriais. Embora tenham surgido há décadas e sido classificadas em vários pa- radigmas, nota-se que determinadas linguagens de programação apre- sentaram maior aderência e aplicabilidade do que outras. Essa aderência esteve muito relacionada às qualidades de cada linguagem, isto é, progra- madores têm buscado linguagens que apresentem maior portabilidade, flexibilidade, reusabilidade e outras características impactantes nos siste- mas computacionais utilizados por diversos tipos de usuários e sistemas operacionais. Além disso, com a evolução tecnológica dos hardwares, torna-se possível expandir as linguagens de programação existentes, pois o pro- cessamento e desempenho dos processadores possibilitam mais inde- pendência em relação aos seus métodos de implementações e aos seus tradutores para a linguagem de máquina. Diante disso, os ambientes de programação são fundamentais para os sistemas de desenvolvimento de software, nos quais a linguagem de programação é um dos componentes do processo. ATIVIDADES 1. Qual é a importância da linguagem de programação para o desenvol- vimento de um programa? 2. Quais são as razões para se estudar as linguagens de programação? 3. Descreva a diferença entre os paradigmas declarativo e imperativo. 4. Quais são os métodos de implementação das linguagens de progra- mação? REFERÊNCIAS BRANCO,@dia, G. A. Jr.; TAMAE, R. Y. Uma breve introdução ao estudo e implementação de compiladores. Revista Científica Eletrônica de Psicologia, ano V, n. 8, fev. 2008. Disponível em: http://faef.revista.inf.br/imagens_arquivos/arquivos_destaque/ RHXqIjJHvJQhhCK_2013-5-28-11-13-48.pdf. Acesso em: 13 mar. 2020. DE MELO, A. C. V.; DA SILVA, F. S. C. Princípios de linguagens de programação. São Paulo: Editora Blucher, 2003. 28 Técnicas de Programação FOLEISS, J. H. et al. SCC: um compilador C como ferramenta de ensino de compiladores. In: Workshop sobre Educação em Arquitetura de Computadores – WEAC 2009, p. 15-22. Disponível em: http://docplayer.com.br/37006644-Scc-um-compilador-c-como- ferramenta-de-ensino-de-compiladores.html. Acesso em: 13 mar. 2020. RECURSIVIDADE. eXcript: dicionáriotécnico de programação. Disponível em: http://excript. com/dicionario/indice.html. Acesso em: 12 mar. 2020. SEBESTA, R. W. Conceitos de linguagens de programação. 4. ed. Porto Alegre: Bookman, 2000. In: SCHÜTZ, F. Programação orientada a comportamentos baseada no modelo de atores. Florianópolis, 2003. 90f. Dissertação (Mestrado em Ciência da Computação) – Centro Tecnológico, Universidade Federal de Santa Catarina. Disponível em: https://repositorio. ufsc.br/xmlui/handle/123456789/86260. Acesso em: 6 mar. 2020. SEBESTA, R. W. Conceitos de linguagens de programação. 11. ed. Porto Alegre: Bookman, 2018. VAREJÃO, F. M. Linguagem de programação: conceitos e técnicas. Rio de Janeiro: Elsevier, 2004. Desenvolvendo um programa 29 2 Desenvolvendo um programa Você já percebeu que, a cada dia, o número de aplicativos para celular ou computadores aumenta exponencialmente? Esses aplicativos também podem ser definidos como progra- mas, os quais são um conjunto de instruções e comandos exe- cutado logicamente em um determinado computador, para um fim específico. Para que um programa possa ser executado em alguma máquina, é necessário que a linguagem de programação esco- lhida cumpra uma sequência de etapas ou fases. Por exemplo, é preciso ter uma sintaxe de fácil compreensão, assim como a semântica suportar vários tipos de dados, estruturas básicas de desenvolvimento, entre outros conceitos e métodos de imple- mentação imprescindíveis a uma linguagem de programação. Além disso, outro ponto importante ao desenvolver um pro- grama diz respeito à manipulação de dados. Na operação de algum programa, vários tipos de dados são inseridos e a lingua- gem de programação adotada deve suportar essa diversidade para garantir uma boa computação deles. Entende-se que a tarefa de um desenvolvedor de linguagem de programação não é trivial, bem como a de um utilizador de linguagem de programação. Nesse sentido, é importante que todo e qualquer programa, independentemente de sua lingua- gem, seja construído de maneira clara, objetiva e concisa para sua utilização por todos os envolvidos. 30 Técnicas de Programação 2.1 Análise léxica e sintática Vídeo O entendimento de conceitos como análise léxica e sintática é de suma importância na construção de um programa, independentemente de sua linguagem de programação. Você já ouviu falar deles? Caso não, vale destacar que toda linguagem de programação apresenta uma descrição vista sob dois aspectos: sintaxe e semânti- ca. A sintaxe pode ser entendida como um conjunto de regras que permite identificar quais construções são corretas, enquanto a se- mântica trata de como as construções da linguagem devem ser exe- cutadas e interpretadas. Sebesta (2018) afirma que os maiores problemas encontrados na descrição sintática e semântica de uma linguagem de programação es- tão relacionados à quantidade de pessoas que utilizarão essa lingua- gem e quais serão seus entendimentos sobre ela. Figura 1 Sintaxe e semântica de uma linguagem de programação ph ot ov ib es /S hu tte rs to ck Nesse contexto, é importante que os usuários das linguagens de programação, para criar seus programas, entendam-nas quan- do consultarem seus manuais de referência. Por isso, é preciso que os conceitos de sintaxe e semântica sejam bem definidos e compreendidos. Desenvolvendo um programa 31 Para Sebesta (2018), a sintaxe de uma linguagem de programação é a forma de suas expressões, instruções e unidades de programa- ção. Por sua vez, a semântica é entendida como o significado dessas expressões, instruções e unidades de programação. Ambos os termos estão diretamente relacionados e, quando bem projetada a lingua- gem de programação, a semântica segue a sintaxe. Um exemplo é a expressão escrita na linguagem Pascal: x:=y Vê-se que a sintaxe é responsável por verificar se o comando de atri- buição está correto, e a semântica por realizar a substituição do valor de x pelo valor de y. Outro exemplo, na linguagem C, é descrito no comando de uma es- trutura de seleção da linguagem: if (<expressão>) <instrução> Novamente, a sintaxe verifica se o comando está correto, e a semân- tica analisa o valor da expressão – se verdadeiro, a instrução/comando é selecionada para a execução. Ainda pensando no desenvolvimento de um programa, veja o tre- cho de um código-fonte e como a busca por erros sintáticos é realizada por um compilador ou interpretador: Figura 2 Trecho de código-fonte desenvolvido em linguagem de programação C 1. int x=0, aux, A [4]; float y#; 2. aux = ‘0’ 3. for (x=0, x<4; x++ 4. { 5. A[x] = aux++; 6. } Fonte: Elaborada pela autora. Quando um código é elaborado, a responsabilidade de um compi- lador é apontar os erros encontrados na linguagem de programação, isto é, os comandos que não representam corretamente a sintaxe da linguagem adotada. Na Figura 2, vê-se que, durante a análise da com- pilação, os seguintes erros foram identificados em relação a problemas de léxico, sintaxe e semântica: compilador: “é o programa de sistema que traduz um programa descrito em uma linguagem de alto nível para um programa equivalente em outra linguagem, como o código de máquina para um processador”. (RICARTE, 2008, p. 8) Glossário 32 Técnicas de Programação • Em relação à análise léxica, foi percorrido o trecho de código e analisado os vocabulários (x, y, for, =, (, <, int, ++, aux, A []). Erro léxico foi identificado na variável y#. • Na análise sintática, são verificadas as combinações dos tokens que formam o programa, por exemplo, o comando for → for (expr1; expr2; expr3) {comandos}. Na linguagem de programação C, o comando for precisa respeitar uma sintaxe para que o compilador entenda o que faz parte do vocabulário da linguagem, como as expressões utilizadas nas estruturas de repetição. • No exemplo, os erros são apontados em relação à estrutura do comando ; for(x=0,... ), uma vez que as expressões pre- cisam estar dentro de parênteses e separadas por ponto e vír- gula. Como observa-se na Figura 2, terceira linha, não existe um fechamento de parênteses e as expressões estão separadas por vírgula e ponto e vírgula. • Já a análise semântica do trecho de código apresentado busca os tipos semelhantes em comandos com, por exemplo, a atribuição e seus respectivos identificadores declarados. Na situação em questão, erros não foram encontrados, pois a semântica estava coerente com o especificado. Sebesta (2018) defende que a análise léxica deve ser separada da análise sintática por razões de simplicidade, eficiência e portabilidade. A simplicidade é decorrente de as técnicas de análise léxica serem mais fáceis, se comparadas à análise sintática, de modo que mantê-las divididas é mais viável. Além disso, quando detalhes de baixo nível são removidos de um analisador léxico, este se torna menor e mais limpo de se utilizar. Já a eficiência trata da otimização do analisador léxico, que necessi- ta de uma grande quantidade de tempo de compilação, tornando inviá- vel a sua otimização. A portabilidade, por sua vez, aborda os arquivos de entrada lidos, de maneira que o analisador sintático seja indepen- dente da plataforma. Pode-se dizer que a análise léxica é uma junção de padrões, tam- bém chamada de casamento de padrões, em que o analisador léxico tenta encontrar uma subcadeia de caracteres idêntica ao padrão in- formado. O casamento de padrões vem sendo usado há muitos anos, Sugere-se conhecer a dissertação de Diego Roberto Gonçalves de Pontes, intitulada Geração de rótulo de privacidade por palavras-chaves e casamento de padrões (2016), que “discute como o conteúdo das políticas de privacidade pode ser apresentado de maneira mais sintética para o usuário, com as informações sobre a coleta e a utilização dos dados sendo exibidas em uma tabela, denominada Rótulo de Privacidade”. São Carlos, 2016. Universidade Federal de São Carlos. Disponível em: https://repositorio. ufscar.br/bitstream/handle/ufscar/8730/DissDRGP. pdf?sequence=1&isAllowed=y. Acesso em: 17 abr. 2020. Leitura Desenvolvendo um programa 33 tendo sua primeira aplicabilidade nos editores de texto chamados ed, introduzidos no sistema operacional UNIX. Um analisador léxico é sempre utilizado em conjunto com um ana- lisador sintático. O primeiro realiza uma varredura na análise sintática de todo o programa desenvolvido e, então, um programa de entrada para um compilador surge com uma única cadeia de caracteres. 2.2 Nomes e variáveis Vídeo No desenvolvimento de um programa, vale destacar a importância dos nomes e das variáveis utilizados no código-fonte. Os nomes dos atributos são características das funcionalidades do programa. Por exemplo, se o programa em desenvolvimento trata de um cadastro de clientes de um departamento, atributos como nome_funcionario, endereço, cidade e telefone são necessários. O fato de adotar nomes representativos às atividades que serão realizadas permite que outro desenvolvedor entenda não somente a sintaxe, mas, também, a se- mântica do programa e o raciocínio do programador. Em linguagens de programação, para nomes é atri- buído um uso mais amplo do que simplesmente o nome dado a uma variável. Associam-se nomes a rótu- los, rotinas, parâmetros formais e outras construções necessárias ao desenvolvimento do programa. As primeiras linguagens de programação adota- vam como nomes apenas um caractere. Isso porque elas se baseavam em equações matemáticas que usavam apenas um caractere para representar as notações formais, como x, y, a, b. Com o tempo, porém, os nomes passaram a ser compostos por uma cadeia com um limite longo de caracteres, adicio- nando sublinhados (_) que representam os espaços em branco na es- crita da língua portuguesa. Hoje, as linguagens de programação possibilitam maior concate- nação e conexões entre os nomes usados – inclusive, algumas delas fazem distinção entre letras maiúsculas e minúsculas na definição do nome. Além disso, a mudança da linguagem de máquina para as lin- nome: cadeia de caracteres utilizada para identificar uma entidade de um programa. Glossário Dependendo da nomenclatura adotada ou do autor usado como referencial, vê-se que o termo nome é associado com o identificador. Curiosidade 34 Técnicas de Programação guagens atuais se caracteriza pela substituição dos endereços numéri- cos de memórias por nomes, tornando as linguagens mais legíveis, de fácil entendimento e escrita. Como exemplo, tem-se os seguintes nomes: Contador, contador, CONTADOR. Os três são entendidos de modo diferente pelo compilador adotado na linguagem de programação C++ e, para alguns autores, essa diferenciação é vista como um grande proble- ma de legibilidade. Algumas linguagens permitem que seus nomes sejam declarados com essa distinção, enquanto outras utilizam as duas formas de nomes predefinidos, como é o caso da linguagem Java. Dessa forma, algumas regras são criadas para o uso de nomes, de modo que respeitem as palavras especiais da linguagem. Estas são usadas para definir as palavras reservadas, ou seja, aquelas emprega- das para tornar os programas legíveis ao dar nome às ações a serem executadas. Assim, segundo Sebesta (2018, p. 178), “uma palavra reservada é especial e não pode ser usada como um nome”. Alguns exemplos de palavras reservadas são ilustrados no Quadro 1. Quadro 1 Exemplos de palavras reservadas if for while repeat int float struct boolean caractere Fonte: Elaborado pela autora. Nesse sentido, os nomes são utilizados para representar uma va- riável no desenvolvimento de um programa. As variáveis são com- postas por nome, endereço, tipo, valor, tempo de vida e escopo de visibilidade. Os nomes das variáveis são, geralmente, atribuídos pelo programa- dor e são representativos para o entendimento do problema. Ao dar nomenclatura a uma determinada variável, regras precisam ser segui- das, tais como: Desenvolvendo um programa 35 • Não deve iniciar com número. • Não deve ter caracteres especiais { ( + - * / \ ; . , ? . • Não deve apresentar espaços em branco. • Não pode usar hífen ou acentuação. • Pode conter letras maiúsculas, minúsculas, números, subscrito ou underline (_). O Quadro 2 ilustra nomes válidos e inválidos para serem atribuídos a uma variável. Quadro 2 Exemplos de nomes válidos e inválidos de variáveis Nomes válidos Nomes inválidos Nota 1Nota nota_1 nota 1 email @e-mail Cadastro1 Cadastro1º Endereco endereço Fonte: Elaborado pela autora. O endereço da variável é sua posição na memória da primeira cé- lula ocupada pela variável. A variável de nome cidade, por exemplo, ocupa a primeira célula do endereço de memória FF00. O tipo de dado de uma variável especifica o conjunto de valores que ela pode assumir – se for um número decimal, por exemplo, será atribuído à variável um tipo de dado inteiro. Já o valor de uma variável pode ser alterado à medida que ela é atua- lizada. Em outras palavras, uma variável pode iniciar a sua execução com um determinado valor e, conforme as instruções/comandos do programa forem executadas, esse valor pode ser alterado. O tempo de vida de uma variável corresponde ao período de sua existência e está diretamente relacionado ao tempo em que há células de memória alocadas na variável. Assim, o tempo de vida é diferente quando as variáveis são globais ou locais. valor: termo usado como representação de valores. Em linguagens de programação, valores significam que estão sendo representados dados. Glossário 36 Técnicas de Programação Para uma variável global, o tempo de vida é todo o período de execução do programa em que foi declarada. Em contrapartida, em variáveis locais, o tempo de vida corresponde ao período em que o bloco de comando no qual as variáveis foram declaradas é executado. Já o escopo de visibilidade descreve o trecho do programa em que a variável foi referenciada. Outro aspecto importante a destacar no uso de variáveis é que, em determinadas circunstâncias, valores precisam ser armazena- dos, e não alterados, durante a execução da computação. Para isso, são utilizadas as constantes, entidades de programas para guardar esses valores. Um exemplo de constante é o pi, que sempre apre- senta o valor de 3,1415. As constantes são valores predeterminados que devem aparecer dentro de um programa. Como as variáveis, as constantes são com- postas por nome, endereço, valor, tipo, tempo de vida e escopo de visibilidade. Podendo ser definidas na própria linguagem de programação, ou então criadas pelo usuário ou programador, o que diferencia as constantes é o fato de que, quando predefinidas, são referenciadas por símbolos ou identificadores associados aos valores dos tipos de dados da linguagem de programação. Por sua vez, quando definidas pelos usuários, as declarações precisam ter um nome associado ao programa (VAREJÃO, 2004). É importante esclarecer que as constantes declaradas pelos usuários tornam-se mais legíveis e permitem maior modificabilida- de ao programa. 2.3 Tipos de dados Vídeo Em linguagens de programação, os tipos de dados são fundamen- tais, pois possibilitam a representação de valores nos códigos pro- duzidos. Nesse sentido, cada linguagem adota um conjunto próprio de tipos e valores que permite a representação dos dados utilizados. É importante não confundir escopo de visibilidade de uma variável com seu tempo de vida. Varejão (2004, p. 86) afirma que, “em determinadas situações, uma variável pode estar alocada num ponto de execução do programa, mas não ser acessível naquele ponto”. Atenção Desenvolvendo um programa 37 Nesse contexto, é válido questionar: como define-se um valor? Tudo que se avalia durante o processo de computação pode ser entendido como um valor, ou seja, o que for armazenado, ou incorporado a uma estrutura de dados do programa, ou então passado como argumento para uma função ou um procedimento, entre outros. Alguns exemplossão apresentados na Tabela 1. Tabela 1 Exemplos de valores na linguagem de programação C 21 3.98 029 “Joao” ‘s’ 0x1F Fonte: Elaborada pela autora. Todo valor é acompanhado de um respectivo tipo de dado, isto é, de um conjunto de valores que exibe comportamento uniforme nas ope- rações associadas com o tipo de dado. Por exemplo, {true, false} representa um tipo de dado chamado booleano, de cardinalidade 2, pois o número de tipos existentes nele é apenas 2. Assim, ao utilizar uma linguagem de programação, sempre é im- portante compreender seus tipos de dados e, principalmente, a fai- xa de valores que esses tipos assumem. Da mesma forma, importa compreender as operações definidas para os valores desses respec- tivos tipos. Para melhor entender como esse processo funciona, inicialmente, é preciso refletir sobre as duas categorias nas quais os tipos de dados são divididos e quais os aspectos sintáticos e semânticos de cada um deles – a saber: primitivos e compostos. Para cada uma dessas catego- rias, outras subcategorias são identificadas para melhor uso de valores e operações entre os valores. 2.3.1 Tipos primitivos Os tipos primitivos, também chamados de atômicos, são os valores que não podem derivar outros valores de tipos mais simplificados. São norteadores das linguagens de programação, pois servem como base para a definição de novos tipos a serem construídos. 38 Técnicas de Programação Considerando que os primitivos são definidos na implementa- ção de uma linguagem de programação, determinadas limitações de hardware podem impactar nesse processo. Um exemplo dessa variação é verificado na linguagem de programação C, em que, para as variações de hardware de 16, 32 ou 64 bits, o tipo int modifica a sua faixa de valores ou intervalo. Esses tipos podem ser classificados em: inteiro, caractere, booleano, decimal, ponto flutuante, enumera- do e intervalos inteiros. Um tipo inteiro ou numérico corresponde a um intervalo do con- junto dos números inteiros. Normalmente, em uma linguagem de programação, existem vários inteiros, decorrentes das operações que podem ser fornecidas em relação ao hardware da máquina uti- lizado no desenvolvimento do programa. Na linguagem de programação Pascal, um exemplo do uso de tipos de dados inteiros e decimais é: var x: integer; y: float; Percebe-se que x e y são as variáveis declaradas com os respectivos tipos de dados numéricos. Na linguagem de programação C, os tipos são enunciados sempre à frente do nome da variável, como pode ser visto no exemplo: int x, y; Outro tipo de dado primitivo bastante usado nas linguagens de pro- gramação é conhecido como não numérico. Ele trata de representar valores que não são numéricos, como é o caso do tipo booleano e do caractere. Valores de tipo caractere são armazenados como códigos numéri- cos, porém algumas linguagens de programação adotam um tipo pri- mitivo no qual os valores correspondem aos símbolos de uma tabela padrão de caracteres. No caso da linguagem Pascal, o tipo caractere é oferecido como sendo char. Tabelas com códigos numéricos para caracteres podem ser vistas pelo padrão ASCII e UNICODE. A mais utilizada para padronização de valores é a ASCII, conforme vê-se a seguir: Desenvolvendo um programa 39 Tabela 2 Tabela ASCII padrão De c He x Oc t Ch r De c He x Oc t HT M L Ch r De c He x Oc t HT M L Ch r De c He x Oc t HT M L Ch r 0 0 00 0 N U LL 32 20 04 0 & #0 32 ; Sp ac e 64 40 10 0 & #0 64 ; @ 96 60 14 0 & #0 96 ; ` 1 1 00 1 St ar t o f H ea de r 33 21 04 1 & #0 33 ; ! 65 41 10 1 & #0 65 ; A 97 61 14 1 & #0 97 ; a 2 2 00 2 St ar t o f T ex t 34 22 04 2 & #0 34 ; “ 66 42 10 2 & #0 66 ; B 98 62 14 2 & #0 98 ; b 3 3 00 3 En d of T ex t 35 23 04 3 & #0 35 ; # 67 43 10 3 & #0 67 ; C 99 63 14 3 & #0 99 ; c 4 4 00 4 En d of Tr an sm is si on 36 24 04 4 & #0 36 ; $ 68 44 10 4 & #0 68 ; D 10 0 64 14 4 & #1 00 ; d 5 5 00 5 En qu iry 37 25 04 5 & #0 37 ; % 69 45 10 5 & #0 69 ; E 10 1 65 14 5 & #1 01 ; e 6 6 00 6 Ac kn ow le dg m en t 38 26 04 6 & #0 38 ; & 70 46 10 6 & #0 70 ; F 10 2 66 14 6 & #1 02 ; f 7 7 00 7 Be ll 39 27 04 7 & #0 39 ; ‘ 71 47 10 7 & #0 71 ; G 10 3 67 14 7 & #1 03 ; g 8 8 01 0 Ba ck sp ac e 40 28 05 0 & #0 40 ; ( 72 48 11 0 & #0 72 ; H 1 04 68 15 0 & #1 04 ; h 9 9 01 1 H or iz on ta l T ab 41 29 05 1 & #0 41 ; ) 73 49 11 1 & #0 73 ; I 10 5 69 15 1 & #1 05 ; i 10 A 01 2 Li ne fe ed 42 2A 05 2 & #0 42 ; * 74 4A 11 2 & #0 74 ; J 10 6 6A 15 2 & #1 06 ; j 11 B 01 3 Ve rt ic al T ab 43 2B 05 3 & #0 43 ; + 75 4B 11 3 & #0 75 ; K 10 7 6B 15 3 & #1 07 ; k 12 C 01 4 Fo rm fe ed 44 2C 05 4 & #0 44 ; , 76 4C 11 4 & #0 76 ; L 10 8 6C 15 4 & #1 08 ; l 13 D 01 5 Ca rr ia ge re tu rn 45 2D 05 5 & #0 45 ; - 77 4D 11 5 & #0 77 ; M 10 9 6D 15 5 & #1 09 ; m 14 E 01 6 Sh ift O ut 46 2E 05 6 & #0 46 ; . 78 4E 11 6 & #0 78 ; N 11 0 6E 15 6 & #1 10 ; n 15 F 01 7 Sh ift In 47 2F 05 7 & #0 47 ; / 79 4F 11 7 & #0 79 ; O 11 1 6F 15 7 & #1 11 ; o 16 10 02 0 D at a Li nk E sc ap e 48 30 06 0 & #0 48 ; 0 80 50 12 0 & #0 80 ; P 11 2 70 16 0 & #1 12 ; p 17 11 02 1 D ev ic e Co nt ro l 1 49 31 06 1 & #0 49 ; 1 81 51 12 1 & #0 81 ; Q 11 3 71 16 1 & #1 13 ; q 18 12 02 2 D ev ic e Co nt ro l 2 50 32 06 2 & #0 50 ; 2 82 52 12 2 & #0 82 ; R 11 4 72 16 2 & #1 14 ; r (C on tin ua ) 40 Técnicas de Programação De c He x Oc t Ch r De c He x Oc t HT M L Ch r De c He x Oc t HT M L Ch r De c He x Oc t HT M L Ch r 19 13 02 3 D ev ic e Co nt ro l 3 51 33 06 3 & #0 51 ; 3 83 53 12 3 & #0 83 ; S 11 5 73 16 3 & #1 15 ; s 20 14 02 4 D ev ic e Co nt ro l 4 52 34 06 4 & #0 52 ; 4 84 54 12 4 & #0 84 ; T 11 6 74 16 4 & #1 16 ; t 21 15 02 5 N eg at iv e Ac k. 53 35 06 5 & #0 53 ; 5 85 55 12 5 & #0 85 ; U 11 7 75 16 5 & #1 17 ; u 22 16 02 6 Sy nc hr on ou s id le 54 36 06 6 & #0 54 ; 6 86 56 12 6 & #0 86 ; V 11 8 76 16 6 & #1 18 ; v 23 17 02 7 En d of T ra ns . Bl oc k 55 37 06 7 & #0 55 ; 7 87 57 12 7 & #0 87 ; W 11 9 77 16 7 & #1 19 ; w 24 18 03 0 Ca nc el 56 38 07 0 & #0 56 ; 8 88 58 13 0 & #0 88 ; X 12 0 78 17 0 & #1 20 ; x 25 19 03 1 En d of M ed iu m 57 39 07 1 & #0 57 ; 9 89 59 13 1 & #0 89 ; Y 12 1 79 17 1 & #1 21 ; y 26 1A 03 2 Su bs tit ut e 58 3A 07 2 & #0 58 ; : 90 5A 13 2 & #0 90 ; Z 12 2 7A 17 2 & #1 22 ; z 27 1B 03 3 Es ca pe 59 3B 07 3 & #0 59 ; ; 91 5B 13 3 & #0 91 ; [ 12 3 7B 17 3 & #1 23 ; { 28 1C 03 4 Fi le Se pa ra to r 60 3C 07 4 & #0 60 ; < 92 5C 13 4 & #0 92 ; \ 12 4 7C 17 4 & #1 24 ; | 29 1D 03 5 G ro up Se pa ra to r 61 3D 07 5 & #0 61 ; = 93 5D 13 5 & #0 93 ; ] 12 5 7D 17 5 & #1 25 ; } 30 1E 03 6 Re co rd Se pa ra to r 62 3E 07 6 & #0 62 ; > 94 5E 13 6 & #0 94 ; ^ 12 6 7E 17 6 & #1 26 ; ~ 31 1F 03 7 U ni t Se pa ra to r 63 3F 07 7 & #0 63 ; ? 95 5F 13 7 & #0 95 ; _ 12 7 7F 17 7 & #1 27 ; D el Fonte: Varejão, 2004, p. 50. Desenvolvendo um programa 41 O tipo primitivo chamado booleano é o mais simples em todas as linguagens de programação, pois apresenta apenas dois valores, os quais correspondem a verdadeiro e falso. Sendo assim, sua cardina- lidade é do tipo 2. Em relação ao tipo de dado decimal, o booleano armazena um nú- mero fixo de dígitos decimais. A localização do ponto decimal é esta- belecida de maneira arbitrária pela linguagem de programação, pelo hardware ou pelo programador, em alguma posição das células de me- mória que armazena o seu valor. Em programações comerciais,o tipo decimal é muito usado, já que é possível armazenar os valores de modo preciso, mesmo com um in- tervalo restrito de conjunto de valores. Esse conjunto reduzido e o des- perdício de memória para representação do tipo de dado são algumas das desvantagens do tipo decimal. Os tipos de dados definidos como pontos flutuantes são responsá- veis por modelar os números reais, e sua representação é finita, como em pi. As linguagens de programação mais atuais utilizam a representação do hardware para o ponto flutuante de duas formas: float e double. E a maioria delas acaba adotando o padrão IEEE 754. No artigo Padrão IEEE 754 para aritmética binária de ponto flutuante, de Gerardo Valdisio Rodrigues Viana, publicado na Revista CT, é possível observar a contribuição do padrão IEEE 754 para o uso de ponto flutuante nas linguagens de programação. Acesso em: 17 abr. 2020. https://www.lia.ufc.br/~valdisio/download/ieee.pdf Artigo Nota-se que a cardinalidade dos tipos double e float é limitada pelo número de bits usado em cada uma das representações. Os tipos enumerados permitem ao programador especificar novos tipos primitivos, enumerando os identificadores que denotarão os va- lores do novo tipo. Em linguagem de programação C, os enumerados podem ser apresentados como: enum mes_letivo {mar, abr, mai, jun, jul}; 42 Técnicas de Programação Os tipos de dados enumerados são usados para melhorar a legibi- lidade e confiabilidade do código. Nesse caso, a primeira é aumentada porque os identificadores de valores são mais facilmente reconhecidos do que códigos numéricos; já a segunda é aumentada por conta dos valores fora da enumeração, não sendo válidos. Assim, a cardinalida- de de um tipo enumerado corresponde ao número de identificadores usados na enumeração. Já os tipos de intervalo inteiros, por sua vez, herdam as operações dos inteiros. A variável intervalo pode ser atribuída a variáveis inteiras, e vice-versa. Analisando estritamente, as inteiras podem ser considera- das como um subtipo de dados inteiros. As vantagens deste são pra- ticamente as mesmas dos tipos enumerados. A legibilidade sempre é aumentada a partir do momento em que fica mais claro qual intervalo de valores o tipo pode assumir (VAREJÃO, 2004). 2.3.2 Tipos compostos Os tipos compostos são definidos por tipos mais simples, como os vetores, as listas, os arquivos, e, segundo Sebesta (2018), são forma- dos por produtos cartesianos, mapeamentos, uniões e tipos recursivos usados para classificar e explicar os tipos de compostos. O produto cartesiano é formado por um conjunto de valores de tipos de dados diferentes e, nas linguagens de programação, como Pascal, Cobol, C e Ada, é conhecido como registros. É possível represen- tar isso com o seguinte trecho de código na linguagem C: struct cadastro { char nome [30]; char endereco [30]; char cidade [10]; }; struct funcionário { struct cadastro nempregado; float salario; } func; Na segunda struct, chamada de funcionário, os identificadores nempregado e salario são considerados seletores que permitem acessar os componentes da tupla, fazendo com que o programador não necessite lembrar a ordem dos componentes. tupla: utilizada para agrupar e organizar uma sequência de valores, isto é, um conjunto de valores/itens em um único valor composto, como uma data de nascimento. Glossário Desenvolvendo um programa 43 Quando se trabalha com produtos cartesianos em linguagem de programação, ao se referenciar os componentes de uma determina- da tupla, é preciso seguir uma notação. De acordo com a linguagem de programação, para acessar o campo endereço, por exemplo, é necessário usar: func.nempregado.endereco Em linguagens de programação orientadas a objetos, os produtos cartesianos são representados por meio das classes, e seu modelo de implementação é com base no armazenamento de valores do produto em posições adjacentes da memória. As uniões consistem na junção de valores de tipos distintos para for- mar um novo tipo de dados, e são classificadas como livres e disjuntas. As primeiras apresentam intersecção entre o conjunto de valores dos tipos que compõem a união. Nesse sentido, a união resultante sempre apresentará como resultado um único valor correspondente a valores comuns aos vários tipos. Na linguagem de programação, uma união livre pode ser exemplifi- cada, conforme descrito por Varejão (2004): union medida { int centímetros; float metros; }; union medida medicao; float altura; medicao.centimetros = 180; altura = medicao.metros; printf (“\n altura : %f metros \n”, altura); Nesse exemplo, nota-se que foi atribuído um valor de 180 centímetros à variável medicao e, na sequência, é utilizada a variável de medição em metros, não havendo, por sua vez, um valor a ela atribuído. Essas situações podem trazer consequências impre- visíveis ao resultado do programa. Assim, o modelo de implementação de uniões livres consiste, nor- malmente, em reservar espaço suficiente em memória para abrigar o componente da união que necessita de mais espaço e compartilhá-lo com os demais. 44 Técnicas de Programação As uniões disjuntas, por outro lado, não possibilitam intersecção entre o conjunto de variáveis dos tipos que formam a união. Para isso, um campo de identificação chamado tag é usado com o intuito de iden- tificar qual o tipo originário do valor da união disjunta (VAREJÃO, 2004). Em Pascal, uma união disjunta pode ser representada da seguinte forma: TYPE Representacao = (decimal, fracionaria); Numero = RECORD CASE Tag: Representacao OF decimal: (val: REAL); fracionaria: (numerado, denominador: INTEGER); END; Vale ressaltar que o modelo de implementação das uniões disjuntas é idêntico ao das uniões livres. Sobre os tipos compostos chamados de mapeamentos, trata-se dos conjuntos de valores correspondentes a todos os valores possíveis dos mapeamentos de um tipo de dados A em outro B. Muitos entendem o conceito de mapeamento quando o relacionam aos produtos cartesia- nos, pois um produto cartesiano de #A elementos pode conter cada elemento, assumindo qualquer valor do tipo B, por exemplo. Há mapeamentos finitos e mapeamentos por funções. No caso dos primeiros, são representados por um conjunto de domínio finito, sen- do possível citar, como exemplo, os vetores, pois, normalmente, eles são declarados e utilizados com um tamanho finito de posições. Tabela 3 Mapeamentos finitos 10 11 13 15 ... 30 34 40 0 1 2 3 ... 4 5 6 Fonte: Elaborada pela autora. A maior parte das linguagens de programação, ao trabalhar com mapeamentos finitos e, por sua vez, vetores, sempre restringe o con- junto índices a um intervalo de inteiros. Ou seja, na Tabela 3, o vetor pode ser declarado com 7 posições, e o conjunto de índices criados inicia na posição 0 e finaliza na posição 6. O mapeamento por funções, como é possível supor, é realizado por funções. Cabe destacar que uma função implementa um mapeamento Desenvolvendo um programa 45 por meio de um algoritmo, o qual toma qualquer valor em uma função e o computa em outra. Faz parte do conjunto de tipos compostos, também, o tipo recursivo, que se caracteriza por valores compostos. Nesse sentido, é possível afir- mar que um recursivo é definido em termos de si próprio. Como exem- plo de tipos recursivos é possível citar as listas, utilizadas em estrutura de dados para armazenamento de um conjunto maior de valores. 2.4 Expressões e sentenças de atribuição Vídeo As expressões e sentenças de atribuição são muito utilizadas em qualquer desenvolvimento de programa, independentemente da lingua- gem de programação adotada. Por meio das expressões, pode-se reali- zar cálculos e resolver problemas que usam representações aritméticas. Para isso, é importante entender a ordem de avaliação dos operadores e seus operandos, bem como conhecer as sobrecargas de operadores que são conhecidos por terem mais de uma funcionalidade. Com base nesse entendimento, torna-se
Compartilhar