Resumo Tipos de Dados - LP1

9
Resumo de Linguagens de Programação I Paradigmas de Linguagens de Programação As linguagens adotam técnicas comuns de programação, desenvolvidas de forma independente de uma linguagem conforme a área de Linguagens de Programação evolui. As linguagens de programação podem ser classificadas de muitas formas diferentes. Uma das formas de classificação é quanto ao paradigma de programação. No contexto de linguagens de programação, podemos dizer de maneira bem simples que paradigma é um estilo. Porém estamos nos referindo a estilo numa conotação forte. Para serem chamados de paradigmas de programação, estilos precisam ser suficientemente diferentes e completos para serem considerados uma forma de ver o mundo. Autores diferentes classificam as linguagens de programação de formas diferentes. Apesar disso, é geralmente aceito que existem dois tipos principais de programação: (a) Programação imperativa(ou procedural), de acordo com a qual os programas são construídos por meio de uma sequência de ordens - o programador escreve um procedimento que leva à solução de um problema; (b) Programação declarativa (ou descritiva), de acordo com a qual os programas são construídos simplesmente pela descrição da solução de um problema - cabe ao compilador encontrar uma sequência de instruções que produz a solução declarada. Na programação declarativa, existem duas formas principais de se descrever soluções: 1 - Através de funções (conceito matemático de associação entre elementos de um conjunto domínio para um conjunto imagem) e 2 - Através de predicados (elementos sintáticos que permitem expressar relações entre elementos de conjuntos). Vale lembrar que uma função é um tipo especial de relação de associação. São três os paradigmas de programação: • Programação imperativa (ou procedural) - em que programas são implementações de algoritmos (sequência de instruções que levam à solução de um problema); • Programação funcional - em que programas são implementações de funções • Programação lógica - em programas são implementações de predicados (relações entre elementos de conjuntos diversos).

Transcript of Resumo Tipos de Dados - LP1

Page 1: Resumo Tipos de Dados - LP1

Resumo de Linguagens de Programação I

Paradigmas de Linguagens de Programação

As linguagens adotam técnicas comuns de programação, desenvolvidas de forma independente de uma linguagem conforme a área de Linguagens de Programação evolui.

As linguagens de programação podem ser classificadas de muitas formas diferentes. Uma das formas de classificação é quanto ao paradigma de programação.

No contexto de linguagens de programação, podemos dizer de maneira bem simples que paradigma é um estilo. Porém estamos nos referindo a estilo numa conotação forte. Para serem chamados de paradigmas de programação, estilos precisam ser suficientemente diferentes e completos para serem considerados uma forma de ver o mundo.

Autores diferentes classificam as linguagens de programação de formas diferentes. Apesar disso, é geralmente aceito que existem dois tipos principais de programação:

(a) Programação imperativa(ou procedural), de acordo com a qual os

programas são construídos por meio de uma sequência de ordens - o programador escreve um procedimento que leva à solução de um problema;

(b) Programação declarativa (ou descritiva), de acordo com a qual os programas são construídos simplesmente pela descrição da solução de um problema - cabe ao compilador encontrar uma sequência de instruções que produz a solução declarada. Na programação declarativa, existem duas formas principais de se descrever soluções:

1 - Através de funções (conceito matemático de associação entre elementos de um conjunto domínio para um conjunto imagem) e

2 - Através de predicados (elementos sintáticos que permitem expressar relações entre elementos de conjuntos). Vale lembrar que uma função é um tipo especial de relação de associação.

São três os paradigmas de programação:

• Programação imperativa (ou procedural) - em que programas são implementações de algoritmos (sequência de instruções que levam à solução de um problema);• Programação funcional - em que programas são implementações de funções • Programação lógica - em programas são implementações de predicados (relações entre elementos de conjuntos diversos).

Page 2: Resumo Tipos de Dados - LP1

É comum encontrar autores que classificam a Programação Orientada a Objetos como sendo um paradigma de programação. Essa classificação considera que o projeto de programas orientados a objetos segue conceitos de destaque suficiente para que esse estilo de programação seja classificado à parte da programação imperativa.

Tipos de Dados

Dizem o que os bits representam.O uso do tipo depende do problema.Algumas linguagens não tem o tipo de dado que você precisa, pode ser

necessário implementá-lo. (Ex.: implementar listas ou árvores usando vetores).Um tipo primitivo de dados é aquele que não pode ser decomposto em partes

mais simples. Para tal classificação, considera-se a linguagem propriamente dita (e não suas bibliotecas). Exemplo: Inteiros.

Um fator importante para determinar a facilidade com que os computadores podem executar uma tarefa é quão bem os tipos de dados coincidem com o espaço de problema do mundo real. Portanto, é crucial que uma linguagem suporte uma variedade de tipos de dados e estruturas.

Os tipos definidos pelos usuários oferecem uma melhor legibilidade pelo uso de nomes de tipos significativos.

Descritor É um conjunto de células de memória que armazenam atributos de variáveis. São construídos pelo compilador e são usados para a verificação de tipos e pelas operações de alocação e de desalocação.

Inteiros

Os inteiros são infinitos, porém a capacidade de bits para inteiro é fixa.Atualmente, muitos computadores suportam diversos tamanhos de inteiros, e

essas capacidades são refletidas em algumas linguagens de programação. Por exemplo, o Ada permite que as implementações incluam ate três tamanhos de inteiros: Short Integer, Integer e Long Integer. Em outras linguagens, como o C++, incluem tipos inteiros sem sinal, usados frequentemente com dados binários.

Em geral, short ocupa 16 bits, long ocupa 32 bits e int, 16 ou 32 bits. Cada compilador é livre para escolher tamanhos adequados ao próprio hardware. A vantagem desses tamanhos diferentes é não desperdiçar memória.

Um inteiro negativo poderia ser armazenado em uma notação de sinal-magnitude, na qual o bit de sinais é fixado para indicar o valor negativo, enquanto o restante da cadeia de bits representa o valor absoluto de número, entretanto, essa notação não se presta para a aritmética computadorizada.

A maioria dos computadores atualmente usa uma notação chamada complemento de dois para armazenar inteiros negativos, o que é conveniente para a adição e para a subtração. Para converter a representação binária de um número em seu decimal correspondente segundo a notação de complemento a dois é um pouco mais trabalhoso. Primeiramente, é necessário verificar se o dígito mais à esquerda do número é um ou zero. Se for zero, o número será zero ou positivo. Se for um, o número decimal será negativo. Nesse caso, deve-se inverter a representação binária do número e incrementá-lo de um. Assim, obtém-se a

Page 3: Resumo Tipos de Dados - LP1

representação do número na base binária. Basta, então convertê-la para a base decimal levando em conta o seu sinal. Por exemplo:

11111101 (representação na notação de complemento a dois)1 (dígito mais a esquerda –> número é negativo)00000010 (representação com inversão binária)00000001 (representação binária do número um)00000011 (adição binária do número invertido e um)00000011 = 0x27+0x26+0x25+0x24+0x23+0x22+1x21+1x20 = 311111101 = -3 (considerando o sinal)

As principais vantagens da notação de complemento a dois são ter uma representação única para o número zero e também poder utilizar os operadores aritméticos binários para implementar suas próprias operações.

Wrap Arround quando é estourado o limite de um tipo de dado, o resultado possui uma parte da operação certa, pois o computador opera até o número máximo de bits possível.

Inteiros com sinal possuem menos espaço do que os inteiros sem sinais.

Inteiros sem sinal possuem mais espaço, pois não precisam representar o caractere ‘’-‘’.

Ponto Flutuante

Modelam os números reais, mas as representações são somente aproximações para a maioria dos números. A ideia parte da notação científica, que evidencia a parte mais importante do número. Isso gera uma imprecisão do número representado, o que faz com que haja uma perda de exatidão nas operações aritméticas. Se o computador tiver mais memória, haverá mais precisão e informação. A imprecisão aumenta quando o número é muito grande.

Os pontos flutuantes são armazenados em dígitos binários. A maioria dos computadores usam a norma IEEE 754, que estabelece 23 bits de mantissa e 8 de expoente para precisão simples; 52 bits de mantissa e 11 bits de expoente para precisão dupla. Ponto Flutuante não é somente número, existe também o NaN (not a number, exemplo: operações impossíveis, tais como 0/0) e o Inf (mais ou menos infinito).

A comparação de inteiro com real é altamente imprevisível, porque usam representações diferentes em bits. A comparação de real com real é chamada de verificação de equivalência, como os dois números são aproximações, é imprevisível dizer se vão ser considerados números iguais ou não.

Decimais

Page 4: Resumo Tipos de Dados - LP1

A maioria dos grandes computadores projetados para suportar aplicações de sistemas comerciais tem suporte de hardware para tipos de dados decimais, que armazenam um número fixo de dígitos decimais, com a vírgula decimal em uma posição fixa no valor.

Vantagem capacidade de armazenar com precisão valores decimais(dentro de uma faixa restrita), o que não pode ser feito em ponto flutuante.

Desvantagem os números decimais usam códigos binários e ocupam mais espaço do que as representações binárias. Essas representações são chamadas decimais codificadas em binário (BCD).

Não é presente nas linguagens modernas devido a ausência da capacidade do hardware. Algumas máquinas tinham hardware próprio para esse tipo e representavam números como strings de bits, desperdiçando um pouco de espaço. Hoje em dia, costuma-se usar emulação desse tipo no software.

Booleanos

Os tipos booleanos são, talvez, os mais simples de todos. Sua faixa de valores tem somente dois elementos: verdadeiro e falso. Algumas linguagens não possuem esse tipo (exemplo: linguagem C, no qual expressões numéricas podem ser usadas como condicionais. Nessas expressões, todos os operandos com valores diferentes de zero são considerados verdadeiros, e zero é considerado falso).

Vantagem aumentam a legibilidade.Um valor booleano poderia ser representado por um único bit, mas pela

dificuldade e pela falta de eficiência do acesso de um bit, geralmente os booleanos são armazenados na menor célula de memória eficientemente endereçável: o byte.

Caracteres

Representa um símbolo com um número correspondente, a representação muda de acordo com a cultura e há problema de padronização.

Nem sempre os símbolos gráficos possuem o mesmo tamanho.Tabela ASCII um dos primeiros padrões (7 bits, 128 posições)UTF8 cada caractere = 4bits, é compatível com o ASCII, padrão de fato e de

direito.UNICODE Lista com símbolos gráficos com objetivo de padronização, ainda

não terminado.Geralmente supõe-se que o caractere tem 1 byte, pois a maioria dos

codificadores da nossa cultura usa dessa forma, porem isso não é bom porque nem sempre será desse jeito nos outros países.

Cadeias de caracteres

Podem ser tipos primitivos (strings) ou não, depende da linguagem.Quando são representados como vetores de caracteres, frequentemente a

linguagem fornece poucas operações.Operações com strings: atribuição, comparação, concatenação, conversão para

maiúsculo.Exemplo de concatenação name1 := name1 + name2;

Page 5: Resumo Tipos de Dados - LP1

A maior parte dos usos de cadeias e a maioria das funções de biblioteca usam a convenção segundo a qual as cadeias de caracteres são finalizadas com um caractere especial nulo (zero). Essa é uma alternativa para manter o tamanho da string.

Para manter o tamanho variável num espaço estático de memória, é preciso algum tipo de controle. FORTRAN usa strings sempre cheias. C usa o terminador zero, favorecendo em armazenamento. Pascal usa o tamanho no primeiro elemento do vetor (problemas de limite para o tamanho), eficiente em buscas na string.

Algumas linguagens modernas possuem vários recursos para strings, tais como casamento de padrão e interpolação [Writeln (‘Resultado =’ resultado);].

Tem um importante papel para a segurança de computadores (buffer overflow)Quanto as opções de tamanho da cadeia, existem 3:Cadeia de tamanho estático – usado no Pascal, Ada, FORTRAN 90 são

sempre cheias, se uma cadeia mais curta for atribuída a uma variável, os caracteres vazios normalmente serão ajustados como brancos (espaços).

Cadeia de tamanho dinâmico limitado – usado no C e C++, as cadeias tem tamanhos variáveis até um máximo declarado e fixo estabelecido pela definição da variável. Usam um caractere especial para indicar o final da string, em vez e manterem seu tamanho.

Cadeia de tamanho dinâmico – usado no Java, Perl, SNOBOL4, as cadeias tem tamanhos variáveis sem nenhum máximo, tal opção exige a sobretaxa de alocação e desalocação dinâmica de armazenamento, mas proporciona máxima flexibilidade.

Tratar cadeia de caracteres como vetores pode ser mais incômodo do que lidar com um tipo de cadeia primitivo. A sua adição como um tipo primitivo a uma linguagem não é custosa, tanto em termos de complexidade da linguagem como do compilador.

OBS: Alocação é definida antes da execução do programa. (tempo de carregamento).

Durante a compilação que se decide quanto espaço o programa precisa para os dados e como esse espaço será dividido entre os vários dados. (tempo de compilação).

Enumerados

Em algumas LPs, tais como PASCAL, ADA, C e C++, é permitido que o programador defina novos tipos primitivos através da enumeração dos identificadores que denotarão os valores do novo tipo.

Tipos enumerados são utilizados basicamente para aumentar a legibilidade e confiabilidade do código. A legibilidade é aumentada porque identificadores de valores são mais facilmente reconhecidos do que códigos numéricos. Por exemplo, num programa de processamento bancário é mais fácil identificar os bancos específicos se os descrevemos por seu nome ao invés de usar seus códigos numéricos.

A confiabilidade é aumentada porque valores fora da enumeração não são válidos. Além disso, operações aritméticas comuns não podem ser realizadas sobre estes tipos, permitindo que o compilador identifique possíveis erros lógicos e tipográficos. Como C e C++ tratam enumerações como inteiros, estas duas vantagens de confiabilidade não estão presentes.

A repetição de constantes simbólicas pode gerar problemas, por exemplo:

Page 6: Resumo Tipos de Dados - LP1

Tipo flor rosaTipo cor rosa

Para solucionar esse problema, ou o programador exibe uma mensagem de erro ou então ele cria uma variável para pegar o nome, ex: a := rosa;

Subfaixas

Aumentam a legibilidade ao tornar explícitos limites de um tipo numérico. Aumenta a confiabilidade porque a atribuição de um valor a uma variável de subfaixa fora da faixa especificada é detectada como um erro pelo compilador ou pelo sistema em tempo de execução.

Ponteiros

Um tipo ponteiro é aquele em que as variáveis têm uma faixa de valores que consiste em endereços de memória e um valor especial, o nil. O nil/null não é um endereço válido e serve para indicar que um ponteiro não pode ser usado atualmente para referenciar qualquer célula de memoria.

Esse tipo foi projetado para dois usos distintos. Primeiro, eles apresentam parte do poder de endereçamento indireto, em segundo, fornecem um método de gerenciamento de armazenamento dinâmico.

Geralmente são usados para referenciar alguma outra variável, em vez de armazenar dados de alguma espécie.

Há duas operações com ponteiros: atribuição e desreferenciamento. A atribuição fixa o valor de uma variável de ponteiro em um endereço útil.

Um ponteiro armazena um valor inteiro e sem sinal (ponteiros são números naturais) que representa um endereço na memória, permitindo acessar os dados contidos nesse endereço de memória.

Exemplo de flexibilidade de ponteiros:

‘’Agora vamos supor que seu programa precisa trabalhar com uma informação, do tipo número inteiro, mas pode ser também que essa informação não exista e o programa deve ser capaz de lidar com esse caso. Usando somente uma variável do tipo inteiro, não é possível representar a situação "não existe nenhum inteiro aqui". Porém, se o inteiro for na verdade um ponteiro para um inteiro, essa representação é possível. Podemos dizer que tal inteiro pode não ter valor. Nesse caso, o uso de um ponteiro para inteiro mais um inteiro aumentou a flexibilidade do programar ao lidar com inteiros. ‘’

Os ponteiros sempre existem nas linguagens de programação, às vezes eles são ‘’escondidos’’.

Em algumas linguagens, usam para acessar endereços de memoria, em outras usam somente recursos. Em java, o compilador reconhece as variáveis como ponteiros.

Vetores

Agregado homogêneo e unidimensional de valores.

Page 7: Resumo Tipos de Dados - LP1

Possui dificuldade para mudar o seu tamanho, porém tem acesso em tempo constante.

Os valores estão em posições consecutivas, sendo que no pascal é possível escolher o valor mínimo do índice. Ex: [10..15]

Vetor dinâmico troca o endereço da memoria, dando a impressão de que o vetor aumentou.

O único vetor heterogêneo existente é o vetor de ponteiros, pois eles podem apontar para vários tipos de dados. Os vetores heterogêneos além de guardar a informação, também guardam os ponteiros, por isso mais memória é gasta.

Operadores: () e []

Vetores Associativos

São estruturas chaves-valor (associação)Quando é digitado determinada chave, retorna um valor.Não é organizado.Algumas linguagens só usam vetores associativos, porque podem ser usados

como vetores, listas ou registros.São implementados por árvores ou funções hash.Função hash entra um monte de bytes e sai uma quantidade fixa de bytesExemplo: CEP 123.456.779-15

_________

Operações desses números geram o número 15

Vetores associativos por árvores são mais fáceis de inserir/remover porque gasta pouco recursos visto que é uma estrutura segmentada, porém o acesso não é em tempo constate.

Vetores associativos por funções hash o oposto do de árvores.

O vetor associativo tem custo em questão de memória e processamento.

Listas

Aglomerado homogêneo, assim como vetores.São recursivas (lista é vazia ou é valor + uma lista) e segmentadasO acesso não é em tempo constante, requer que a estrutura seja percorrida para

acessar um valor.Inserir/Remover elementos de listas é muito fácil.São geralmente dinâmicas, mas podem ser estáticas.

Vetores x Listas

Vetores são melhores em processamento, é mais fácil achar um elemento num vetor do que numa lista, pois nos vetores o acesso é em tempo constante.Listas são melhores para mudar a estrutura dos dados, já que é uma estrutura segmentada. É mais fácil de inserir/remover elementos de uma lista do que em vetores.

Registros

Page 8: Resumo Tipos de Dados - LP1

É um agregado possivelmente heterogêneo de elementos de dados. Cada elemento individual é identificado por seu nome.

Os campos de um registro normalmente não são referenciados por índices. A referência é feita por identificadores (que são nomeados).

Registros em C, C++ são chamados de estruturas, não incluem registros variantes ou uniões.

Referências a campos do registro:

A maioria das linguagens usa uma notação de pontos para as referências a campos, cujos componentes da referência são conectados por pontos.

Referência amplamente qualificada é aquela que todos os nomes de registro intermediários, do maior registro envolvente ao campo específico, são nomeados a referência.

Referência elíptica nelas o campo é nomeado, mas qualquer um ou todos os nomes de registro envolventes podem ser omitidos, contanto que a referência resultante não seja ambígua no ambiente de referência. As referências elípticas são prejudiciais para a legibilidade.

Operações em registros

Atribuição na maioria dos casos, os tipos dos dois lados devem ser idênticos. MOVE CORRESPONDING no COBOL, essa instrução copia um campo do

registro-fonte especificado para o de destino somente se este tiver um campo com o mesmo nome.

O uso de registros é seguro, o único aspecto dos registros que não é claramente legível são as referências elípticas permitidas pelo COBOL e PL/I.

Os registros são usados quando um conjunto de valores de dados é heterogêneo e os diferentes campos não são processados da mesma maneira, além disso, os campos de um registro, muitas vezes, não precisam ser processados em uma ordem sequencial particular. O acesso aos campos é muito eficiente.

União

É um tipo que pode armazenar diferentes valores de tipo durante a execução do programa. Em alguns casos, as uniões limitam-se a fazer parte das estruturas de registro, mas, em outros, não.

Uniões livres é permitida completa liberdade aos programadores quanto a verificação de tipos em seu uso. (exemplo de linguagens: FORTRAN, C e C++)

Uniões discriminadas cada construção de união inclui um indicador de tipo (discriminante) (exemplo de linguagens: Pascal, Ada, ALGOL 68). Também chamada de registro variante.

Page 9: Resumo Tipos de Dados - LP1

Desvantagem As uniões são construções potencialmente inseguras em muitas linguagens. Elas constituem um dos motivos pelos quais linguagens como o FORTRAN, Pascal, C, C++ não são fortemente tipificadas, pois não permitem verificação de tipos das referências a suas uniões.

Vantagem as uniões economizam memória e proporcionam flexibilidade de programação, em algumas linguagens permite a aritmética de ponteiros. Há algumas linguagens, Ada por exemplo, que podem ser usadas com segurança.

Um grande número de linguagens não inclui uniões. Isso talvez reflita a grande preocupação com a segurança nas linguagens de programação.

‘’O problema das uniões é a verificação de tipos, ou seja, garantir que as operações que usam uniões estão corretas em termos de tipos de dados. Essa dificuldade vem do fato de que o valor de uma união pode ser de mais de um tipo.’’

Conjuntos

Tipo cujas variáveis podem armazenar coleções não-ordenadas de valores distintos de algum tipo ordinal.

Vantagens Exemplo de vantagem: ‘’Se o conjunto de vogais fosse representado como um vetor char no Pascal, identificar se determinada variável armazenou uma vogal exigiria um laço para procurá-la no vetor de vogais. Se estas fossem representadas como um conjunto, a mesma determinação poderia ser feita com uma aplicação do operador in ( if ch in [‘a’, ‘e’, ‘i’, ‘o’, ‘u’] ). Isso não somente é eficiente para o programador, mas, provavelmente, também será eficiente para o computador. Nesse caso é melhor lidar com o conjunto inteiro como sendo uma unidade.’’

Desvantagens não pode repetir os elementos num mesmo conjunto, limitações de capacidades (no Pascal tem limite de 60 elementos) e operações. É complicado realizar operações de união, intersecção, pertencente, etc, por não poder repetir elementos.

Unidade

Guarda um valor possível (zero). Void.