Notas de Aula – Prof. Jorge Habib.

Transcrição

Notas de Aula – Prof. Jorge Habib.
Este material aborda o conteúdo de uma
disciplina de introdução à programação
para cursos de Ciência da Computação e
Engenharias. A linguagem de
programação utilizada é Pascal. A
primeira parte engloba o histórico da
computação e os fundamentos para
compreender a representação de dados
no mundo digital. A segunda parte
contempla os principais elementos de
programação do paradigma imperativo e
procedural.
Introdução à
Programação:
Conceitos e Práticas.
Jorge Habib Hanna El Khouri
Introdução à Programação:
Conceitos e Práticas.
(notas de aulas)
Introdução à Programação: Conceitos e Práticas.
Página 1
Introdução à Programação:
Conceitos e Práticas.
(notas de aulas)
Jorge Habib Hanna El Khouri
Professor Assistente do Centro de Engenharias e Ciências Exatas
Universidade Estadual do Oeste do Paraná
Campus de Foz do Iguaçu
Revisão Técnica:
Jun-2015
Introdução à Programação: Conceitos e Práticas.
Página 2
CONTEÚDO
1. História da Computação ..................................................................................................... 11
1.1. Principais Eventos ............................................................................................................... 11
1.2. Gerações de Computadores .............................................................................................. 17
1.2.1. Primeira Geração (1938 - 1953) ............................................................................... 17
1.2.2. Segunda Geração (1952 - 1963) .............................................................................. 19
1.2.3. Terceira Geração (1962 - 1975)................................................................................ 21
1.2.4. Quarta Geração (1972 - ...)........................................................................................ 23
2. Sistemas de Numeração .................................................................................................... 25
2.1. Sistema de Numeração Egípcio ........................................................................................ 25
2.2. Sistema de Numeração Romano ...................................................................................... 26
2.3. Sistema de Numeração Maia ............................................................................................ 26
2.4. Sistema de Numeração Decimal....................................................................................... 28
3. Conceito de Bases .............................................................................................................. 32
3.1. Sistema Decimal .................................................................................................................. 32
3.2. Sistema Hexadecimal ......................................................................................................... 33
3.3. Sistema Binário .................................................................................................................... 34
3.4. Base Qualquer ..................................................................................................................... 35
3.5. Conversão entre Bases ...................................................................................................... 36
3.5.1. Conversão de Qualquer Base para a Base 10 ....................................................... 36
3.5.2. Conversão da Base 10 para Qualquer Base .......................................................... 38
3.6. Exercícios ............................................................................................................................. 41
3.6.1. Conversão da Base 2n para a Base 2 ...................................................................... 41
3.6.2. Conversão da Base 4 para a Base 2 ....................................................................... 42
3.6.3. Conversão da Base 8 para a Base 2 ....................................................................... 42
3.6.4. Conversão da Base 16 para a Base 2 ..................................................................... 43
3.7. Exercícios ............................................................................................................................. 44
4. Operações com Números Binários ................................................................................... 45
4.1. Operações Aritméticas ....................................................................................................... 45
4.1.1. Soma ............................................................................................................................. 45
4.1.2. Subtração...................................................................................................................... 46
4.1.3. Multiplicação ................................................................................................................. 47
Introdução à Programação: Conceitos e Práticas.
Página 3
4.1.4. Divisão ........................................................................................................................... 47
4.1.5. Exercícios ..................................................................................................................... 48
4.2. Operações Lógicas ............................................................................................................. 49
4.2.1. AND (E) ......................................................................................................................... 51
4.2.2. OR (OU) ........................................................................................................................ 54
4.2.3. NOT (NÃO) ................................................................................................................... 50
4.2.4. XOR / OU EXCLUSIVO .............................................................................................. 56
4.2.5. Exemplos ...................................................................................................................... 57
4.2.6. Exercícios ..................................................................................................................... 59
4.3. Operações Aritméticas Binárias com Circuitos Lógicos ................................................ 59
4.3.1. Somador Completo ..................................................................................................... 60
4.3.2. Subtrator Completo ..................................................................................................... 61
5. Representação de Dados................................................................................................... 64
5.1. Representação de Números Inteiros ................................................................................ 65
5.1.1. Inteiros Sem Sinal – Binário Puro ............................................................................. 65
5.1.2. Inteiro Com Sinal ......................................................................................................... 65
5.1.2.1.
Módulo Sinal ............................................................................................................. 65
5.1.2.2.
Complemento de 1 .................................................................................................. 66
5.1.2.3.
Complemento de 2 .................................................................................................. 67
5.1.2.4.
Excesso de 2N-1........................................................................................................ 68
5.1.2.5.
Visualização ............................................................................................................. 69
5.1.3. Soma em Complemento de 2 .................................................................................... 71
5.1.4. Exercícios ..................................................................................................................... 72
5.2. Representação de Números Reais................................................................................... 73
5.2.1. Formato IEEE 754 ....................................................................................................... 77
5.2.2. Exercícios ..................................................................................................................... 78
5.3. Representação de Informações Textuais ........................................................................ 80
6. Introdução a Arquitetura ..................................................................................................... 83
6.1. Processador - CPU ............................................................................................................. 85
6.1.1. Seção de Controle ....................................................................................................... 86
6.1.2. Seção de Processamento .......................................................................................... 87
6.1.3. Barramentos ................................................................................................................. 87
6.1.4. O sinal de Clock ........................................................................................................... 90
6.1.5. Organização do Computador .................................................................................... 90
6.1.5.1.
Pipeline...................................................................................................................... 91
6.1.5.2.
Cache ........................................................................................................................ 91
6.1.5.3.
Outras Técnicas ....................................................................................................... 93
7. Introdução à Programação................................................................................................. 94
8. O Processo de Tradução ................................................................................................... 97
9. A Linguagem Pascal ........................................................................................................... 98
10. Estrutura de um Programa Pascal .................................................................................. 101
11. Identificadores .................................................................................................................... 101
12. Variáveis e Tipos de Dados ............................................................................................. 102
13. Comando de Atribuição .................................................................................................... 103
14. Expressões Numéricas ..................................................................................................... 104
14.1.
Tipos Numéricos ........................................................................................................ 104
Introdução à Programação: Conceitos e Práticas.
Página 4
14.2.
Constantes.................................................................................................................. 107
14.3.
Operadores Matemáticos ......................................................................................... 113
14.4.
Funções Matemáticas ............................................................................................... 114
14.5.
Exemplos .................................................................................................................... 119
15. Comandos de Entrada e Saída ....................................................................................... 121
15.1.
Entrada ........................................................................................................................ 121
15.2.
Saída ........................................................................................................................... 122
15.3.
Exemplos .................................................................................................................... 122
16. Implementando Funções .................................................................................................. 124
16.1.
Exemplos .................................................................................................................... 125
16.2.
Exercícios ................................................................................................................... 127
17. Passagem de Parâmetros ................................................................................................ 134
17.1.
Por Cópia .................................................................................................................... 134
17.2.
Por Referência ........................................................................................................... 137
18. Implementando Procedures ............................................................................................. 141
19. Expressões Textuais ......................................................................................................... 145
19.1.
Tipos Textuais ............................................................................................................ 145
19.2.
Constantes.................................................................................................................. 145
19.3.
Operadores ................................................................................................................. 150
19.4.
Funções....................................................................................................................... 151
19.5.
Exemplos .................................................................................................................... 156
20. Expressões Lógicas .......................................................................................................... 159
20.1.
Tipo de Dado Boolean .............................................................................................. 159
20.2.
Operadores Lógicos .................................................................................................. 159
20.3.
Operadores Relacionais ........................................................................................... 161
20.4.
Exemplos .................................................................................................................... 162
21. Instruções de Controle ...................................................................................................... 165
21.1.
Seleção – IF-THEN-ELSE........................................................................................ 166
21.1.1. Sintaxe e Semântica ................................................................................................. 166
21.1.2. Exemplos .................................................................................................................... 168
21.2.
Seleção – CASE ........................................................................................................ 176
21.2.1. Sintaxe e Semântica ................................................................................................. 176
21.2.2. Exemplos .................................................................................................................... 178
21.3.
Repetição – FOR⋯DO.............................................................................................. 183
21.3.1. Sintaxe e Semântica ................................................................................................. 183
21.3.2. Exemplos .................................................................................................................... 185
21.4.
Repetição – WHILE⋯DO ......................................................................................... 202
21.4.1. Sintaxe e Semântica ................................................................................................. 202
21.4.2. Exemplos .................................................................................................................... 204
21.5.
Repetição – REPEAT⋯UNTIL ................................................................................ 216
21.5.1. Sintaxe e Semântica ................................................................................................. 216
21.5.2. Exemplos .................................................................................................................... 217
22. Array .................................................................................................................................... 221
22.1.
Vetor ............................................................................................................................ 222
22.2.
Sintaxe e Semântica ................................................................................................. 223
22.3.
Exemplos .................................................................................................................... 225
Introdução à Programação: Conceitos e Práticas.
Página 5
22.4.
Matriz ........................................................................................................................... 246
22.5.
Sintaxe e Semântica ................................................................................................. 247
22.6.
Exemplos .................................................................................................................... 249
23. Arquivos .............................................................................................................................. 270
23.1.
Arquivo Texto: Funções e Procedimentos............................................................. 274
23.2.
Exemplos .................................................................................................................... 281
24. Conjuntos ............................................................................................................................ 302
24.1.
Operadores ................................................................................................................. 302
24.2.
Exemplos .................................................................................................................... 304
25. Registro ............................................................................................................................... 309
25.1.
Sintaxe......................................................................................................................... 311
25.2.
Exemplos .................................................................................................................... 314
26. Tipos Ordinais Definidos pelo Usuário ........................................................................... 319
26.1.
Enumerados ............................................................................................................... 319
26.2.
Subdomínio................................................................................................................. 322
27. Expressões Binárias ......................................................................................................... 325
27.1.
Operadores Binários ................................................................................................. 325
27.2.
Operadores de Deslocamento de Bits ................................................................... 326
27.3.
Exemplos .................................................................................................................... 328
28. Ponteiros ............................................................................................................................. 334
28.1.
Sintaxe......................................................................................................................... 334
28.2.
Operação com Ponteiros .......................................................................................... 335
28.3.
Exemplos .................................................................................................................... 336
29. Estrutura de dados dinâmica ........................................................................................... 346
29.1.
Organização da memória de um programa em execução .................................. 346
29.2.
Alocação dinâmica .................................................................................................... 348
29.3.
Exemplos .................................................................................................................... 350
30. Interpretador da Linha Comando .................................................................................... 359
31. Recursividade..................................................................................................................... 361
31.1.
Conceito ...................................................................................................................... 361
31.2.
Exemplos .................................................................................................................... 363
32. Referências Bibliográficas................................................................................................ 368
Introdução à Programação: Conceitos e Práticas.
Página 6
FIGURAS
Figura 1: Ábaco. ............................................................................................................ 11
Figura 2: Ábaco e o seu uso. ......................................................................................... 11
Figura 3: O mecanismo de Anticítera. ........................................................................... 12
Figura 4: Réplica do mecanismo de Anticítera. ............................................................. 12
Figura 5: Esquema da máquina de Anticítera................................................................ 12
Figura 6: Tabela de Logaritmo de Napier ...................................................................... 12
Figura 7: Manuscrito Original de Schickard. .................................................................. 13
Figura 8: Réplica da Calculadora de Schickard. ............................................................ 13
Figura 9: La Pascaline. .................................................................................................. 13
Figura 10: La Pascaline. ................................................................................................ 13
Figura 11: Régua de Cálculo. ........................................................................................ 14
Figura 12: Máquina de Leibniz. ..................................................................................... 14
Figura 13: Tear Automático de Jacquard. ..................................................................... 14
Figura 14: Máquina Analítica de Babbage. .................................................................... 15
Figura 15: Formulário: Primeiro algoritmo de Ada. ............Erro! Indicador não definido.
Figura 16: Cartão perfurado de Hollerith. ...................................................................... 16
Figura 17: Máquina de Tabulação. ................................................................................ 16
Figura 18: ENIAC. ......................................................................................................... 17
Figura 19: Memória de Núcleo. ..................................................................................... 19
Figura 20: Ambiente de Programação da Segunda Geração. ....................................... 20
Figura 21: Evolução no nível de Programação. ............................................................. 22
Figura 22: Principais características de Software e Hardware por geração. ................. 24
Figura 23: Circuitos Digitais: Contribuições ................................................................... 45
Figura 24: Circuito Somador Completo de 1 bit. ............................................................ 61
Figura 25: Circuito da Soma de N bits. .......................................................................... 61
Figura 26: Circuito Subtrator Completo de 1 bit. ............................................................ 63
Figura 27: Mundo Real x Mundo Digital. ....................................................................... 64
Figura 28: Métodos de Representação de Dados ......................................................... 64
Figura 29: Representação em Módulo-Sinal ................................................................. 66
Figura 30: Faixa de Representação de Números Reais. ............................................... 76
Figura 31: Organização típica de um computador. ........................................................ 83
Introdução à Programação: Conceitos e Práticas.
Página 7
Figura 32: Programa na Memória RAM: Código + Dados. ............................................ 84
Figura 33: Unidade Central de Processamento típica. .................................................. 85
Figura 34: Passos na execução de uma instrução. ....................................................... 86
Figura 35: A sincronização da execução de uma instrução com o sinal de clock. ........ 90
Figura 36: Execução e Pipeline. .................................................................................... 91
Figura 37: Memória Cache. ........................................................................................... 92
Figura 38: Genealogia das Linguagens – Base FORTRAN. ......................................... 94
Figura 39: Genealogia das Linguagens. ........................................................................ 95
Figura 40: Níveis de Programação. ............................................................................... 95
Figura 41: Ciclo de Desenvolvimento de Software. ....................................................... 96
Figura 42: Processo de Tradução ................................................................................. 97
Figura 43: Estilo de Programação Spaghetti. ................................................................ 98
Figura 44: Evolução no estilo de programação. ............................................................ 99
Figura 45: Modos do Compilador. ............................................................................... 105
Figura 46: Acesso a tela com as diretivas de compilação. .......................................... 106
Figura 47: Alocação das variáveis na memória. .......................................................... 107
Figura 48: Programa fonte e janela de execução ........................................................ 122
Figura 49: Estrutura de uma função. ........................................................................... 125
Figura 50: Contexto da chamada da função foo. ......................................................... 135
Figura 51: Ponto 1 – Passagem por Cópia. ................................................................. 136
Figura 52: Ponto 2 – Passagem por Cópia. ................................................................. 136
Figura 53: Ponto 3 – Passagem por Cópia. ................................................................. 137
Figura 54: Ponto 1 – Passagem por Referência. ......................................................... 138
Figura 55: Ponto 2 – Passagem por Referência. ......................................................... 139
Figura 56: Ponto 3 – Passagem por Referência. ......................................................... 139
Figura 57: Ponto 1 – Calculo Raizes. .......................................................................... 142
Figura 58: Ponto 2 – Calculo Raizes. .......................................................................... 143
Figura 59: Ponto 3 – Calculo Raizes. .......................................................................... 144
Figura 60: Diagrama lógico para o cálculo das raízes de uma equação do 2º grau. ... 170
Figura 61: Instrução CASE .......................................................................................... 177
Figura 62: Repetição do tipo FOR. .............................................................................. 184
Figura 63: Estrutura de Controle do tipo FOR ............................................................. 184
Figura 64: Instrução BREAK........................................................................................ 197
Figura 65: Conversão Decimal - Binário ...................................................................... 205
Figura 66: Correspondência entre Definição do Vetor e a Atribuição. ......................... 225
Figura 67: Cópia de Sub-Vetor. ................................................................................... 241
Figura 68: Posição de Sub-Vetor................................................................................. 241
Figura 69: Eliminação de um Sub-Vetor. ..................................................................... 242
Figura 70: Comparação Escalar, Vetor e Matriz .......................................................... 246
Figura 71: Entrada/Saída de grande volume de dados sem o uso de arquivos .......... 270
Figura 72: Entrada/Saída de grande volume de dados com o uso de arquivos .......... 271
Figura 73: Visualização de um arquivo texto como sequência de caracteres. ............ 272
Figura 74: Visualização de um arquivo executável como sequência de caracteres. ... 272
Figura 75: Dado em Memória gravado em arquivo como binário ................................ 273
Figura 76: Dado em Memória gravado em arquivo como texto ................................... 273
Figura 77: Manipulação de Arquivo por um programa ................................................. 274
Figura 78: Organização dos dados da disciplina na memória ..................................... 289
Introdução à Programação: Conceitos e Práticas.
Página 8
Figura 79: Abstrações típicas de uma linguagem procedural ...................................... 310
Introdução à Programação: Conceitos e Práticas.
Página 9
PREFÁCIO
O conteúdo deste material é fruto de um conjunto de notas de aulas preparadas para a
disciplina introdutória à programação da grade do curso de Ciência da Computação e
posteriormente estendido para cursos de engenharias, principalmente Engenharia Elétrica
e Mecânica. A estrutura do material não está centrada em uma linguagem de
programação, mas sim no estabelecimento de uma sequência natural de conteúdos que
proporcione, desde o seu princípio, o suporte logico para a construção de programas
elementares. No avançar das temáticas o conhecimento vai sendo refinado e ao mesmo
tempo testado com problemas mais elaborados.
Antecedendo o conteúdo de programação são apresentados tópicos que ilustram os
pontos na história que marcaram a evolução da computação, onde conhecimentos das
mais diversas áreas foram combinados a fim de delinear o estado atual da tecnologia da
informação. Uma parte fundamental da computação está na compreensão da natureza
dos dados e como eles circulam no ambiente computacional. Assim, os sistemas de
numeração são abordados visando alcançar um entendimento sobre a notação binária
que predomina no mundo digital. Uma breve exposição sobre a
destaca
o trânsito da informação entre as camadas de
e de
, e expõe a
importância de se compreender toda a transformação a que é submetido um determinado
problema até se transformar efetivamente em um programa ativo na arquitetura do
computador. Um estudante de computação ou de engenharia (relacionada ao tema) deve
ter a clara noção de todas as camadas de abstração que formam o contexto
computacional. Os principais métodos de representação de dados elementares são
expostos e proporcionam conhecimentos essenciais ao entendimento dos seus impactos
nos algoritmos.
A parte de programação estabelece uma sequência de exposição do conteúdo tanto nos
aspectos conceituais quanto nas aplicações práticas. Os recursos de programação
apresentados são os típicos da família de linguagens denominada imperativa ou
procedural, e a linguagem
é a escolhida para concretizar os ensinamentos. A
grande similaridade entre as linguagens procedurais atuais faz com que a transposição
dos conhecimentos apresentados para outras linguagens seja muito facilitada.
Introdução à Programação: Conceitos e Práticas.
Página 10
1. História da Computação
Este capítulo resume os principais eventos históricos que culminaram com o estágio
atual da tecnologia digital. Os desenvolvimentos ocorreram nas mais variadas áreas da
Ciência e o processo de evolução tecnológica foi gerado em grande parte pelo
cruzamento destes conhecimentos. Destaca-se como fonte de consulta para
] . Além disso, o
aprofundamento dos temas aqui citados a publicação [
acervo do
e do site
, principalmente as
fotos, também serviram de fonte de consulta.
1.1.
Principais Eventos
O uso de ferramentas para apoiar as atividades do homem não é recente, e desde os
primórdios de nossa história tem-se observado um constante aumento no uso de
equipamentos e instrumentos que auxiliam nas tarefas normalmente realizadas por seres
humanos.
No campo da informática, o processo de evolução se deu de forma lenta durante séculos,
experimentando uma explosão tecnológica acentuada na segunda metade do século
passado.
Na busca por alternativas para o trabalho realizado pelo homem, principalmente na
mecanização do processo de contagem e na realização de trabalhos exaustivos,
obstáculos importantes foram sendo superados, a saber:
a)
b)
a.C. - uso do ábaco no vale entre os rios Tigre e Eufrates;
a.C. - aparecimento do ábaco chinês, chamado Suan-Pan, e do Soroban no
Japão;
Figura 1: Ábaco.
Introdução à Programação: Conceitos e Práticas.
Figura 2: Ábaco e o seu uso.
Página 11
c)
a.C. – uso de um mecanismo denominado Anticítera1 com um complexo sistema
de engrenagens provavelmente aplicado à navegação. Foi resgatado em
na
costa da ilha grega de Anticítera. O sistema de engrenagens simulava as órbitas da
lua, sol e de mais cinco planetas, além de prever eclipses da lua e do sol.
Figura 3: O mecanismo de
Anticítera.
Figura 4: Réplica do
2
mecanismo de Anticítera .
Figura 5: Esquema da máquina de
Anticítera.
d) séc.
- John Napier (Edimburgo - Escócia,
— de abril de
) inventou o
logaritmo e uma máquina capaz de multiplicar e dividir automaticamente;
Figura 6: Tabela de Logaritmo de Napier
1
http://pt.wikipedia.org/wiki/Máquina_de_Anticítera
Disponível no Museu Arqueológico Nacional de Atenas (feita por Robert J. Deroski, com base em Derek J. de Solla
Price. http://pt.wikipedia.org/wiki/Máquina_de_Anticítera
2
Introdução à Programação: Conceitos e Práticas.
Página 12
e)
- Wilhelm Schickard (
de abril de
, Herrenberg, Alemanha —
de
outubro de
, Tübingen) construiu uma calculadora mecânica, baseada em rodas
dentadas, capaz de realizar as operações básicas com números de seis dígitos e
indicar um overflow através do toque de um sino.
Figura 7: Manuscrito Original de Schickard.
f)
- Blaise Pascal (Clermont-Ferrand - França,
de Junho de
— Paris,
de
Agosto de
) utilizando o princípio do ábaco, implementou uma máquina
automática de calcular - La pascaline. Efetuava somas e subtrações;
Figura 9: La Pascaline.
g)
Figura 8: Réplica da Calculadora de Schickard.
Figura 10: La Pascaline.
– Padre Willian Oughtred (Eton-Inglaterra, de Março de
— Albury,
de
Junho de
) inventou a régua de cálculo (Slide rule/ slipstick) baseada nos
logaritmos de Napier e divulgou o uso do sinal
para multiplicação, tendo
introduzido os termos
,
e
.
Introdução à Programação: Conceitos e Práticas.
Página 13
h)
– Seth Patridge, Inglês, desenvolveu a régua de cálculo deslizante. Este
dispositivo foi muito utilizado até os anos setenta;
Figura 11: Régua de Cálculo.
i)
- Gottfried Wilhelm von Leibniz (Leipzig - Alemanha,
de julho de
—
Hanover,
de novembro de
) aprimorou a máquina de Pascal e obteve uma
calculadora que somava, subtraía, multiplicava e dividia;
Figura 12: Máquina de Leibniz.
j)
– Joseph Marie Charles - apelido Jacquard (Lyon – França, de Julho de
–
de Agosto de
), mecânico, construiu um tear automático com entrada de dados
via cartões perfurados para controlar a confecção dos tecidos e seus desenhos;
Figura 13: Tear Automático de Jacquard.
Introdução à Programação: Conceitos e Práticas.
Página 14
k)
– Charles Babbage (Londres - Inglaterra,
de Dezembro de
— Londres,
de Outubro de
) projetou a sua Máquina Analítica ou Diferencial, que possuía
memória, programa, unidade de controle e periféricos;
Figura 14: Máquina Analítica de Babbage.
l)
- Ada Augusta Byron King, Condessa de Lovelace (Londres – Inglaterra,
de
Dezembro de
de Novembro de
), conhecida como Ada Lovelace, fez os
primeiros estudos sobre aritmética binária. Escreveu o primeiro algoritmo para ser
processado por uma máquina, a máquina analítica de Charles Babbage.
Figura 15: Formulário: Primeiro algoritmo
de Ada.
Figura 16: Detalhe de parte do Formulário.
Introdução à Programação: Conceitos e Práticas.
Página 15
m)
- George Boole (Lincoln - Inglaterra, de Novembro de
— Ballintemple,
de Dezembro de
) desenvolveu a teoria da Álgebra de Boole (livro: An
Investigation of the Laws of Thought), que permitiu o desenvolvimento da Teoria dos
Circuitos Lógicos;
n)
- Herman Hollerith (Buffalo - EUA,
de Fevereiro de
— Washington, D.C.,
de Novembro de
) empresário norte-americano, construiu a Máquina de
recenseamento utilizada no censo de
dos EUA. A máquina efetuava a leitura dos
cartões de papel perfurados com as informações em código
(Decimal Codificado
em Binário). Os dados do censo de
foram tabulados em apenas um ano. O
censo de
levou oito anos para ser tabulado;
Figura 17: Cartão perfurado de
Hollerith.
o)
Figura 18: Máquina de Tabulação.
- Hollerith e Watson fundam a IBM;
p)
- Alan Mathison Turing (Londres – Inglaterra,
de Junho de
— de Junho
de
) desenvolveu a teoria de uma
capaz de resolver qualquer problema
computável. Foi denominada de
;
q)
- Claude Elwood Shannon (Petoskey, Michigan – EUA,
de Abril de
—
de Fevereiro de
) escreve sua tese de mestrado “A Symbolic Analysis of Relay
and Switching Circuits” onde utiliza aritmética binária e Álgebra de Boole para
implementar lógicas através de circuitos com chaves e relés, tornando-se um marco
para os circuitos digitais;
r)
- sob a liderança de Alan Turing foi projetado o
, computador inglês
utilizado na Segunda Guerra Mundial para quebrar o segredo alemão codificado pela
máquina
.
Introdução à Programação: Conceitos e Práticas.
Página 16
Este processo evolutivo culminou com o surgimento das primeiras máquinas capazes de
realizar cálculos mais complexos do que as operações básicas. A partir de então, várias
gerações de computadores foram surgindo até os dias atuais.
1.2.
Gerações de Computadores
Na sequência são listadas as principais contribuições em cada geração de
computadores, enfatizando-se a tecnologia utilizada para a construção do hardware e a
forma de programação. Trata-se apenas de um sumário bastante resumido, que serve
como referência de termos para pesquisas mais detalhadas.
1.2.1.
Primeira Geração (1938 - 1953)
A primeira geração foi marcada pela construção do primeiro computador eletrônico, o
V
(Electronic Numerical Integrator and Computer), em
, tornando-se um marco
na evolução da computação. O
começou a operar em
, sendo concluído
totalmente em
e encerrando suas operações em
.
O desenvolvimento do
se deu na Universidade da Pensilvânia (Filadélfia, EUA), e
contou com o apoio de John von Neumann.
Figura 19: ENIAC.
O
continha
válvulas,
relés,
resistores,
capacitores o
que resultava em mais de
toneladas de equipamentos distribuídos em
. Seu
consumo chegava a
. A entrada e saída de dados eram feitas por meio de leitora
de cartões de perfurados, enquanto que a programação se dava pela construção de
Introdução à Programação: Conceitos e Práticas.
Página 17
circuitos específicos para tratar o problema por ajustes manuais de chaves e conexões de
cabos.
A unidade de sincronização trabalhava com ciclos de
microsegundos ( ciclos de
clock de
), sendo capaz de executar
adições/subtrações ou
multiplicações ou
divisões ou raiz quadrada por segundo. A memória era capaz de
conter
números ( bytes).
Sua utilização inicial foi em trabalhos com soluções numéricas de problemas relacionados
com trajetórias balísticas e no desenvolvimento da bomba de hidrogênio.
Em junho de
, von Neumann publicou o trabalho sobre o
(Electronic Discrete
Variable Automatic Computer), e estabeleceu as bases para as arquiteturas de
computadores das gerações seguintes, atualmente conhecida como ―arquitetura de von
Neumann‖, que trazia o conceito de programa armazenado.
O esforço de guerra levou à construção, em
, pelos ingleses da máquina
,
concebida para quebrar o código da máquina alemã
, utilizada na transmissão de
mensagens. Pelo fato de ser uma máquina estratégica no campo militar, a sua divulgação
foi bastante limitada, o que restringiu o reconhecimento da sua importância no
desenvolvimento da computação. Os trabalhos de Alan Turing sobre computabilidade
foram consideravelmente relevantes na construção dos algoritmos da máquina
.
Nesta geração, a programação era em linguagem de máquina composta da codificação
binária das instruções da máquina. Por exemplo, a soma de dois números produzindo um
resultado na memória tinha um código semelhante à:
O entendimento desta lógica era restrito aos profissionais com conhecimento da
arquitetura do computador.
Em resumo, a primeira geração se caracterizou por:






Surgimento do
;
Utilização de relés como dispositivos de chaveamento;
Utilização de válvulas a vácuo;
Hardware caro, grande e de difícil manutenção;
Programação em linguagem de máquina;
permitiu o uso de software.
Introdução à Programação: Conceitos e Práticas.
Página 18
1.2.2.
Segunda Geração (1952 - 1963)
A segunda geração foi caracterizada pela invenção do
por John Bardeen,
Walter Brattain e William Shockley. Em dezembro de
Brattain e Moore apresentaram
o dispositivo para um grupo da Bell Labs.
Em
a Bell Labs conclui o
, tido como o primeiro computador totalmente
transistorizado. As vantagens dos transistores em relação às válvulas a vácuo são
principalmente: menos consumo de energia, peso e tamanho menores, reduzida perda de
calor e aquecimento, maior confiabilidade e robustez, maior duração e resistência a
impacto e vibração.
Também nesta geração foram consolidados dispositivos como as impressoras, as fitas
magnéticas e os discos para armazenamento, dentre outros.
A memória do computador passou a utilizar tecnologia de núcleo magnético, também
denominada
, composta por diminutos anéis magnéticos conectados por fios
que permitiam a leitura e gravação de informação. Os valores
e
eram associados
ao sentido de magnetização deste núcleo.
Figura 20: Memória de Núcleo.
O surgimento dos sistemas operacionais e das linguagens de programação acelerou o
desenvolvimento dos computadores.
A forma de programação evoluiu da
para
,
onde os códigos binários eram associados a mnemônicos que indicavam o tipo de
operação realizada. Assim, a soma de dois números produzindo um resultado na memória
tinha um código semelhante à:
LINGUAGEM ASSEMBLY
LINGUAGEM DE MÁQUINA
A percepção do poder de codificação em linguagens mais acessíveis levou a um
importante salto das linguagens de alto nível com a criação do FORTRAN em
e
COBOL em
, iniciando assim um forte ciclo de desenvolvimento de novas linguagens.
Introdução à Programação: Conceitos e Práticas.
Página 19
O mesmo problema podia agora ser codificado em uma
muito semelhante à sua notação matemática:
LINGUAGEM DE ALTO NÍVEL
LINGUAGEM ASSEMBLY
de forma
LINGUAGEM DE MÁQUINA
A forma de utilização dos computadores era semelhante a de uma calculadora, onde o
programa e dados eram introduzidos via cartões perfurados, fita de papel perfurado ou fita
magnética e os resultados eram gerados para estes mesmos dispositivos. Em
a
VI
primeira impressora , fabricada pela Remington-Rand, foi utilizada como dispositivo de
saída integrado ao computador
, dos mesmos criadores do
.
Neste período, os computadores ocupavam salas específicas que acomodavam toda a
estrutura de equipamentos e sua operação demandava técnicos especializados. É
importante lembrar que os computadores eram caros e de uso restrito a governos,
universidades e grandes corporações. Os programas eram produzidos e escritos em
formulário próprio e levados à sala de perfuração de cartão. O maço de cartões era levado
á sala com a leitora, onde um operador procedia a leitura e processamento do pacote com
o programa. Ao encerrar o processamento deste lote de cartões então o operador se
dirigia a sala de impressora para retirar o relatório para entrega ao usuário. A seguinte
figura esboça este fluxo:
Figura 21: Ambiente de Programação da Segunda Geração.
Introdução à Programação: Conceitos e Práticas.
Página 20
Cada programa que necessitava de processamento tinha que seguir este fluxo. A
necessidade de melhores mecanismos de interação entre usuário e o computador,
facilidades para administrar o processamento dos programas e formas de gerenciar o
computador e seus periféricos levou ao desenvolvimento de um conjunto de programas
que foi denominado de
.
Assim, surgiu a ideia de processamento em lote onde grupos de programas (maços de
cartões) eram lidos e gravados em uma fita. A fita era levada à sala de processamento e
lida para o computador, que processava toda a sequência e gerava uma saída também
em fita, cuja impressão acontecia em uma unidade separada (impressão off-line).
Em resumo, a segunda geração se caracterizou por:






1.2.3.
invenção do transistor;
1º computador a transistor (
) pela BELL Labs;
uso de transistores e diodos;
uso de memória de núcleo;
uso de linguagem Assembly até
, e de FORTRAN e COBOL a partir daí;
surgimento dos Sistemas Operacionais para Processamento em
(Lote) de
programas.
Terceira Geração (1962 - 1975)
Na geração anterior, o elemento básico para construção dos processadores evoluiu da
válvula a vácuo para os transistores. Na terceira geração, o transistor continuou a ser o
dispositivo de construção elementar, porém surgiu o circuito integrado ( ou chip) em
pequena (
componentes eletrônicos por
) e média escala (
componentes
eletrônicos por ), que são circuitos eletrônicos em miniatura compostos principalmente
por dispositivos semicondutores.
A invenção do circuito integrado ou
(
) é atribuída a Jack Kilby da Texas
Instruments e Robert Noyce, da Fairchild Semiconductor, cabendo a Kilby o Prêmio Nobel
de Física no ano 2000 pela participação na criação.
O uso de circuitos integrados permitiu maior compactação e confiabilidade dos
computadores com expressiva redução de custos. A tecnologia de fabricação da memória
de acesso aleatório (RAM) evolui da
para dispositivos de estado sólido.
O
tinha as maiores atenções no projeto de um computador, porém o
estava ganhando importância rapidamente. Foram criadas várias linguagens de
programação, entre elas
,
, ,
,
,
dentre outras. O processo
de produção de programas começou a ser visto como atividade de engenharia, com todo
o rigor que isto significa.
Introdução à Programação: Conceitos e Práticas.
Página 21
A figura a seguir ilustra como o programador foi se afastando da necessidade de
codificar diretamente em binário na medida em que surgiam novas linguagens de
programação. Inicialmente a
permitiu maior produtividade na
programação, e a tradução para a
era feita por um software
tradutor denominado
. Em seguida, com o surgimento da
, como o
, o programador codificava de forma mais
adequada aos problemas matemáticos, sendo que a tradução para o
era feita
por um software denominado
.
Figura 22: Evolução no nível de Programação.
Houve importante melhoria nos compiladores, que passaram a produzir códigos tão
eficientes quanto um bom programador de linguagem assembly.
O mercado de computadores era majoritariamente dominado pelos produtos da IBM, com
destaque para os
ou computadores de grande porte. Os sistemas
operacionais apresentaram significativa melhora e incorporaram recursos de
multiprogramação, time-sharing e memória-virtual. A multiprogramação permitia que o
sistema operacional trabalhasse com vários programas ativos. Neste caso, se um
determinado programa demandava dados armazenados em fita, então outro programa
entrava em processamento, até que o recurso do programa anterior fosse disponibilizado.
O
, similar ao multiprocessamento, permitiu que um único computador tivesse
seu uso compartilhado por múltiplos usuários com acesso via terminal on-line. A memória
virtual é um técnica que permite que programas utilizem mais memória do que o
disponível fisicamente na memória principal. A memória secundária (em disco, fita ou
outro meio de armazenamento) é utilizada como suporte para esta técnica de
gerenciamento de memória.
Outro recurso típico da terceira geração permitiu que programas fossem carregados
diretamente dos cartões para discos. Assim, logo que um determinado programa tivesse
sua execução encerrada, o sistema operacional iria carregar um dos programas do disco
para a partição de memória destinada aos serviços em execução. Este recurso recebeu o
nome de
(
).
Em resumo, a terceira geração se caracterizou por:
Introdução à Programação: Conceitos e Práticas.
Página 22







1.2.4.
uso de circuitos integrados em pequena (SSI) e média escala (MSI);
uso de circuitos impressos em multicamadas;
uso de memória de estado sólido;
linguagens de alto nível com compiladores inteligentes;
uso de multiprogramação
sistemas operacionais para uso em
(tempo-compartilhado);
utilização de memória virtual.
Quarta Geração (1972 - ...)
Os circuitos integrados apresentaram um aumento significante na quantidade de
transistores. A tecnologia foi denominada de Integração em Escala Muito Grande
(
–
), incorporando de
a
transistores.
As escalas seguintes de integração, ultra e super, comportam
a
e
a
dispositivos semicondutores respectivamente.
Este nível de integração e compactação permitiu que os CI´s incorporassem cada vez
mais blocos funcionais da arquitetura do computador, ao ponto que todos os elementos
básicos de uma CPU (Central Processing Unit) coubessem em um único chip, surgindo o
microprocessador.
A Intel teve importante papel no desenvolvimento dos microprocessadores, tendo iniciado
com o modelo Intel
produzido em
. Este processador era um dispositivo de
bits que continha uma ALU (Aritmetic and Logic Unit), uma unidade de controle e alguns
registradores. O marco importante foi o lançamento em
, do seu primeiro
processador de
bits, o
.
Logo em seguida, a IBM lança em
o IBM PC que se tornou padrão para
microcomputadores. O respaldo da IBM foi essencial para a aceitação e o crescimento
deste equipamento. Uma série de fabricantes passou a produzir componentes para esta
arquitetura, enquanto que a própria IBM se manteve na linha dos computadores de grande
porte, os
.
Os meios de armazenamentos tais como unidades de disco e fita ocupavam espaços
consideráveis nos CPD´s (Centro de Processamento de Dados), tornando assim um
desafio produzir uma unidade que fosse compatível com uso pessoal. Neste ponto, as
unidades de discos flexíveis (floppy disk) foram fundamentais para a viabilização dos
PC´s.
Os sistemas operacionais incorporavam cada vez mais facilidades de gerenciamento dos
recursos computacionais, tais como CPU, memória, processos e arquivos. Os sistemas
operacionais DOS e Unix tiveram seu período de consolidação, sendo o DOS no ambiente
PC Intel e o UNIX basicamente nas
RISC. A Microsoft iniciou sua trajetória
com o DOS, e esta plataforma estimulou o surgimento de um novo mercado de
desenvolvimento de softwares.
Introdução à Programação: Conceitos e Práticas.
Página 23
A necessidade de compartilhar informações e itens de
impulsionou o
surgimento das redes de computador e do processamento distribuído. E os sistemas
operacionais tiveram que ampliar suas capacidades para incluir o gerenciamento de mais
estes recursos, fazendo que toda esta complexidade fosse transparente ao usuário.
O nível de integração dos circuitos integrados alavancou arquiteturas de computadores
com múltiplos processadores permitindo o processamento paralelo.
Em resumo, a quarta geração se caracterizou por:








uso de circuitos integrados em escala muito grande (VLSI);
compactação em alta densidade (computadores menores);
Linguagens de alto nível que manuseiam tanto dados escalares como vetores;
sistema operacionais em Time-sharing e Memória Virtual;
sistemas com multiprocessadores;
Processadores paralelos;
aparecimento dos microprocessadores;
uso de disquetes (floppy disk) como meio de armazenamento;
Algumas literaturas qualificam o estágio atual como sendo
, principalmente pelo
forte emprego da tecnologia de
. Porém, é difícil classificar uma
geração fazendo parte dela, pois o avanço tecnológico atual traz inovações a todo o
momento. Por exemplo, poderíamos qualificar como marco extraordinário a abertura da
internet e o surgimento da
e do primeiro browser em
, por Tim
Berners-Lee. O interessante é que seria uma geração caracterizada principalmente por
criações de
.
O quadro a seguir destaca os principais elementos de
caracterizaram as gerações:
Software Linguagem de Máquina
Hardware Válvulas e Relés
1ª geração
1935
Linguagem Assembly
Diodo e Transistor
Linguagem de Alto Nível
Circuitos Integrados
2ª geração
1945
e de
1955
3ª geração
1965
que
Sistemas Operacionais
Compiladores Inteligentes
Circuitos Integrados VLSI
Microprocessadores
4ª geração
1975
Figura 23: Principais características de Software e Hardware por geração.
Introdução à Programação: Conceitos e Práticas.
Página 24
2. Sistemas de Numeração
Há cerca de
anos o homem começou a ter necessidade de contar (agricultura e
pastoreio), onde os pastores de ovelhas tinham necessidades de controlar os rebanhos.
Precisavam saber se não faltavam ovelhas. (III)
Alguns vestígios indicam que os pastores faziam o controle de seu rebanho usando
conjuntos de pedras. Ao soltar as ovelhas, o pastor separava uma pedra para cada
animal que passava e guardava o monte de pedras.
Quando os animais voltavam, o pastor retirava do monte uma pedra para cada ovelha
que passava. Se sobrassem pedras, ficaria sabendo que havia perdido ovelhas. Se
faltassem pedras, saberia que o rebanho havia aumentado. Desta forma mantinha tudo
sob controle.
Uma ligação do tipo: para cada ovelha, uma pedra chama-se, em Matemática,
correspondência um a um. Provavelmente passou a utilizar o dedo como apoio à
contagem, sem, no entanto poder guardar a informação.
O processo de contagem evoluiu para o agrupamento quando tratava de grandes
quantidades, p. ex: João fez
pontos ( pontos).
2.1.
Sistema de Numeração Egípcio
Essa ideia de agrupar marcas foi utilizada nos sistemas mais antigos de numeração. Os
egípcios da antiguidade criaram um sistema muito interessante para escrever números,
baseado em agrupamentos.

era representado por uma marca que se parecia com um bastão |

por duas marcas ||

E assim por diante.
Símbolo
descrição
valor
bastão
calcanhar
rolo de corda
flor de lótus
dedo apontando
peixe
homem
Introdução à Programação: Conceitos e Práticas.
Página 25
Os números eram compostos pela associação destes símbolos e a quantidade
representada era obtida pela soma dos valores individuais. Por exemplo,
é
representado por:
2.2.
Sistema de Numeração Romano
O sistema de numeração romano possui um conjunto símbolos, conforme tabela
abaixo, sendo que um número é representado pela combinação destes símbolos e o
valor é a soma de cada uma das parcelas.
A fim de evitar representações muito extensas, um determinado valor pode ser
representado a partir de um símbolo de referência acompanhado de símbolos a
esquerda (subtração do valor principal) ou a direita (soma ao valor principal). Por
exemplo,
(
)e
( –
).
Este sistema é bastante limitado para aplicações da matemática que vão além da
representação de números, onde mesmo as operações básicas são difíceis de serem
efetuadas.
2.3.
Sistema de Numeração Maia
A cultura
teve destaque nos últimos anos principalmente pelas questões relativas
ao calendário e o suposto fim dos tempos. Porém, os
também dispunham de um
sistema de numeração bem estruturado que se caracterizava como posicional,
vigesimal e símbolo para o
. Os valores dos símbolos vão de
a
,
sendo eles:
Introdução à Programação: Conceitos e Práticas.
Página 26
●
●
●
●
●●
●●
●●
●●
●●●
●●●
●●●
●●●
●●●●
●●●●
●●●●
●●●●
Os números são estruturados pela combinação destes símbolos, sendo cada símbolo
contribuindo com o seu valor multiplicado por
elevado a sua posição. A soma destas
parcelas fornece o valor do número. Por exemplo, o número
,
que no sistema
fica:
𝟐
●●
𝟗
●●●●
Este sistema permite a execução das operações básicas com a mesma facilidade que
fazemos no nosso sistema decimal. Vejamos o exemplo que segue:
A coluna
indica a operação desejada. As colunas e indicam a decomposição do
e
no sistema vigesimal. As colunas e
contém o
e
no sistema
. A coluna indica a soma provisória que se
Introdução à Programação: Conceitos e Práticas.
Página 27
obtém juntando as parcelas. Na sequência vêm os ajustes necessários, transferindo os
excedentes a , ou seja, cada
unidades excedentes em uma casa equivale a uma
unidade na casa superior. Como o símbolo
equivale a ●●●●●, então na coluna
são transferidas
unidades (
e ●) da posição
para a posição
. Isto
faz surgir um símbolo ● a mais na posição
. Na coluna
tem-se os ●●●●● da
posição
substituídos por um
. Na coluna tem-se a notação
convertida
para uma expressão convencional e o resultado da soma destas parcelas é indicado na
coluna , tal como se esperava da soma
.
2.4.
Sistema de Numeração Decimal
Os sistemas numéricos egípcio, romano e maia apresentados são apenas parte dos
muitos sistemas adotados por diferentes civilizações da antiguidade, tais como os
babilônios, gregos, chineses, hindus entre outros. Cabe destacar, que com exceção dos
maias, que habitavam a América, as civilizações da Europa, Oriente e Oriente Médio
mantinham um sistema de troca de mercadorias e comumente impérios que se
sucediam, onde um dos efeitos era a difusão de conhecimentos.
A ciência dos gregos atingiu grande desenvolvimento no século
com Euclides,
cuja obra sobre Geometria (Os Elementos) é importante até hoje no ensino dessa
matemática. Os gregos tinham seu próprio sistema de numeração, com base
,
utilizando letras para representar os números, o que não facilitava os cálculos.
Os romanos, que expandiram seus domínios a partir do século
., foram aos
poucos ocupando o espaço do império deixado por Alexandre, ao mesmo tempo que
foram assimilando parte da ciência grega. O interesse dos romanos foi pelas aplicações
práticas na engenharia (construção de estradas e aquedutos) e na medicina, com
pouca contribuição na matemática.
As invasões bárbaras, nos séculos e
, colocaram fim ao Império Romano no
ocidente e conduziu a Europa a um período de trevas no campo da Ciência.
Entretanto, enquanto o Império Romano declinava, uma grande civilização florescia no
Oriente, no vale do rio Indo, entre as regiões que atualmente constituem o Paquistão e
a Índia.
É importante destacar que os sistemas de numeração egípcio e romano não eram
propícios para efetuar cálculos. As dificuldades destes sistemas foram superadas pelos
hindus, que desenvolveram as bases do moderno sistema de numeração. Eles
souberam reunir três características que estavam dispersos em outros sistemas
numéricos da antiguidade, a saber:

Decimal: uso de dez símbolos para representar os dígitos de zero a dez (o
egípcio, o romano e o chinês também o eram);

Posicional: os símbolos assumem diferentes valores de acordo com a posição
que ocupa na formação do número (o babilônio e o maia também eram);

Presença do Zero: Foi um importante avanço a adoção de um símbolo para o
nada.
Introdução à Programação: Conceitos e Práticas.
Página 28
Estas três características, reunidas, tornaram o sistema de numeração hindu o mais
prático de todos. Não é sem motivo que hoje ele é usado quase no mundo todo.
Enquanto os hindus, que habitavam o vale do rio Indo, desenvolviam seu sistema de
numeração, grandes acontecimentos tiveram início na Península Arábica.
No século
floresce o Islamismo, e estabelece um grande império que abrangia a
região do rio Indo, a leste, o norte da África e a Península Ibérica.
A expansão Islâmica através da conquista veio na sequência de grandes impérios, tais
como o babilônio, persa, grego (macedônio) e romano. A matemática era uma das
áreas de interesse dos estudiosos árabes e o contato com o saber oriental e toda a
história de conhecimento dos impérios que o antecedeu permitiu um salto importante na
ciência.
Um grande passo foi dado na direção do extremo oriente, quando os árabes entraram
em contato com a cultura hindu e logo manifestaram particular interesse pelo seu
sistema numérico, reconhecendo sua simplicidade e praticidade.
Em outra frente, os árabes haviam ocupado parte da Península Ibérica, o que serviu de
ponte para a ciência oriental ser introduzida na Europa medieval. A expansão árabe
resultou também no surgimento, entre os séculos
e
, de várias universidades e
bibliotecas, desde Bagdá, no atual Iraque, até Granada e Córdoba, na atual Espanha.
Um marco relevante na tentativa de introduzir o sistema hindu-arábico na Europa foi a
publicação de Leonardo de Pisa (também conhecido por
), intitulada
(O Livro do Ábaco). O pai de Fibonacci era dono de casas de comércio
ultramarino, sendo uma no norte da África. Ainda jovem Fibonacci mudou-se para esta
região e conviveu com esta nova matemática e aprofundou seus conhecimentos no
sistema árabe de numerais e cálculo. Ao retornar a Pisa, Leonardo deu sequência a
seus estudos e publicou pela primeira vez em
o destacado livro, cujo conteúdo
introduzia a notação árabe, as operações fundamentais com números inteiros, cálculo
envolvendo séries, proporções, raízes quadradas e cúbicas, e uma breve abordagem
sobre geometria e álgebra. Neste livro foi apresentado o problema de crescimento da
população de coelhos de acordo com uma série que levou o nome de
. As
páginas do livro tornavam difíceis a reprodução de
exemplares dado que este processo era totalmente manual, o que limitou sua difusão.IV
O início da retomada, em
, do território ibérico dos mouros pelo rei da Espanha,
permitiu que populações árabes passassem ao domínio europeu, facilitando a absorção
do conhecimento escrito em árabe, principalmente os trabalhos de
.
Entretanto, foram necessários vários séculos para que o sistema hindu-arábico fosse
aceito de fato na Europa. O intervalo entre a queda do império romano e a era dos
descobrimentos se caracterizou como período das trevas em função da pouca
produção de conhecimento. Não foi diferente em relação ao sistema de numeração
hindu e da nova forma de realizar as operações aritméticas, que enfrentou resistência
frente aos métodos baseados no ábaco, herança dos romanos.
Uma parte do espaço deixado pela queda do império romano no ocidente no século
foi ocupada pela Igreja, que praticamente deu continuidade a utilização do sistema
numérico criado pelos romanos. A chegada dos árabes à Europa no século
trouxe
Introdução à Programação: Conceitos e Práticas.
Página 29
consigo o sistema de numeração hindu, que certamente em algum momento iria levar à
confrontação de sistemas.
Basta efetuar algumas operações aritméticas utilizando algarismos romanos, para
perceber as inegáveis vantagens que o sistema numérico hindu-arábico tem sobre o
sistema romano. Mesmo assim, o novo sistema de numeração acabou prevalecendo na
Europa somente no século
.
Atualmente quando comparamos as representações dos dígitos numéricos em árabe e
a forma ocidental observamos uma diferença sensível, e muitas vezes não atentamos
que possuem a mesma raiz. Porém, as grandes distâncias entre o Oriente Médio,
Península Ibérica e o extremo oriente combinadas com os séculos de história fizeram
que sequências de pequenas alterações na forma de representar os dígitos
resultassem em diferenças significativas na configuração final. Até o século
todo o
material produzido era escrito a mão, e diferentes copistas possuíam diferentes
caligrafias que associadas á direção da escrita (direita para a esquerda ou esquerda
para a direita) contribuíram para as sucessivas alterações nas aparências dos dígitos
numéricos.
A invenção da imprensa por Gutenberg no século
permitiu que tanto as letras
quanto os símbolos utilizados para representar os dígitos numéricos adquirissem uma
forma mais estável e definitiva.
A seguinte tabela ilustra as modificações sofridas na forma de representação dos
dígitos utilizados no sistema de numeração criado pelos hindus, adotado pelos árabes e
passado aos europeus:
Por volta do século
, os hindus
representavam os algarismos assim, ainda
sem um símbolo para o nada:
No século
, já com
representação evoluiu para:
o
,
a
No século
os hindus representavam os
dez dígitos assim:
No mesmo século
, os árabes que
estavam no Ocidente representaram assim:
No século
os árabes
empregavam esta representação:
orientais
Introdução à Programação: Conceitos e Práticas.
Página 30
As formas usadas pelos europeus nos
séculos
e
:
A representação ocidental atual:
1 2 3 4 5 6 7 8 9 0
A representação árabe escrita da esquerda
para a direita:
۱۲۳٤٥٦٧٨٩۰
Introdução à Programação: Conceitos e Práticas.
Página 31
3. Conceito de Bases
Em nosso cotidiano lidamos com números representados na base decimal. Isto se deve a
razões e históricas, talvez fundamentadas na quantidade de dedos nas mãos. Porém, os
computadores consolidaram o sistema binário como elemento de referência no projeto dos
circuitos. A utilização da base proporciona grande facilidade na representação eletrônica
e digital dos números e . A possibilidade de representar os dígitos binários através de
valores de tensões ou correntes, por exemplo,
e
, simplifica a construção dos
processadores e demais elementos de uma arquitetura. Combinado com este fato há toda
uma álgebra desenvolvida no contexto da informação binária/digital, que inclui uma série
de operações sobre dados binários/lógicos que serviu de base para a construção das
principais funcionalidades computacionais (memória, circuitos aritméticos, ...).
Um sistema de numeração é determinado fundamentalmente pela base, que é o número
de símbolos utilizados. A base é o coeficiente que estabelece o valor de cada símbolo de
acordo com a sua posição.
Na notação posicional os dígitos assumem valores diferentes para cada posição que
ocupa na representação do número.
Tomando o ponto
como separador para a parte inteira e a parte fracionária, temos que
a cada posição que se desloca o dígito a esquerda do ponto o seu valor é multiplicado
cumulativamente pela base. Da mesma forma, a cada posição que se desloca o dígito a
direita do ponto o seu valor é dividido cumulativamente pela base.
3.1.
Sistema Decimal
O sistema decimal é o mais comumente utilizado nas operações do dia a dia. O conjunto
de dígitos utilizado é:
{
} → Base
→
Símbolos.
Por exemplo, partindo do número decimal
, observa-se que cada dígito
possui um valor diferente dependendo da posição que ocupa no número, a saber:
Posição 2
Posição 1
Introdução à Programação: Conceitos e Práticas.
Posição 0
Posição -1
Página 32
Esta característica é um dos pilares do sistema decimal utilizado, dando-lhe o aspecto
, que atribui a cada posição do número um peso distinto. Decompondo
em uma somatória, levando em conta o peso da posição, tem-se:
As
parcelas
mostram
claramente,
através
da
, a contribuição de cada elemento
sistema de numeração utilizado.
sua
forma
geral
do
EXERCÍCIOS: Representar na forma de polinômio os seguintes números na base
:
i.
ii.
iii.
3.2.
Sistema Hexadecimal
O sistema hexadecimal tem todas as características do sistema decimal, porém utiliza
símbolos para a representação dos dígitos. Logo:
{
Os símbolos utilizados são os
com seus respectivos valores:
} → Base
→
Símbolos.
do sistema decimal, acrescidos dos seguintes símbolos,
Símbolo
Valor
Absoluto
EXERCÍCIOS: Representar na forma de polinômio os seguintes números na base
:
i.
ii.
iii.
Introdução à Programação: Conceitos e Práticas.
Página 33
3.3.
Sistema Binário
O sistema binário também tem todas as características do sistema decimal porém
utilizando dois dígitos:
{
} → Base → Símbolos.
É o sistema de numeração utilizado internamente pelos computadores modernos. Em
informática, cada dígito de um número representado neste sistema é denominado de bit
(binary digit). Além disso, alguns conjuntos destes bits recebem denominação específica,
a saber:


= conjunto de
(exemplo:
);
(
) = conjunto de ,
ou mais bytes, que determina a
capacidade de processamento do computador (exemplo:
palavra =
bits,
palavra =
, Arquitetura Pentium =
);

= conjunto de

(KBytes);
= conjunto de

(MBytes);
= conjunto de
: Quantities and units – Part 13: Information
, foram estabelecidos os seguintes prefixos:
De acordo com a norma
science and technology, de
Potência de 10
(GBytes);
Potência de 2
Nome Símbolo Nome Símbolo
Potência
Valor
quilo
k
kibi
Ki
1024
mega
M
mebi
Mi
1 048 576
giga
G
gibi
Gi
1 073 741 824
tera
T
tebi
Ti
1 099 511 627 776
peta
P
pebi
Pi
1 125 899 906 842 624
exa
E
exbi
Ei
1 152 921 504 606 846 976
zetta
Z
zebi
Zi
1 180 591 620 717 411 303 424
yotta
Y
yobi
Yi
1 208 925 819 614 629 174 706 176
Apesar de diferentes, é comum utilizar os termos das potências de
potências de .
Introdução à Programação: Conceitos e Práticas.
para se referir às
Página 34
EXERCÍCIOS: Representar na forma de polinômio os seguintes números na base :
i.
ii.
iii.
3.4.
Base Qualquer
É possível generalizar os conceitos anteriores para números em qualquer base, bastando
selecionar a quantidade de símbolos adequada, e seguir os princípios do sistema de
numeração, cuja essência é a
. Assim, uma base qualquer, pode ser
estabelecida da seguinte forma:
{
} → Base
representa o valor
Denotando um número
→
Símbolos, onde o último símbolo
.
na base
com seus dígitos, temos:
,
sendo a parte inteira com
dígitos e a parte fracionária com
. Expandindo na forma de polinômio, tem-se:
⋯
dígitos, sendo que
⋯
Ou, colocando este
somatório, tem-se:
sob a forma de
∑
Desta forma, temos todos os elementos para formar um sistema em qualquer base: os
dígitos
a base
e as posições em . Por exemplo, para a
, teria:
{
} → Base → Símbolos/Dígitos.
Uma determinada quantidade pode ser representada por diferentes números em
qualquer base. Quanto menor a base mais dígitos são necessários para representar a
mesma quantidade.
Introdução à Programação: Conceitos e Práticas.
Página 35
3.5.
Conversão entre Bases
Uma determinada quantidade pode ser representada de forma distinta dependendo da
base utilizada. Por exemplo, a quantidade
pode ser representada na base
como
, enquanto que em outras bases sua representação será diferente. Mais
especificamente, no mundo computacional é muito comum sermos requisitados a
interpretar informações codificadas em binário (
). Porém, estarmos habituados
ao sistema decimal, o que frequentemente demandará o uso de metodos de conversão
nos dois sentidos.
Além disso, é fundamental que um profissional da área de computação ou engenharia
relacionada, compreenda as transformações aplicadas a uma informação em todo o
seu trajeto, desde a forma natural no mundo real até a completa representação no
ambiente digital, tanto por software quanto pelo hardware.
Desta forma, serão apresentados métodos para realizar as seguintes conversões de
quantidades:
i.
ii.
iii.
3.5.1.
Conversão de Qualquer Base para a Base 10
Para converter de uma base
qualquer para a base
, basta aplicar o
de um número na base
:
∑
, e efetuar as operações tal como estamos habituados na base , e o
resultado obtido será nesta base .
Exemplos:
O número com as posições dos dígitos: (
)
O número com as posições dos dígitos: (
O número com as posições dos dígitos: (
Introdução à Programação: Conceitos e Práticas.
)
)
Página 36
É importante conhecer os limites estabelecidos em termos de quantidade de dígitos em
uma determinada base. Por exemplo, sabemos que com três dígitos decimais é possível
representar
quantidades distintas, que vão do número
ao número
.
Depreende-se que a maior quantidade representável é quando todas as posições forem
ocupadas pelo dígito de maior valor. Assim, para o sistema binário e para o tamanho de
um
, a maior quantidade possível de ser representada é obtida quando todos os bits
forem iguais a . A questão é: ―Quanto é este valor em decimal ?‖. A resposta vem da
conversão deste binário para decimal, conforme segue:
De uma forma geral, o equivalente decimal do maior número possível
representado por bits é obtido através da fórmula:
de ser
⋯
⋯
Observa-se que temos o somatório de uma Progressão Geométrica de
Para o caso em que
(1
termos:
) temos:
.
Introdução à Programação: Conceitos e Práticas.
Página 37
3.5.2.
Conversão da Base 10 para Qualquer Base
A conversão da base
para uma base qualquer é feita de forma distinta para a Parte
inteira e para a Parte fracionária:
i.
Parte inteira:

Divide-se a parte inteira pela base desejada, obtendo-se assim um quociente
e um resto. Repita esta divisão com o quociente, e assim sucessivamente
com os demais quocientes até obter quociente zero. Agrupe os restos,
conforme exemplo a seguir, para obter o número convertido para a base
desejada, sabendo que o primeiro resto é o dígito menos significativo;
Exemplos:
47
1
2
23
1
2
11
1
33
1
2
5
1
2
2
0
2
1
1
2
16
0
2
8
0
2
4
0
2
2
0
2
0
2
1
1
2
0
O dígito menos significativo de um número inteiro é aquele que ocupa a posição ,
sendo que o dígito mais significativo é aquele que ocupa a posição de maior ordem
. Quando se trata de um número binário, os termos utilizado são
e
, ou seus equivalentes em inglês:
e
. Também podem ser
encontrados os termos bit de mais baixa ou alta ordem.
235
3
8
29
5
8
3
3
2030
1
8
0
Introdução à Programação: Conceitos e Práticas.
16
126
14
16
7
7
16
0
Página 38
Vamos comprovar este processo utilizando a forma polinomial de representação do
número inteiro.
⋯
Efetuando a divisão deste polinômio por , temos:
⋯
⋯
⋯
Esta primeira divisão de inteiros produziu como resto o dígito . O quociente obtido foi
⋯
, que é um polinômio que representa um número composto
pelos
demais
dígitos,
deslocados
uma
posição
à
direita
. De fato, a divisão por
faz com que todos os dígitos sejam
deslocados uma posição à direita e elimina o dígito mais a direita. Assim, a lógica de
fundo é uma sequência de deslocamentos à direita e a obtenção de um dígito através
do resto. O término deste processo ocorre quando o quociente é zerado. Neste caso a
próxima divisão seria:
⋯
⋯
ii.
⋯
Parte fracionária

Multiplica-se a parte fracionária pela base desejada, obtendo-se assim um
número composto por uma parte inteira e uma parte fracionária. Repita este
processo para esta parte fracionária, e assim sucessivamente até que o
resultado obtido seja um inteiro ou quando a quantidade de dígitos desejada
foi alcançada. Agrupe as partes inteiras, conforme exemplo a seguir, para
obter o número convertido para a base desejada:
Introdução à Programação: Conceitos e Práticas.
Página 39
0.75 x 2 =
1.5
0.5 x 2 =
1.0
0.15
0.
0.60
0.20
0.40
0.80
0.60
0.20
0.40
0.80
x2=
x2=
x2=
x2=
x2=
x2=
x2=
x2=
x2=
2=
0.0378
0.6048
0.6768
0.8288
0.2608
0.1728
0.7648
0.2368
0.7888
0.6208
0.9328
0.924805
0.796875
0.75
0.44
0.52
0.16
0.28
0.24
0.92
0.36
0.88
0.04
0.32
0.3000
0.6000
1.2000
0.4000
0.8000
1.6000
1.2000
0.4000
0.8000
.6000
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x8=
x8=
x8=
x8=
x8=
x8=
x8=
x8=
x8=
x8=
0.6048
9.6768
10.8288
13.2608
4.1728
2.7648
12.2368
3.7888
12.6208
9.9328
14.9248
14.7969
12.7500
12.0000
3.5200
4.1600
1.2800
2.2400
1.9200
7.3600
2.8800
7.0400
0.3200
2.5600
⋯
⋯
Observe a dízima
Podemos verificar facilmente este método de conversão partindo da expansão do
número
na forma de polinômio.
⋯
⋯
Considerando somente a parte fracionária, temos:
⋯
Introdução à Programação: Conceitos e Práticas.
Página 40
Multiplicando o polinômio pela base B, temos:
⋯
⋯
=
Podemos interpretar através da parcela
que o dígito
foi deslocado para a
posição , ou seja, foi deslocado para assumir uma posição na parte inteira. De fato, a
multiplicação por
faz com que todos os dígitos sejam deslocados uma posição à
esquerda. Logo, a lógica de fundo é uma sequência de deslocamentos à esquerda e a
obtenção de um dígito por vez. Aplica-se novamente este processo para a nova parte
fracionária
. O término deste ciclo ocorre quando a parte fracionária
é zerada
, ou a quantidade de dígitos obtida já alcançou a precisão estabelecida.
3.6.
Exercícios
a) Converter para a base
os seguintes números que estão na base informada:
i.
ii.
iii.
iv.
v.
vi.
b) Converter para base informada os seguintes números que estão na base
:
i.
ii.
iii.
iv.
3.6.1.
Conversão da Base 2n para a Base 2
A conversão de uma base com potência inteira de
através do uso de uma tabela.
(
) para a base
pode ser feita
Sem a tabela, a conversão demandaria as seguintes transformações:
O uso da tabela evita os cálculos das duas conversões. Esta tabela de duas colunas
pode ser facilmente montada, como segue:
Introdução à Programação: Conceitos e Práticas.
Página 41
i.
ii.
3.6.2.
Relacionar na primeira coluna os dígitos da base
Escrever na segunda coluna o equivalente binário do valor de cada dígito
utilizando
;
Conversão da Base 4 para a Base 2
A tabela para a conversão da Base
Ao converter um número na base
respectiva combinação de bits.
para a Base
fica:
para a base , basta substituir cada dígito pela
Ao converter um número na base para a base , primeiro ajusta-se a quantidade de
bits da parte inteira e parte fracionária para uma quantidade múltipla de , e em seguida
substitui-se cada agrupamento de
pelo equivalente dígito da base . Este ajuste
não pode alterar o valor do número. Assim, quando necessário a parte inteira é
complementada com zeros a esquerda, e a parte fracionária é ajustada com zeros a
direita.
Exemplo:
Os agrupamentos e os complementos estão indicados em negrito.
3.6.3.
Conversão da Base 8 para a Base 2
A tabela para a conversão da Base
para a Base
Introdução à Programação: Conceitos e Práticas.
fica:
Página 42
Ao converter um número na base
respectiva combinação de bits.
para a base , basta substituir cada dígito pela
Ao converter um número na base
para a base , tomar os mesmos cuidados
anteriores e ajustar a quantidade de bits para um número múltiplo de .
Exemplo:
Os agrupamentos e os complementos estão indicados em negrito.
3.6.4.
Conversão da Base 16 para a Base 2
A tabela para a conversão da Base
Ao converter um número na base
respectiva combinação de bits.
para a Base
para a base
fica:
, basta substituir os dígitos pela
Ao converter um número na base
para a base
, tomar os mesmos cuidados
anteriores e ajustar a quantidade de bits para um número múltiplo de .
Exemplo:
Introdução à Programação: Conceitos e Práticas.
Página 43
A Conversão entre base
duas tabelas, ou seja:
3.7.
e base
, por exemplo, pode ser feita pela aplicação de
Exercícios
1. Converter para a base
i.
ii.
iii.
iv.
v.
vi.
vii.
viii.
ix.
x.
xi.
xii.
xiii.
⋯
os seguintes números que estão na base informada:
⋯
⋯
⋯
2. Converter para a base informada os seguintes números que estão na base
:
i.
ii.
iii.
iv.
v.
3. Converter os seguintes números:
i.
ii.
Introdução à Programação: Conceitos e Práticas.
Página 44
4. Operações com Números Binários
O conjunto de dígitos binários combinado com as operações aritméticas dão forma ao
sistema binário, cuja praticidade serviu de base para o surgimento da
e dos circuitos digitais. O seguinte diagrama ilustra as contribuições fundamentais para
o desenvolvimento da tecnologia digital.
Figura 24: Circuitos Digitais: Contribuições
4.1.
Operações Aritméticas
Na sequência são apresentadas as quatro operações aritméticas aplicadas a números
binários. O entendimento dos detalhes relativos a estas operações contribui para uma
melhor compreensão do funcionamento dos computadores, uma vez que a aritmética
binária é a base para a lógica digital.
4.1.1.
Soma
A soma de números binários é simplificada em relação à soma decimal, uma vez que é
necessário conhecer as somas possíveis para dois dígitos binários. Porém se o
resultado da soma de dois bits não couber em um bit, é produzido o bit de
. Este
é o caso da soma de
com , que resulta em
com
. Pode ocorrer que
somando com surja o bit
da soma anterior, produzindo
. Neste
caso, o resultado em binário é
, ou em decimal. A interpretação do
é que o
resultado é e ocorre o
. Assim, têm-se as seguintes combinações:





Introdução à Programação: Conceitos e Práticas.
Página 45
Exemplos:
11 1 1
111010101
+ 10010100
---------1001101001
4.1.2.
469
148
--617
11111111
11111111
+
1
---------100000000
255
1
--256
111111
10111100
+
1111111
---------100111011
188
127
--315
1 11
10011001
+ 10110100
---------101001101
153
180
--333
Subtração
A subtração de números binários é semelhante à soma binária, com atenção especial
quando é necessário o empréstimo para habilitar a subtração. Assim, têm-se as
seguintes combinações:




–
–
–
–
-1 2
2
-1-1
0
- 1
--1
0
- 1
--0
Neste caso – não é possível,
então empresta 1 da conta futura.
Este empréstimo vale 2, o que gera
, produzindo 1 como
resultado.
Neste caso – , tendo ainda que
pagar um empréstimo anterior não
é possível, então empresta 1 da
conta futura. Este empréstimo vale
2, o que gera
,
produzindo 0 como resultado.
Exemplos:
-
111010101
10010100
---------101000001
O símbolo
469
148
--321
11111111
11111111
1
---------11111110
255
1
--254
222222
*******2
10111100
1111111
---------00111101
188
127
--315
2 2
**2**2
10110100
- 10011001
---------00011011
180
153
--27
indica que houve um empréstimo para viabilizar a subtração.
Introdução à Programação: Conceitos e Práticas.
Página 46
4.1.3.
Multiplicação
O produto de dois números binários também fica simplificado uma vez que a tabela de
multiplicação dos dígitos se reduz a quatro combinações. A composição das parcelas é
feita através da soma. As combinações possíveis são:




Exemplos:
1101
13
11
3
------- --1101
1101
-------- --100111
39
11010
10
------00000
11010
-------110100
x
x
26
2
---
x
--52
1001
9
101
5
------- --1001
0000
1001
-------- --101101
45
10111
100
------00000
00000
10111
-------1011100
x
23
4
---
--92
Estes exemplos permitem constatar que a multiplicação binária é a soma de parcelas
oriundas da multiplicação de um dígito do primeiro operando pelo segundo operando.
Como o dígito será ou , logo as parcelas serão compostas ou por zero ou pelo
segundo operando. Além disso, observa-se o deslocamento dos bits a cada parcela.
Estas características reforça a simplificação proporcionada pela notação binária.
4.1.4.
Divisão
A divisão entre binários, apesar de não ser tão direta quanto à multiplicação, também é
simplificada, uma vez que o quociente final é montado a partir de quocientes parciais
que vão agregando
e
. Além disso, cada dígito do quociente inicia uma subtração
para completar o cálculo. Desta forma, a divisão é executada através de uma série de
subtrações. Observe o seguinte exemplo:
-1+2
1 0 1 1
1 1
1 0 1
1 1
0 1 0
1
0 0 0
resto
0
1 1
1 1 1
quociente
22
21
1
resto
3
7
quociente
0
1
1
Introdução à Programação: Conceitos e Práticas.
Página 47
O quadro da esquerda apresenta o processo de divisão binária e o quadro da direita
mostra os equivalentes decimais.
A divisão de
por
quantidade mínima de
̅̅̅̅̅ .
inicia pelo agrupamento da esquerda para a direita de uma
que seja divisível por
, que no caso seriam três bits:
10110
11
10
11
1
A divisão prossegue abaixando o próximo dígito e verificando se o grupo é maior ou
igual ao divisor. Não sendo, é abaixado o próximo dígito e adicionado o bit
ao
quociente. Segue outro exemplo:
101101
101
000101
101
0
101
1001
O resultado pode ser certificado pelo equivalente decimal, onde neste caso é
dividido por
, resultando em quociente
e resto .
4.1.5.
Exercícios
1. Somar os seguintes números em binário e hexadecimal:
i.
ii.
iii.
iv.
v.
vi.
vii.
2. Subtrair os seguintes números binários:
i.
ii.
iii.
–
–
–
Introdução à Programação: Conceitos e Práticas.
Página 48
3. Multiplicar os seguintes números binários:
i.
ii.
iii.
4. Dividir os seguintes números binários:
i.
ii.
iii.
4.2.
Operações Lógicas
A
ou
combina uma série de operações,
denominadas operações lógicas, aplicáveis ao conjunto de números { } produzindo
como resultado
ou . Constitui-se em um dos fundamentos mais importantes na
construção de circuitos digitais e consequentemente da arquitetura de um computador.
As operações lógicas podem ser implementadas em circuitos, denominados portas
lógicas, que por sua vez podem ser combinados na construção de circuitos mais
complexos, como circuito de soma, subtração dentre outros.
Além disso, o conjunto {
{
}, {
}, também pode ser mapeado como {
}, {
} ...
},
Na sequência a descrição das operações lógicas.
Introdução à Programação: Conceitos e Práticas.
Página 49
4.2.1.
NOT (NÃO)
A operação
requer apenas um argumento e produz um resultado. Esta
operação retorna o complemento de (negação ou inversão) do bit de argumento.
Circuito Equivalente
A lâmpada acenderá (
chave estiver aberta (
Circuito Eletrônico
) quando a
).
𝑉𝑐𝑐
𝑋
𝐴̅
𝐴
Símbolo para o Circuito Lógico
Representação da Operação
̅
Tabela Verdade
NOT 0
1
Introdução à Programação: Conceitos e Práticas.
1
0
Página 50
4.2.2.
AND (E)
A operação
requer dois argumentos e produz um resultado. O resultado será
quando as duas entradas forem , e para outras combinações.
Circuito Equivalente
A lâmpada
chaves e
acenderá (
) quando as
forem fechadas (
).
Circuito Eletrônico
𝑉𝑐𝑐
𝑋
𝑋
𝐴𝐵
̅̅̅̅
𝐴𝐵
𝐴
𝐵
Símbolo para o Circuito Lógico
Introdução à Programação: Conceitos e Práticas.
Página 51
Representação da Operação
Tabela Verdade
AND 0
0
0
1
0
1
0
1
Característica da Operação
A
representa todas as combinações da expressão lógica
onde os valores de , e estão representados nas seguintes células:
,
Nesta representação podemos constatar que terá valor somente quando os valores
de e também forem . As características da operação
podem ser extraídas da
tabela, observando o comportamento de . Na operação
, quando tem valor , a
linha correspondente em resulta inteira em , o que permite deduzir a característica
. Esta expressão pode ser lida como: independente do valor do bit
, quando
fazemos um
com , o resultado será sempre . Assim, o operador
tem a
característica de ser utilizado sempre que se precisa anular (
,
,
, ...)
bits.
Uma outra característica pode ser extraída analisando a linha de correspondente ao
valor de igual . Neste caso, esta segunda linha de é idêntica à linha do argumento
, o que permite deduzir a expressão
, ou seja: independente do valor do bit
, quando fazemos um
com , o resultado será sempre o valor do próprio bit ( ).
Observamos que a operação
se assemelha à operação aritmética de
multiplicação, o que lhe confere também a denominação de produto lógico.
Introdução à Programação: Conceitos e Práticas.
Página 52
Em muitas situações a tabela verdade pode ser construída no seguinte formato:
AND
A B
0 0
0 1
1 0
1 1
X
0
0
0
1
A coluna expressa os resultados da operação
aplicada linha a linha para cada
valor das colunas
e . A tabela possui quatro linhas ( ) em virtude de estarmos
trabalhando com a expressão lógica
contendo dois (
) argumentos ( e
). Neste caso, as colunas e representam todas as combinações de e possíveis
para duas variáveis. Em uma expressão lógica envolvendo variáveis a tabela verdade
conteria
linhas, e assim por diante.
Exemplo: Supor que temos um número inteiro
com
:
, e
desejamos obter um composto desta forma:
, ou seja com os quatro
bits altos iguais aos de e os quatro bits baixos zerados. Isto pode ser obtido fazendo a
operação
de
com um número bit a bit, tal que o resultado produza a
configuração desejada, ou seja:
ou
O número utilizado como argumento é normalmente chamado de
Introdução à Programação: Conceitos e Práticas.
(
).
Página 53
4.2.3.
OR (OU)
A operação
( ) requer dois argumentos e produz um resultado. O resultado será
quando as duas entradas forem , e para outras combinações.
Circuito Equivalente
A lâmpada apagará (
e forem abertas (
Circuito Eletrônico
) quando as chaves
).
𝑉𝑐𝑐
𝑋
𝑋
𝐴
𝐴
𝐵
̅̅̅̅̅̅̅̅
𝐴
𝐵
𝐵
Símbolo para o Circuito Lógico
Introdução à Programação: Conceitos e Práticas.
Página 54
Representação da Operação
Tabela Verdade
OR
0
1
0
0
1
1
1
1
Característica da Operação
Analisando a
características.
da operação
podemos extrair suas principais
Na operação
, a primeira linha de , quando
é igual a , é idêntica à linha do
argumento , o que permite deduzir a expressão
, ou seja: independente do
valor do bit
, quando fazemos um
com , o resultado será sempre o valor do
próprio bit ( ).
Quando tem valor , a linha correspondente em resulta inteira em , o que permite
deduzir a característica
. Esta expressão pode ser lida como: independente do
valor do bit
, quando fazemos um
com , o resultado será sempre . O operador
tem a característica de ser utilizado quando que se precisa
( ,
, ...)
bits.
Exemplo: Supor que temos um número inteiro
com
:
, e
desejamos obter um composto desta forma:
, ou seja com os quatro
bits altos iguais aos de e os quatro bits baixos ligados. Isto pode ser obtido fazendo a
operação
de com um número bit a bit, tal que o resultado produza a configuração
desejada, ou seja:
ou
Introdução à Programação: Conceitos e Práticas.
Página 55
4.2.4.
XOR / OU EXCLUSIVO
A operação
(
) requer dois argumentos e produz um resultado. É
semelhante ao
, porém quando os dois argumentos forem o resultado será . O
termo
se refere ao fato que dois argumentos
produz o resultado
.
Símbolo para o Circuito Lógico
Representação da Operação
Tabela Verdade
XOR 0
0
0
1
1
Característica da Operação
Analisando a
características.
1
1
0
̅ , onde ̅ significa a negação de
da operação
podemos extrair suas principais
Na operação
, a primeira linha de , quando é igual a , é idêntica à linha do
argumento , o que permite deduzir a expressão
, ou seja: independente do
valor do bit
, quando fazemos um
com , o resultado será sempre o valor do
próprio bit ( ).
Quando tem valor , a linha correspondente em resulta em valores invertidos em
̅ . O operador
relação ao argumento , o que permite deduzir a característica
Introdução à Programação: Conceitos e Práticas.
Página 56
tem a característica de ser utilizado quando se quer inverter (
o valor de um bit específico.
,
,
)
Exemplo: Supor que temos um número inteiro
com
:
, e
̅̅̅̅̅̅̅̅̅̅̅̅̅, ou seja com os
desejamos obter um
composto desta forma:
quatro bits altos iguais aos de e os quatro bits baixos invertidos. Isto pode ser obtido
fazendo a operação
de A com um número bit a bit, tal que o resultado produza a
configuração desejada, ou seja:
ou
A operação
4.2.5.
i.
pode ser utilizada para realizar uma criptografia básica. Efetuando
, e em seguida calculando
, produz-se novamente o valor de .
Exemplos
Montar a tabela verdade para a seguinte expressão lógica
circuito lógico equivalente.
. Desenhar o
A tabela deverá considerar os valores possíves para ,
e
e o resultado . A
quantidade de linhas da tabela deve conter todas as combinações para os valores de ,
e . Como cada uma destas variáveis admitem os valores
, logo as três variáveis
produzirão
ou linhas. Por conveniência podem ser adicionadas colunas com valores
intermediários o que confere maior clareza na obtenção da coluna com o resultado final.
Assim, a tabela final seria:
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
0
0
0
0
0
1
1
0
1
0
1
0
1
1
1
O circuito lógico equivalente é:
Introdução à Programação: Conceitos e Práticas.
Página 57
ii.
Montar a tabela verdade para a seguinte expressão lógica
circuito lógico equivalente.
A tabela deverá considerar os valores possíves para
linhas. Assim, a tabela final seria:
0
0
1
1
0
1
0
1
1
1
0
0
1
0
1
0
0
0
1
0
e
0
1
0
0
. Desenhar o
e o resultado . Serão
ou
0
1
1
0
Observe que o resultado de coincide com a tabela verdade do operador
a operação
entre e equivale a expressão lógica
.
. De fato
O circuito lógico equivalente é:
Uma notação alternativa mais compacta utiliza um círculo na entrada da porta principal
para denotar a operação
, conforme ilustra o seguinte diagrama:
Introdução à Programação: Conceitos e Práticas.
Página 58
4.2.6.
Exercícios
Montar a tabela verdade e o circuito lógico para cada uma das expressões abaixo:
i.
ii.
iii.
iv.
v.
vi.
vii.
viii.
ix.
x.
xi.
xii.
xiii.
xiv.
xv.
xvi.
xvii.
4.3.
̅̅̅̅̅̅̅̅
Operações Aritméticas Binárias com Circuitos Lógicos
Este tópico faz a correlação entre as operações de soma e subtração de binários com
expressões lógicas e finalmente com circuitos lógicos. É importante destacar que este
material apresenta uma breve introdução aos conceitos de circuitos lógicos e não se
aprofunda nas questões relacionadas com redução de expressões.
Introdução à Programação: Conceitos e Práticas.
Página 59
4.3.1.
Somador Completo
É possível relacionar a operação de soma aritmética com as operações lógicas. Para
isto, temos que montar uma tabela verdade completa para a soma de com e
,
produzindo como resultado e um novo
.
A tabela abaixo mostra todas as combinações para
. A coluna
resultado da soma
e a coluna
o
resultante.
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
1
1
0
1
0
0
1
contém o
0
0
0
1
0
1
1
1
Apenas com os conhecimentos até o momento apresentados, é possível observar que
a coluna pode ser obtida por
. Já
pode ser obtido por
para as quatro primeiras linhas, quando
,e
para as quatro últimas,
quando
. Combinando as duas equações para
, tem-se
que também pode ser escrita como
. A seguinte tabela
verdade mostra que o valor de
é o mesmo para as duas expressões e idêntico aos
valores obtidos na tabela verdade da soma binária completa:
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
1
1
1
0
1
1
1
0
1
1
0
0
1
1
0
0
0
0
0
0
1
1
1
0
0
0
1
0
0
0
1
0
0
0
0
0
1
1
0
0
0
0
1
0
1
1
1
0
0
0
1
0
1
1
1
Utilizando as portas lógicas é possível montar facilmente um circuito somador completo,
que receba
e produza
, como na figura abaixo:
Introdução à Programação: Conceitos e Práticas.
Página 60
Figura 25: Circuito Somador Completo de 1 bit.
Este circuito é capaz de realizar a soma de bit. Para somar um inteiro com mais bits,
basta sequenciar vários somadores completos. Por exemplo, se o projeto da
prevê
a soma de dois inteiros de
, então o circuito poderia ser similar á:
Figura 26: Circuito da Soma de N bits.
4.3.2.
Subtrator Completo
A abordagem feita para o somador completo pode ser aplicada para o subtrator
completo. Para isto, temos que montar uma Tabela Verdade completa para a subtração
de por com eventual pagamento do
, produzindo como
resultado e um novo indicador de
.
Introdução à Programação: Conceitos e Práticas.
Página 61
A tabela abaixo mostra todas as
resultado da subtração
0
0
0
0
1
1
1
1
combinações para
e a coluna
o
0
0
1
1
0
0
1
1
0
1
0
1
0
1
0
1
0
1
1
0
1
0
0
1
Por exemplo, as linhas
e
com os valores
entendidas como sendo as seguintes operações:
. A coluna
resultante.
0
1
0
0
1
1
0
1
e
2
-1 0
2
-1-1
0
- 1
--1
0
- 1
--0
Neste caso – não é possível,
então empresta
da conta futura.
Este empréstimo vem somando , o
que gera
, produzindo
como resultado.
contém o
para
são
Neste caso – , tendo ainda que
pagar um empréstimo anterior não
é possível, então empresta
da
conta futura. Este empréstimo vem
somando , o que gera
,
produzindo
como
resultado.
De modo similar à soma, é possível observar que a coluna
pode ser obtida por
. Já
pode ser obtido por
para as quatro primeiras linhas
e
para as quatro últimas. Combinando as duas equações para
, temse
. Também é possível obter
para as quatro
primeiras linhas e
para as quatro últimas. Combinando as duas equações
para
, tem-se
(
). Esta última expressão pode ser
trabalhada para reduzir o número de portas lógicas do circuito final e aproveitar uma
operação
do cálculo de e chega-se a
(
).
Introdução à Programação: Conceitos e Práticas.
Página 62
Um circuito lógico para o subtrator completo seria:
Figura 27: Circuito Subtrator Completo de 1 bit.
Introdução à Programação: Conceitos e Práticas.
Página 63
5. Representação de Dados
A figura abaixo ilustra a separação entre as informações que circulam no mundo real e
seus equivalentes no mundo digital. Estão exemplificadas informações clássicas, tais
como números e textos. Para entrar no mundo digital é fundamental que o dado exterior
seja convertido para
e
através de algum método ou convenção.
Figura 28: Mundo Real x Mundo Digital.
Os métodos aqui apresentados serão agrupados conforme segue:
Representação
de Dados
Números
Inteiros
Reais
Inteiro sem
sinal
Binário Puro
Textos
Inteiro com
sinal
MóduloSinal
Complemento de 1
Complemento de 2
Excesso de
2n-1
Figura 29: Métodos de Representação de Dados
Introdução à Programação: Conceitos e Práticas.
Página 64
Na representação de dados no mundo digital é necessário definir uma quantidade de
bits disponíveis para o enquadramento do dado. No caso de números inteiros,
normalmente as arquiteturas e as linguagens disponibilizam os tamanhos com
e
. Para os exemplos que seguem adotaremos o tamanho de
, até
que se informe o contrário.
5.1.
Representação de Números Inteiros
Na sequência são apresentados os métodos mais referenciados para representação de
números inteiros. Inicialmente será considerado tamanho
.
5.1.1. Inteiros Sem Sinal – Binário Puro
A representação de inteiros sem sinal é simplesmente a conversão do número desejado
para
no tamanho estabelecido.
Exemplo
Representação
00001010
01011101
01111111
00000000
11111111
100000000  Não foi possível representar em 8 bits.
Assim, a faixa de representação é dada por:
5.1.2. Inteiro Com Sinal
A representação de inteiros com sinal demanda algum artifício para codificar o sinal no
padrão digital. Na sequência são apresentados os quatro métodos mais conhecidos.
5.1.2.1.
Módulo Sinal
O método
( ) utiliza o bit mais significativo para codificar o sinal do
número e os demais bits codificam a magnitude do número em binário.
Introdução à Programação: Conceitos e Práticas.
Página 65
Figura 30: Representação em Módulo-Sinal
Exemplo
Representação
00001010
10001010
01111111
00000000
10000000
010000000  Não foi possível representar em 8 bits.
110000000  Não foi possível representar em 8 bits.
11111111
01100100
Assim, a faixa de representação é dada por:
5.1.2.2.
Complemento de 1
O método
consiste na conversão do valor absoluto
(magnitude) de para binário. Se o número for negativo, segue-se com a inversão dos
bits (toma-se o complemento do que falta para que cada bit de seja ).
Introdução à Programação: Conceitos e Práticas.
Página 66
Exemplo
Representação
00001010
:
00001010
C-1:
11110101  Ok
01111111
00000000
:
00000000
C-1:
11111111  Ok
10000000  Sinal inconsistente. Não foi possível
representar em 8 bits.
:
10000000
C-1:
01111111 Sinal inconsistente. Não foi
possível representar em 8 bits.
:
01111111
C-1:
10000000  Ok
01100100
Assim, a faixa de representação é dada por:
5.1.2.3.
Complemento de 2
O método
consiste na conversão do valor absoluto de para
binário. Se o número for negativo, segue-se com a inversão dos bits (toma-se o
complemento do que falta para que cada bit de seja ) e soma-se a este
.O
último
é desprezado.
Introdução à Programação: Conceitos e Práticas.
Página 67
Exemplo
Representação
00001010
:
C-1:
+
C-2:
01111111
00000000
:
C-1:
00001010
11110101
1
-------11110110  Ok
00000000
11111111
+
1
-------C-2:
00000000  Ok
10000000  Sinal inconsistente. Não foi possível
representar em 8 bits.
:
10000000
C-1:
01111111
+
1
-------C-2:
10000000  Ok
:
01111111
C-1:
10000000
+
1
-------C-2:
10000001  Ok
01100100
Assim, a faixa de representação é dada por:
O método
proporciona a mesma representação para o
5.1.2.4.
Excesso de 2N-1
e
.
O método de Excesso de
consiste em somar a o valor de
, e então codificar
esta soma em binário. Se o resultado desta soma for negativo ou exceder a quantidade
de bits permitida, então o valor de estará fora da faixa para os
definidos para a
representação.
Introdução à Programação: Conceitos e Práticas.
Página 68


, verificar coerência do sinal


O método
também proporciona a mesma representação para o
e
. A
notação de sinal na representação final é invertida em relação aos demais métodos.
Exemplo
Representação
10001010  Ok
01110110  Ok
11111111  Ok
:
10000000  Ok
:
10000000  Ok
:
100000000  Não foi
possível representar em 8 bits.
:
00000000  Ok
:
00000001  Ok
:
11100100  Ok
:
:
:
Assim, a faixa de representação é dada por:
5.1.2.5.
Visualização
Podemos facilmente visualizar a relação entre um número do mundo real e sua
representação no mundo digital. O quadro abaixo ilustra uma sala com várias cadeiras,
onde as cadeiras são numeradas em binário com
.
Inteiro sem sinal
Binário Puro
0
00..00
1
00.01
...
...
127
01..11
128
10..00
129
10.01
...
...
255
11..11
Introdução à Programação: Conceitos e Práticas.
Página 69
Do lado do mundo real uma determinada família de números quer adentrar ao mundo
digital e ocupar uma cadeira. A primeira restrição é o tamanho da sala. Não há cadeiras
para todos os elementos da família, apenas alguns poderão ocupar um assento. No
caso da família dos
, a sala típica com cadeiras numeradas com
, estarão disponíveis
cadeiras, desde a cadeira
até a
.O
de valor ocupará a cadeira
, o valor ocupará a cadeira
, e assim por diante até o valor
que ocupará a cadeira
. O
protocolo de conversão determina qual a cadeira a ser ocupada por um determinado
valor. No caso dos
vimos que o método utilizado para conversão é o
. As características da sala permitem que apenas os valores definidos por
, poderão ser representados. Caso seja necessário abranger uma faixa
maior, deverá ser utilizada uma sala com cadeiras maiores, ou seja com maior
quantidade de bits.
Para a família dos
conversão:
, temos uma sala para cada protocolo de
,
e
,
Inteiro com sinal
Módulo-Sinal
Complemento de 1
+0
00..00
+1
00.01
...
...
+127
01..11
+0
00..00
+1
00.01
...
...
+127
01..11
-0
10..00
-1
10.01
...
...
-127
11..11
-127
10..00
-126
10.01
...
...
-0
11..11
Complemento de 2
Excesso
±0
00..00
+1
00.01
...
...
+127
01..11
-128
00..00
-127
00.01
...
...
-1
01..11
-128
10..00
-127
10.01
...
...
-1
11..11
±0
10..00
+1
10.01
...
...
+127
11..11
Nas salas do
e do
podemos visualizar que o número
, tanto o
quanto o
, ocupam distintas cadeiras, o que caracteriza uma
desvantagem do método, pois uma destas cadeiras poderia ser ocupada por mais um
elemento dos
. Nas salas do
e do
constatamos que o
, quer seja o
ou o
, são levados, como consequência do
método, para a mesma cadeira, o que acaba liberando um assento para o
.
Introdução à Programação: Conceitos e Práticas.
Página 70
5.1.3. Soma em Complemento de 2
A representação em
traz uma grande vantagem para a operação de
soma, pois trata de forma transparente os inteiros sem sinal e com sinal.
Tomemos como exemplo a seguinte soma de binários, para um
Exemplo
1111
00001111
+ 10001001
-------10011000
Inteiro sem Sinal
Binário Puro
15
+ 137
----152
Inteiro com Sinal
Complemento de 2
C-2 10001001
1
-------C-1 10001000
|X| 01110111
X = -119
C-2 10011000
1
-------C-1 10010111
|X| 01101000
X = -104
15
+ -119
-----104
O que se observa é que independente da interpretação dada ao binário, se inteiro sem
sinal ou inteiro com sinal em
, o resultado é coerente.
Na sequência são apresentados exemplos com algumas incoerências nos resultados
das somas de inteiros sem sinal e nas somas de inteiros com sinal. Pode ser observada
facilmente a lógica destas incoerências, a saber:

Quando somamos dois inteiros sem sinal e ocorre o
no último bit então
estamos diante de um
, ou estouro de capacidade.

Quando somamos dois inteiros com sinal deve ser observada a coerência dos
sinais: Soma de positivos deve gerar resultado positivo e soma de negativos
deve gerar resultado negativo.
Exemplo
1111
01111001
+ 01101010
-------11100011
Inteiro sem Sinal
Binário Puro
121
+ 106
----227
(ok)
Introdução à Programação: Conceitos e Práticas.
Inteiro com Sinal
Complemento de 2
121
+ 106
------29
C-2 11100011
1
-------C-1 11100010
|X| 00011101
X = -29
(overflow)
Página 71
11 1
11001001
+ 11101110
-------10110111
201
+ 238
----183
-55
+ -18
------73
(overflow)
1
11
10000101
+ 10001110
-------00010011
133
+ 142
----19
(ok)
-123
+ -114
-----+ 19
(overflow)
(overflow)
C-2 11001001
1
-------C-1 11001000
|X| 00110111
X = -55
C-2 11101110
1
-------C-1 11101101
|X| 00010010
X = -18
C-2 10110111
1
-------C-1 10110110
|X| 01001001
X = -73
C-2 10000101
1
-------C-1 10000100
|X| 01111011
X = -123
C-2 10001110
1
-------C-1 10001101
|X| 01110010
X = -114
5.1.4. Exercícios
1. Obtenha os valores de X que a sequência de binário representa para cada um
dos métodos:
BP
0000
1000
1111
0111
1000
1111
MS
C–1
C–2
1111
1101
0000
1111
0000
1111
Introdução à Programação: Conceitos e Práticas.
Página 72
5.2.
Representação de Números Reais
A representação de números reais é mais complexa e exige a codificação de vários
componentes de . Os passos para se chegar a representação digital incluem:
i.
ii.
iii.
Converter para a base
Normalizar
Enquadrar
Exemplo:
i.
Converter
para a base
101110.
ii.
0.32
0.12
0.92
0.72
0.52
x16 = 5.12
x16 = 1.92
x16 = 14.72
x16 = 11.52
x16 = 8.32
Normalizar
Normalizar equivale a reescrever o número binário na notação científica,
reposicionando o ―ponto decimal‖ a frente do primeiro dígito
e fazendo a devida
compensação multiplicando-se o binário por
, onde
é o número de casas
deslocadas, sendo quando para esquerda e quando para a direita.
Assim, tem-se a seguinte forma geral para um número normalizado:
, onde:

, com exceção quando
Introdução à Programação: Conceitos e Práticas.
. Todas as partes serão .
Página 73

será um inteiro com sinal.
Os componentes que devem ser representados são o
iii.
eo
.
Enquadrar
Agora, resta enquadrar as partes de
em um determinado padrão codificado em
binário. Para os nossos exemplos, até que se coloque em contrário, adotaremos o
seguinte padrão para números reais:

Serão 24 bits assim divididos:
S
Expoente ( )
Mantissa (
o O bit de Sinal será
para
positivo
ou
)
para
negativo
o Os bits do campo Expoente acomodarão a codificação de como inteiro
com sinal em algum dos métodos apresentados. Normalmente utiliza-se
ou
; Nos exemplos que seguem utilizaremos
.
o O campo Mantissa deverá acomodar os
decimal‖ da notação normalizada.
S
0
0
0
Expoente ( )
0 0 1 1
0
1
0
o O Sinal ficou com , pois
o O Expoente ficou
1
1
1
0
bits que veem após o ―ponto
Mantissa ( )
0 1 0 1 0
0
0
1
1
1
é positivo;
, pois
o A Mantissa ficou
pela notação.
, e a codificação é em
, pois são os
;
bits comportados
Exemplo:
i.
Converter
para a base
0.004600000
0.073600000
0.177600000
0.841600000
Introdução à Programação: Conceitos e Práticas.
x 16 =
x 16 =
x 16 =
x 16 =
0.073600000
1.177600000
2.841600000
13.465600000
Página 74
0.465600000 x 16 =
0.449600000 x 16 =
7.449600000
7.193600000
⋯
ii.
Normalizar
iii.
Enquadrar
Agora, resta enquadrar as partes de
S
1
1
1
Expoente (7)
1 1 0 0
1
1
0
no padrão estabelecido em binário.
0
1
0
1
Mantissa (16)
1 0 1 0 1
1
1
0
1
1
Onde a parte do Expoente foi obtida da seguinte forma:
BP:
0000111
C-1: 1111000
+
1
-------C-2: 1111001  Ok
Ou simplesmente:
No caso de representação de números reais, é importante conhecer a capacidade da
notação, principalmente as características de amplitude e precisão. A estrutura do
exemplo não é capaz de representar todos os números reais com precisão infinita.
Logo, a técnica utilizada mapeia apenas um subconjunto dos números reais. Considere
a reta dos reais abaixo indicada:
Introdução à Programação: Conceitos e Práticas.
Página 75
Figura 31: Faixa de Representação de Números Reais.
Nem todos os pontos das retas dos reais são representados. Neste caso interessa
conhecer os maiores e os menores números representáveis. Estes limites são
calculados a partir da equação normalizada:
O Maior Positivo (
) é obtido com o produto da maior Mantissa (
⋯ ) com o
maior valor de , onde
e a representação em
. Neste caso temos a
seguinte faixa para o Expoente ( ):
. Assim, tem-se:
Como:
Logo:
O Menor Positivo ( ) é obtido com o produto da menor Mantissa (
valor de . Assim, tem-se:
) com o menor
Logo:
Introdução à Programação: Conceitos e Práticas.
Página 76
5.2.1. Formato IEEE 754
O IEEE padronizou algumas representações de números reais na norma IEEE
(IEC
). A maioria dos computadores modernos adota este padrão. O seguinte quadro
relaciona os tipos disponibilizados nesta norma:
Tipo
Half
Single
Double
Double extended
(80-bit)
Quad
Detalhando o tipo
S
Sinal
Expoente
Mantissa
Total
bits
1
1
1
5
8
11
10
23
52
16
32
64
15
127
1023
11
24
53
Dígitos
Significativos
Decimal
~3.3
~7.2
~15.9
1
15
64
80
16383
64
~19.2
1
15
112
128
16383
113
~34.0
Expoente
bias
Bits
Precisão
, tem-se a seguinte estrutura:
Expoente ( )
o O bit de Sinal é
Mantissa (
para
positivo
ou
para
)
negativo
o Os
do campo
acomodam a codificação de como inteiro
com sinal utilizando um método semelhante ao
, porém com um
de
, que para
é
. A faixa de representação é de
.
o O campo
acomoda
, porém com um diferencial. Quando
se normaliza um número binário, a mantissa sempre iniciará com o dígito
, com exceção para o número zero. Assim, este dígito fica implícito,
sem a necessidade de ocupar fisicamente um posição na notação. Logo,
os
representam uma precisão real de
.
Exemplo:
i.
Converter X para a base 2
11.
0.141592654
0.265482457
0.247719319
0.963509104
0.416145661
Introdução à Programação: Conceitos e Práticas.
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
2.265482457
4.247719319
3.963509104
15.416145661
6.658330571
Página 77
0.658330571
0.533289135
0.532626152
0.522018433
x 16 =
x 16 =
x 16 =
x 16 =
10.533289135
8.532626152
8.522018433
8.352294922
⋯
⋯
ii.
Normalizar
Observe que o primeiro bit da mantissa reposicionado na parte inteira ficará oculto na
representação.
iii.
Enquadrar
Agora, resta enquadrar as partes de X no padrão binário IEEE.
Onde a parte do Expoente foi obtida da seguinte forma:
, em Excesso com bias de
Ou simplesmente:
5.2.2. Exercícios
i. Representar em números reais os seguintes números:









–
Introdução à Programação: Conceitos e Práticas.
Página 78

–
ii. Que números estão representados pelas seguintes codificações binárias:



Introdução à Programação: Conceitos e Práticas.
Página 79
5.3.
Representação de Informações Textuais
A representação de informações textuais é feita através de um acordo que convenciona
atribuir para cada caractere um código numérico. A convenção mais aceita é dada por
uma tabela denominada Tabela
(acrônimo para American Standard Code for
Information Interchange, ou em português "Código Padrão Americano para o
Intercâmbio de Informação"). Desenvolvida a partir de
, grande parte das
codificações de caracteres modernas tomam esta tabela como base.
Caracteres não imprimíveis (
):
Representados como a parte não imprimível da tabela
, os caracteres de controle
tiveram sua origem nos primórdios da computação, quando se usavam máquinas
teletipo e fitas de papel perfurado.
Binário
0000 0000
0000 0001
0000 0010
0000 0011
0000 0100
0000 0101
0000 0110
0000 0111
0000 1000
0000 1001
0000 1010
0000 1011
0000 1100
0000 1101
0000 1110
0000 1111
0001 0000
0001 0001
0001 0010
0001 0011
0001 0100
0001 0101
0001 0110
0001 0111
0001 1000
0001 1001
0001 1010
0001 1011
0001 1100
0001 1101
Decimal
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Hexa
0
1
2
3
4
5
6
7
8
9
0A
0B
0C
0D
0E
0F
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
Controle
^@
^A
^B
^C
^D
^E
^F
^G
^H
^I
^J
^K
^L
^M
^N
^O
^P
^Q
^R
^S
^T
^U
^V
^W
^X
^Y
^Z
^[
^\
^]
Abreviação
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
HT
LF
VT
FF
CR
SO
SI
DLE
DC1
DC2
DC3
DC4
NAK
SYN
ETB
CAN
EM
SUB
ESC
FS
GS
Introdução à Programação: Conceitos e Práticas.
Descrição
Null
Nulo
Start of Header
Início do cabeçalho
Start of Text
Início do texto
End of Text Fim do texto
End of Tape
Fim de fita
Enquire
Interroga Term ID
Acknowledge
Reconhecimento
Bell
Campainha
Back-space
Espaço atrás
Horizontal Tab
Tabulação horizontal
Line-Feed
Alimenta linha
Vertical Tabulation
Tabulação vertical
Form-Feed
Alimenta formulário
Carriage-Return
Enter
Shift-Out
Saída do shift
Shift-In
Entrada no shift
Data-Link Escape
Device-Control 1
Device-Control 2
Device-Control 3
Device-Control 4
Neg-Acknowledge
Não-reconhecimento
Synchronous Idle
End-of-Transmission
Cancel
End-Of-Medium
Substitute
Escape
File Separator
Group Separator
Página 80
0001 1110
0001 1111
0111 1111
30
31
127
1E
1F
7F
^^
^_
^?
Caracteres não imprimíveis (
Estendidos (
):
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Caracter
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
RS
US
DEL
Record Separator
Unit Separator
Delete
), Caracteres imprimíveis (
) e Caracteres
0
1
2
3
4
5
6
7
8
9
10 11 12 13 14 15
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
BEL
BS
HT
LF
VT
FF
CR
SO
SI
ETB CAN
EM
SUB
ESC
FS
GS
RS
US
'
7
G
W
g
w
ç
ù
º
À
Ã
Î
þ
¸
)
9
I
Y
i
y
ë
Ö
®
╣
╔
┘
Ú
¨
*
:
J
Z
j
z
è
Ü
¬
║
╩
┌
Û
·
+
;
K
[
k
{
ï
ø
½
╗
╦
█
Ù
¹
,
<
L
\
l
|
î
£
¼
╝
╠
▄
ý
³
=
M
]
m
}
ì
Ø
¡
¢
═
¦
Ý
²
.
>
N
^
n
~
Ä
×
«
¥
╬
Ì
¯
▔
/
?
O
_
o
•
Å
ƒ
»
┐
¤
▀
´
NUL SOH STX
DLE
0
@
P
`
p
Ç
É
á
░
└
ð
Ó
ETX
EOT ENQ ACK
DC1 DC2 DC3 DC4 NAK SYN
!
1
A
Q
a
q
ü
æ
í
▒
┴
Ð
ß
±
"
2
B
R
b
r
é
Æ
ó
▓
┬
Ê
Ô
‗
#
3
C
S
c
s
â
ô
ú
│
├
Ë
Ò
¾
$
4
D
T
d
t
ä
ö
ñ
┤
─
È
õ
¶
%
5
E
U
e
u
à
ò
Ñ
Á
┼
ı
Õ
§
&
6
F
V
f
v
å
û
ª
Â
ã
Í
µ
÷
(
8
H
X
h
x
ê
ÿ
¿
©
╚
Ï
Þ
°
. Caracter
.
Exemplo: O texto
seria codificado como uma sequência de bytes
equivalentes aos seguintes códigos:
J
o
a
o
d
a
74 111 97 111 32 100 97
Introdução à Programação: Conceitos e Práticas.
32
S
i
l
v
a
83 105 108 118 97
Página 81
Exemplo: O texto
equivalentes aos seguintes códigos:
A
v
B
r
a
s
I
l
,
seria codificado com os binários
3
2
2
.
A
p
t
º
1
0
65 118 32 66 114 97 115 73 108 44 32 51 50 50 46 32 65 112 116 186 32 49 48
6
54 67
Os caracteres estendidos podem ser diferentes dependendo da fonte. Neste último
exemplo, os códigos foram obtidos através de um recurso da planilha Excel, o que
justifica algumas diferenças em relação à tabela acima.
Introdução à Programação: Conceitos e Práticas.
C
Página 82
6. Introdução a Arquitetura
A arquitetura de um computador é um modelo da organização e funcionamento de um
sistema de processamento. A descrição da arquitetura destaca as funções dos
componentes básicos de um computador, a interconexão destes componentes e o
modo como os componentes interagem. A maioria das arquiteturas está baseada na
proposta de
:
Figura 32: Organização típica de um computador.
A dinâmica da execução de um programa inicia quando o usuário submete um
determinado arquivo executável para ser processado pelo computador. Inicialmente
este programa está contido em um arquivo e o primeiro passo é carrega-lo para a
memória principal (
–
) onde ocupará um espaço
designado pelo Sistema Operacional. Neste espaço, uma área conterá os bytes
correspondentes às instruções do programa e outra área é reservada ao
armazenamento de resultados provenientes da execução destas instruções. Esta última
área também é denominada área de dados. A seguinte figura ilustra de forma
simplificada o uso da memória por um programa em execução:
Introdução à Programação: Conceitos e Práticas.
Página 83
INSTRUÇÕES
(código)
DADOS
RAM
A:
B:
C:
X:
Y:
Z:
T:
mov
add
mov
mov
mov
sub
mov
add
mov
eax, A
eax, B
C, eax
ebx, eax
eax, X
eax, Y
Z, eax
ebx, eax
T, eax
1111
1110
1101
1100
1011
1010
1001
1000
0111
0110
0101
0100
0011
0010
0001
0000
Figura 33: Programa na Memória RAM: Código + Dados.
A execução do programa inicia pelo processamento da instrução que estiver no
endereço de memória designado como início do código. A primeira instrução é então
levada da memória para a
onde é tratada e processada, e quando for o caso, um
resultado é armazenado na memória ou na própria
. Em seguida o mesmo
tratamento é dado para a segunda instrução e assim até o término do programa,
quando o mesmo é liberado da memória.
A gestão deste ambiente é feita pelo Sistema Operacional, enquanto que a
é
responsável pelo ciclo de execução da instrução. Observa-se que durante a execução
de um programa há um forte trânsito de dados entre a
e a memória principal
(
). A
trabalha em uma velocidade muito superior a velocidade da memória
RAM. Assim, durante a execução do programa a
passa muito tempo aguardando
os bytes chegarem da/na
, o que acarreta desperdício deste recurso precioso que
é a
. Este limitante onde
é comumente chamado de Gargalo de Von
Newmann.
Segue uma descrição resumida dos elementos que formam a arquitetura apresentada:

Processador (
) é o componente ativo, controlador de todo o sistema. É o
processador que realiza todas as operações sobre os dados, de acordo com o
indicado pelas instruções no código do programa.

memória principal (
) armazena as instruções que são executadas pelo
processador, e os dados que serão manipulados.

interfaces de entrada e de saída (
) são as portas de comunicação para o
mundo externo, às quais estão conectados os dispositivos periféricos tais como
vídeo, teclado, discos e impressora.
Introdução à Programação: Conceitos e Práticas.
Página 84

Estes componentes estão interconectados por meio de um
, através
do qual o processador realiza o acesso a instruções e dados armazenados na
memória principal.

É também através deste mesmo barramento que o processador recebe ou envia
dados de ou para as interfaces de entrada/saída.

Instruções e dados estão armazenados em
principal.
6.1.
, na memória
Processador - CPU
A estrutura básica de um processador é composta normalmente por uma
e uma
. A figura a seguir ilustra uma
–
Central Processing Unit – simplificada:
Figura 34: Unidade Central de Processamento típica.
A
pode ser vista como uma fábrica que processa matéria prima gerando produtos.
Neste cenário a
é a responsável pelo gerenciamento da fábrica,
incluindo a entrada da matéria prima, a fabricação do produto e a entrega deste
produto. Cada instrução recebida pela
se assemelha a chegada
de uma ordem de serviço para fabricação de um produto. Inicialmente o gerente da
fábrica busca compreender a instrução de fabricação do produto, partindo em seguida
Introdução à Programação: Conceitos e Práticas.
Página 85
para o preparo da linha de produção para a fabricação, e uma vez pronto, o produto é
encaminhado para o depósito, de onde tomará seu destino final.
6.1.1.
Seção de Controle
As operações básicas que ocorrem dentro da seção de processamento são todas
comandadas pela unidade de controle. Ao efetuar a busca da instrução, a unidade de
controle interpreta a instrução de modo a identificar quais as operações básicas que
devem ser realizadas, bem como ativa os sinais de controle que fazem uma operação
básica de fato acontecer.
Os sinais de controle que são ativados, bem como a sequência com que são ativados,
dependem de cada instrução em particular.
Assim, a execução de uma instrução envolve a realização de uma sequência de
passos, que podemos chamar de
. Em geral, a execução de uma
instrução envolve quatro passos, como mostra a seguinte:
busca
decodificação
execução
resultado
Figura 35: Passos na execução de uma instrução.

No primeiro passo, denominado busca (
), o processador realiza o acesso
ao código binário da instrução, armazenado na memória principal.

A etapa seguinte é a decodificação (
) da instrução, na qual as
informações contidas no código da instrução são interpretadas.

No terceiro passo, denominado execução, no qual a operação indicada pela
instrução (por exemplo, uma operação na
) é efetuada.

Finalmente no quarto passo, chamado resultado (
), é armazenado em um
registrador ou na memória o resultado produzido pela instrução.

Cada passo de execução envolve a realização de várias operações básicas.




transferência de dados entre os registradores e a
;
transferência de dados entre os registradores;
transferência de dados entre os registradores e a memória;
operações aritméticas e lógicas realizadas pela
.
Introdução à Programação: Conceitos e Práticas.
Página 86
6.1.2.
Seção de Processamento
A seção de processamento é formada basicamente pela unidade lógica e aritmética
(
) e por diversos registradores.
A
realiza as operações aritméticas, tais como adição e subtração, e operações
lógicas, tais como
.
Os registradores são utilizados para armazenar informações internamente no
processador. Um registrador pode ser utilizado tanto para acesso de leitura quanto
para acesso de escrita. Os diversos registradores possuem um uso bem definido
dentro da arquitetura, e de uma maneira geral podem ser classificados em três tipos:

registradores de uso geral,

registradores de uso específico e

registradores auxiliares.
Os registradores de uso geral normalmente são usados para armazenar dados que
serão processados pela
, bem como resultados produzidos pela
. O
registrador de estado (status register) associado à
é um registrador de uso
específico, e contém informações sobre o resultado produzido pela
. Este
registrador possui bits sinalizadores que são ativados ou desativados3 de acordo com o
tipo de resultado produzido pela
(
...).
Um outro exemplo de registrador de uso específico é o contador de programa
(
), cuja função é guardar o endereço da locação de memória onde se
encontra a próxima instrução a ser executada pelo processador.
6.1.3.
Barramentos
A interligação entre a
e os registradores é feita através de barramentos internos.
Os barramentos internos permitem a transferência de dados dos registradores para a
e permite a transferência do resultado produzido pela
, de um registrador
temporário, para outro registrador.
Uma arquitetura de processador é uma arquitetura de n bits quando todas as
operações da
podem ser realizadas sobre operandos de até
.
3
Considera-se aqui que um bit é ativado quando ele recebe o valor lógico 1, sendo desativado ao receber o valor
lógico 0.
Introdução à Programação: Conceitos e Práticas.
Página 87
Normalmente, em uma arquitetura de
os registradores de dados e os
barramentos internos também são de
, de forma a permitir que os dados sejam
armazenados e transferidos de forma eficiente.
A arquitetura Intel, desde o
Barramento de Dados (
Barramento de Controle (
até o Pentium, inclui três barramentos distintos:
), Barramento de Endereço (
) e
).

Barramento de Dados: por onde trafega informação qualificada como dado;

Barramento de Endereço: trafega informação qualificada como endereço;
O movimento de dados é uma das instruções mais utilizadas em um programa.
Equivale ao comando de atribuição em uma linguagem de alto nível, como Pascal e C.
É comum trazer dados da memória para a
e vice-versa.
Exemplo: Supondo que queiramos executar a seguinte instrução:
[
Que corresponde a guardar o número
seguintes passos serão realizados:
i.
ii.
iii.
iv.
v.
]
na célula de memória do endereço
. Os
Colocar
no barramento de endereço;
Colocar
no barramento de dados;
Ativar o sinal
no barramento de controle;
Aguardar enquanto o controlador da memória armazena o dado na célula de
indicada;
Desativar o sinal
no barramento de controle;
Esta sequência culmina com uma ordem ao controlador da memória em pegar estas
informações dos barramentos e efetuar a operação de gravar na memória.
De modo semelhante, a seguinte instrução:
[
], que determina que a
informação contida no endereço
da memória seja copiada para um registrador,
iniciará a seguinte sequência de utilização dos barramentos:
i.
ii.
iii.
iv.
v.
Colocar
no barramento de endereço;
Ativar o sinal
no barramento de controle;
O controlador da memória lê este pedido e copia a informação solicitada para o
barramento de dados;
Transferir o número que está no barramento de dados para o Registrador;
Desativar o sinal
no barramento de controle
Introdução à Programação: Conceitos e Práticas.
Página 88
O tamanho em bits dos barramentos de dados e de endereço influenciam diferentes
aspectos da arquitetura.
O tamanho do barramento de dados está ligado diretamente a capacidade de
transferência de informações entre partes distintas da
e entre a
e outros
componentes do sistema de processamento, como a memória
. Por exemplo, se
deseja trazer
da memória
para um registrador da
, e o barramento de
dados comporta
simultâneos, então este trabalho será feito em duas instruções,
Caso este mesmo barramento comportasse
simultâneos o trabalho seria feito
em uma instrução.
O tamanho do barramento de endereços influencia diretamente na capacidade de
endereçamento físico de memória
. Uma analogia pode ser feita com os Códigos
de Endereçamento Postal (CEP). Se cada cidade tivesse um CEP com apenas dígitos
decimais, então este sistema permitiria endereçar até
cidades (
).
Quando relacionamos cidades com células (
) de memória
e o CEP com a
informação colocada no barramento de endereços identificando um destino na
memória, logo vemos que quanto mais bits estiverem disponíveis no barramento de
endereços mais bytes de memória poderão ser endereçados. Por exemplo: se tivermos
de tamanho do barramento de endereços, então a capacidade de endereçamento
será de
células (bytes). O endereço da primeira célula seria
e da última
.
Na arquitetura Intel o tamanho dos barramentos evoluiu da seguinte forma:
Processador
8086
80286
80386
80486
Pentium
4
Barramento de Endereço
Tamanho
Quantidade de Bytes
de Memória
20
24
32
32
32/36/644
Primeiras implementações utilizam
http://en.wikipedia.org/wiki/X86-64
parte
dos
Introdução à Programação: Conceitos e Práticas.
64
bits.
O
Tamanho dos
Registradores
Barramento de
Dados
16
16
32
32
32/64
16
16
32
32
32/64
uso
integral
permitiria
16
EBytes,
Página 89
6.1.4.
O sinal de Clock
Para atender as relações de tempo requeridas na ativação dos sinais de controle, a
unidade de controle opera em sincronismo com um sinal de
.
1 ciclo
clock
leitura
decodificação
execução
resultado
Figura 36: A sincronização da execução de uma instrução com o sinal de clock.
A execução de uma instrução consome certo número de ciclos de
. O número de
ciclos de
por instrução não é o mesmo para todas as instruções, já que cada
instrução pode envolver um número diferente de operações básicas em cada passo de
execução.
O tamanho do ciclo de
é um dos fatores que determinam diretamente o
desempenho de um processador. Quanto menor o tamanho do ciclo de
, menor
será o tempo de execução das instruções, e assim maior será o número de instruções
executadas por unidade de tempo.
Em um processador com frequência de clock de
, o período será:
A frequência de clock dos processadores Intel era de
processadores
chegando a
no
.
6.1.5.
nos primeiros
Organização do Computador
A busca por melhor desempenho impulsionou não só o desenvolvimento de
processadores com melhores características de frequência de
, tamanho de
barramento, tamanho de registradores e quantidade de memória, mas também levou a
pesquisa de novos elementos de arquitetura que pudessem impactar no desempenho
do processador e na sua interação com a memória principal.
Segue um resumo das principais técnicas.
Introdução à Programação: Conceitos e Práticas.
Página 90
6.1.5.1.
Pipeline
Uma destas técnicas foi inspirada no conceito da linha de produção. Foi visto que o
processamento de uma instrução na
passa pelas etapas de:
,
,
e
; ou Busca, Decodificação, Execução e Resultado. Assim, uma
instrução quando trazida da memória para a
ocupava a
até o término da sua
execução. Então, os projetistas trabalharam no redesenho da
de tal forma que os
circuitos fossem reagrupados em partes independentes, uma para cada etapa do ciclo
de execução. Esta técnica, inspirada na linha de produção, foi denominada de
.
O seguinte diagrama ilustra o processamento de instruções na CPU com pipeline.
Figura 37: Execução e Pipeline.
Inicialmente uma instrução ocupa a unidade de Busca, e na sequencia a unidade de
Decodificação, liberando o estágio anterior, que pode ser ocupada pela instrução .
Enquanto avançam de estágio novas instruções podem ir ocupando os estágios
liberados. Neste exemplo, vemos que no tempo
quatro instruções ocupam a
,
melhorando sensivelmente o desempenho do processamento.
A pipeline perde desempenho quando processa instrução de desvio, e somente terá a
confirmação que o desvio será feito no estágio de execução, e as instruções
anteriormente trabalhadas serão desperdiçadas. Isto se deve ao fato de que o desvio
para outro trecho do programa demandará uma nova sequencia de instruções.
Processadores modernos concentram esforços para contornar este problema,
geralmente adotando mais de uma pipeline.
6.1.5.2.
Cache
Citamos anteriormente a existência de um limitante derivado do aspecto onde
, denominado
. Para assegurar a disponibilidade de uma
Introdução à Programação: Conceitos e Práticas.
Página 91
grande quantidade de memória
, fundamental às aplicações atuais, os fabricantes
tiveram que utilizar tecnologias que contrastam custo
quantidade
tempo de
acesso. Para obter um custo reduzido e permitir o uso de grandes quantidades de
memória, foi utilizada tecnologia de memória que resulta em maior tempo de acesso,
quando comparada aos tempos de uma
. O ideal seria que a memória
tivesse
o mesmo desempenho de um Registrador da
. Porém, os registradores são poucos
e específicos para alguns fins.
Desta forma, os projetistas avaliaram o comportamento dos programas quando estão
sendo executados e observaram um aspecto, onde trechos dos programas quando
processados permaneciam manipulando segmentos bem limitados (endereços
próximos) da memória
por um longo tempo. É importante destacar que um
programa na memória tem o seu fluxo de processamento composto basicamente por
instruções executadas em sequencia ou por instruções de desvios. As instruções de
desvios normalmente se referem a uma seleção de caminhos de processamento ou
uma iteração. É neste último caso que situações típicas envolvem o processamento
repetitivo de uma área de memória com endereços próximos.
Logo os projetistas concluíram que era possível desenvolver uma memória com tempo
de acesso menor que o tempo de acesso da
, e em menor quantidade, o suficiente
para acomodar o trecho da
que está sendo referenciado num determinado
momento.
Figura 38: Memória Cache.
Assim, a memória
se situa entre a
e a memória
, e possui um chip
controlador que implementa uma política que decide sobre a ocupação deste espaço de
memória. Esta lógica tem que decidir, quando encontra um acesso a um endereço da
não disponível no seu domínio, como se dará a substituição para que este novo
bloco passe a ocupar a
.
Um programa com excesso de desvios para trechos de códigos que manipulam áreas
de memória distintas degradam o desempenho, uma vez que são produzidas muitas
faltas na
.
Introdução à Programação: Conceitos e Práticas.
Página 92
6.1.5.3.
Outras Técnicas
Outras técnicas são empregadas visando elevar ao máximo o desempenho global de
um sistema de processamento. Muito resumidamente, seriam:
i.
Processamento Paralelo: Esta técnica visa multiplicar uma parte ou toda uma
permitindo que trechos distintos de um programa ou mesmo distintos
programas possam ser processados simultaneamente. Além de ser uma
característica da
, também os Sistemas Operacionais e as Linguagens de
Programação devem ser capazes de explorar este recurso. Processadores
modernos com tecnologia
empregam esta técnica.
ii.
Processamento Vetorial: A
com processamento escalar é capaz de operar
sobre apenas um dado. Por exemplo: a instrução de soma é capaz de somar um
número com outro número produzindo um resultado. Em um processador
vetorial, um único registrador da
é capaz de conter múltiplos dados, e as
instruções podem operar com estes múltiplos dados. Por exemplo: em uma
com processamento vetorial é possível trazer quatro inteiros da
para a
e acomodá-los em um registrador; em seguida uma instrução de soma poderá
adicionar estes quatro inteiros a outros quatro inteiros produzindo como
resultado quatro inteiros, tudo ao mesmo tempo. As tecnologias
dos processadores
incorporam esta característica,
onde uma instrução pode operar múltiplos dados.
Introdução à Programação: Conceitos e Práticas.
Página 93
7. Introdução à Programação
Atualmente não restam mais dúvidas sobre o sucesso da tecnologia digital, pois em
curto espaço de tempo alcançou um grau de disseminação que transcende fronteiras,
culturas e classes sociais. Certamente o nível de desenvolvimento tecnológico que
presenciamos hoje representa apenas uma amostra do que há por vir.
Este avanço se deve ao surgimento do computador nos anos , que de forma inegável
marcou o início de uma revolução que se propagaria em toda a sociedade. Porém, a
linguagem de programação poderia ser igualmente qualificada como revolucionária,
pois a sua utilização proporcionou uma incrível flexibilidade aos computadores.
5
A linguagem
teve um papel relevante nesta revolução pelo fato ter sido a
primeira linguagem com grande aceitação, sucesso este em grande parte creditado a
sua maior apoiadora, a
Após este sucesso, teve início uma onda de criação de
novas linguagens, cuja amostra pode ser observada na seguinte árvore genealógica.
FORTRAN (54)
COBOL (59)
1960
ALGOL 60
BASIC (64)
Simula 67
PL/I (65)
ALGOL 68
1970
C (72)
Pascal (71)
Modula 2 (75) Conc Pascal (75)
CLU (75)
Ada (79)
1980
Ada (83) ANSI
C++(85)
Eifell (86)
1990
Java (95)
Ada (95)
Figura 39: Genealogia das Linguagens – Base FORTRAN.
5
http://pt.wikipedia.org/wiki/Fortran
Introdução à Programação: Conceitos e Práticas.
Página 94
Esta árvore destaca claramente a influência da linguagem
, gerando uma
grande quantidade de descendentes, o que não se observa em linguagens com
diferentes propostas de estilos de programação, como ilustra a figura abaixo:
LISP (59)
APL (62)
SNOBOL (62)
Smalltalk (69)
PROLOG (72)
OPS5 (77)
Perl (87)
Tcl/Tk (88)
Figura 40: Genealogia das Linguagens.
Um dos fatores que foram determinantes no sucesso das linguagens de programação
foi a possibilidade de fazer com que o computador desempenhe diferentes funções,
bastando para isto programar o comportamento desejado. Além disso, a produtividade
proporcionada por uma linguagem de alto nível, como o
, estimulou
largamente o emprego de programas para realizar funções das mais variadas.
A expansão e os aprimoramentos incorporados às linguagens fizeram com que a
atividade de programação saísse dos ambientes de pesquisa e começasse a permear
os mais diferentes setores da economia e incorporasse programadores originários de
várias outras profissões.
A seguinte figura ilustra como a produção de programas foi facilitada pelas linguagens
de programação de alto nível.
Figura 41: Níveis de Programação.
Introdução à Programação: Conceitos e Práticas.
Página 95
Tanto o código
quanto o código de máquina da figura são de uma compilação
real de uma expressão simples em linguagem de alto nível, que produziu três linhas em
e dezesseis bytes para o código de máquina.
Assim, com a facilidade proporcionada pelas linguagens de alto nível, as décadas de
e
experimentaram uma expansão em larga escala no uso de programas de
computadores, gerando uma nova situação que era a preocupação em como gerenciar
este novo elemento, chamado programa de computador.
A ausência de um processo de engenharia no desenvolvimento de programas e a
ausência de boas práticas de gerenciamento levaram ao surgimento do termo
, inicialmente citado por Edsger Dijkstra em
.
Esta constatação despertou para a necessidade de abordar a atividade de
programação como um processo de engenharia, demandando a aplicação de
metodologias, técnicas, ferramentas e padrões durante todo o ciclo de vida do software.
A figura a seguir ilustra um processo de desenvolvimento de software:
Figura 42: Ciclo de Desenvolvimento de Software.
O software passou a ser visto como um produto e rapidamente se converteu em
tecnologia presente nos mais diversificados dispositivos, tais como: aviões, carros,
televisões, telefone, micro-ondas, foguetes, trens, dentre outros.
Introdução à Programação: Conceitos e Práticas.
Página 96
8. O Processo de Tradução
A Linguagem de Programação reduziu a lacuna entre o problema e o programa, pois
permitiu que o código ficasse mais próximo da formulação do problema. No caso
particular do
a forma de programar se assemelhava a descrição dos
problemas em notação matemática. Isto lhe valeu o acrônimo de
.
Porém, os computadores continuavam a compreender apenas a linguagem binária. As
instruções eram entendidas pelas
apenas no formato numérico. Logo, era
necessário traduzir o programa expresso na forma textual para um formato adequado
para processamento na
. A figura a seguir ilustra os diversos conversores e
montadores necessários para efetuar esta tradução:
Figura 43: Processo de Tradução
Atualmente estão disponíveis avançados ambientes de programação denominados
–
que tornam transparente ao programador
as etapas de tradução. O programador interage com o
digitando o programa em
uma linguagem de alto nível e aciona o comando ou a tecla de compilação. Assim
obtém o código final, que pode ser executado ou depurado no próprio ambiente do
.
O depurador é uma importante ferramenta que permite ao programador executar
pausadamente cada linha de código, permitindo inspecionar a memória em busca de
erros na lógica.
Introdução à Programação: Conceitos e Práticas.
Página 97
9. A Linguagem Pascal
A linguagem
foi por muito tempo utilizada no ensino de programação. Porém,
as versões iniciais da linguagem não proporcionavam mecanismos que ajudassem de
forma natural na escrita de programas com qualidade de produto. De forma simplificada
um programa em execução na memória pode ser visto em dois blocos, sendo um
composto pelas instruções e outro por uma área de dados para armazenamento de
informações. As instruções, por sua vez podem ser de duas naturezas:
e
. A de tipo
é aquela que concluída a sua execução é dada a vez para
a próxima na memória. A de tipo
é aquela que testa uma condição para decidir
qual a próxima instrução a ser executada. Conforme o resultado da condição testada
poderá ser executada a instrução subsequente ou uma instrução em outro endereço.
Assim, programas
nos primórdios do seu uso tinham a seguinte aparência,
onde uma série de instruções de desvio (
ou
) alterava o fluxo de execução
do programa, dificultando o entendimento da lógica:
L01
L02
L03
L04
L05
L06
L07
L08
L09
L10
L11
L12
L13
L14
L15
L16
L17
L18
instrução
instrução
jump L06
instrução
jump L16
instrução
jump L10
instrução
jump L04
instrução
jump L15
instrução
jump L02
instrução
jump L01
instrução
jump L10
instrução
Figura 44: Estilo de Programação Spaghetti.
Esta aparência rendeu a denominação de estilo
de programação em função
da aparência confusa e semelhante a este típico prato italiano. Neste período, fins dos
anos
e década de
, o que norteava o desenvolvimento de programas era a
necessidade de economizar os recursos computacionais (memória e tempo de
),
pois o
custava muito mais do que o tempo dos desenvolvedores. Para tal fim,
os programadores utilizavam técnicas de reaproveitamento de memória e otimização
das instruções que resultava no médio prazo em grande dificuldade de manutenção.
Nas décadas seguintes foram surgindo novos estilos de programação com o objetivo de
melhorar a engenharia dos programas, e consequentemente elevar o grau de qualidade
Introdução à Programação: Conceitos e Práticas.
Página 98
e confiabilidade destes produtos. Estes estilos visavam a melhor organização das
entidades que compõem um programa, principalmente dados e rotinas, e também
almejavam melhorar a produtividade do programador através do reuso de códigos. O
seguinte quadro ilustra a evolução nos estilos de programação.
Figura 45: Evolução no estilo de programação.
Após o
, o esforço seguinte que mereceu destaque na história das linguagens
6
foi o projeto do
, que nasceu da intenção de prover uma linguagem que
conduzisse a programas melhores construídos.
O
era uma linguagem grande e complexa e dadas as condições da época, não
houveram implementações completas de compiladores. Porém, um dos participantes
nos trabalhos do
observou que os princípios desta linguagem poderiam ser
utilizados para compor uma nova linguagem mais simples que auxiliasse na formação
acadêmica e no ensino de programação. Assim surgiu a linguagem Pascal em
,
como proposta do prof. Niklaus Wirth.
A linguagem Pascal7 alcançou a popularização nos anos
8
da
, denominados
. A linha
6
7
através dos compiladores
foi descontinuada na
http://pt.wikipedia.org/wiki/ALGOL
http://pt.wikipedia.org/wiki/Pascal_(linguagem_de_programação)
Introdução à Programação: Conceitos e Práticas.
Página 99
metade dos anos
ainda em plataforma de
, sendo sucedida pelo ambiente
integrado de desenvolvimento
que suportava a linguagem
Porém, um grupo de seguidores do Turbo Pascal iniciou um esforço para desenvolver
um compilador multiplataforma que acompanhasse a evolução dos processadores.
9,10
Nasceu assim a linha
ainda na década de
e disponibiliza
compiladores de
.
8
http://pt.wikipedia.org/wiki/Turbo_Pascal
http://pt.wikipedia.org/wiki/Free_Pascal
10
http://www.freepascal.org/
9
Introdução à Programação: Conceitos e Práticas.
Página 100
10.
Estrutura de um Programa Pascal
A Figura 33: Programa na Memória RAM: Código + Dados. ilustrou um programa na
memória separado em duas áreas distintas, sendo uma para acomodar a codificação
das instruções e a outra para conter os resultados produzidos por estas instruções.
Esta organização reflete também o título do livro
, de Niklaus Wirth, publicado em
, afirmando que um programa é a
combinação de algoritmo e estrutura de dados, ou em termos mais simples:
.
De forma semelhante, um programa Pascal tem a seguinte estrutura básica:
Program exemplo;
Var
.
.
.
Begin
.
.
.
End.
Nome do programa
Trecho destinado aos dados
Trecho destinado às instruções
Assim, para iniciar a programação em Pascal é necessário conhecer tanto os recursos
disponíveis para definição de dados quando os recursos para manipulação dos dados.
Uma das vantagens das linguagens de alto nível em relação às linguagens de baixo
nível foi a possibilidade de trabalhar com nomes em vez de endereços físicos de
memória. Assim, na sequência são apresentadas as regras para a criação de nomes ou
identificadores.
11.
Identificadores
O programador terá que se habituar a dar nomes para as entidades de um programa,
tais como constantes, tipos, variáveis, procedures, funções, units e programas. A regra
para nomes ou identificadores é dada por:
Introdução à Programação: Conceitos e Práticas.
Página 101
A notação11 acima indica que um identificador válido inicia com um dos caracteres
listados em
seguido por zero ou mais
caracteres em
A definição
admite letra ou dígito. A linguagem
não distingue entre maiúsculo e
minúsculo, ou seja: um nome todo em maiúsculo ou todo em minúsculo ou misto é
entendido pelo Pascal como sendo o mesmo identificador. Seguem alguns exemplos:
Identificadores válidos
Identificadores não válidos
A
B
Soma
SOMA_TOTAL
B20
A1
Qdade
I
_J
K_
12.
SOMA TOTAL
9AUX
SOMA-TOTAL
Dado%
Valor$
#qdade
aluno@nome
Variáveis e Tipos de Dados
Associar nomes com endereços de memória facilitou a atividade de programação e deu
origem ao conceito de variável. Assim, variável é uma referência a um endereço de
uma área de memória, e através da qual se pode armazenar ou recuperar valor.
A seguinte figura ilustra uma sequência de bytes na memória (endereços de
a
)
e a associação com os nomes , , e , formando o conceito de variáveis. As células
de memória podem ser trabalhadas através destes nomes.
Nome
A:
B:
C:
X:
Célula - RAM
Endereço
303
302
301
300
A reserva destas células de memória em
se dá pela declaração de variáveis no
trecho destinado aos dados. Além do nome que se deseja associar à área de memória
também é necessário indicar a natureza do dado que se deseja acomodar nesta área,
que em termos de linguagem de programação é o
.
Assim, a sintaxe para declaração de variáveis é:
11
Notação semelhante à BNF:
 O símbolo “::=” significa “é definido como”.
 O símbolo “*” significa “repetir 0 ou mais vezes”.
Introdução à Programação: Conceitos e Práticas.
Página 102
{
}
Alguns exemplos de declaração de variáveis numéricas:
Program exemplo;
Var
A : Integer;
B : LongInt;
C : Word;
D : Byte;
X : Real;
Y : Double;
Z : Extended;
I, J, K : Integer;
Soma, Produto : Real;
Begin
.
.
End.
Na sequência serão detalhados os significados dos tipos numéricos.
13.
Comando de Atribuição
A primeira instrução a ser apresentada e uma das mais utilizadas é a instrução de
atribuição, cuja função é armazenar valores na memória. A sintaxe é:
O símbolo
representa a instrução de atribuição, cujo significado é armazenar na
célula de memória indicada pela variável o valor final da expressão. A
aparece
no
da instrução de atribuição e o
aparece no
. Para
fazer uso deste recurso é preciso aprender a escrever expressões, que podem ser de
natureza numérica/aritmética, textuais, lógicas ou binárias.
Introdução à Programação: Conceitos e Práticas.
Página 103
14.
Expressões Numéricas
As expressões numéricas combinam constantes, variáveis, operadores e funções a fim
de obter um novo valor calculado. A sintaxe da linguagem de programação deve ser
entendida para que uma expressão escrita em notação matemática normal seja
corretamente convertida para a forma computacional. Alguns exemplos de expressões
que serão reescritas em Pascal:
√
√
14.1. Tipos Numéricos
A linguagem Pascal disponibiliza tipos de dados numéricos que permitem a
representação de inteiros sem sinal, inteiros com sinal e reais, com diversos tamanhos
e precisões.
A seguinte tabela apresenta os tipos inteiros disponíveis no
Tipo
Byte
Shortint
Smallint
Word
Integer
Faixa
smallint ou longint
depende da arquitetura
Longint
Longword
Int64
QWord
12
12
:
#bytes
1
1
2
2
2 ou 4
4
4
8
8
O Pascal padrão disponibiliza alguns destes tipos
Introdução à Programação: Conceitos e Práticas.
Página 104
Pela faixa de representação distinguem-se os inteiros com sinal e sem sinal. Os inteiros
sem sinal são armazenados como
, enquanto os inteiros com sinal são
representados em
.
A seguinte tabela apresenta os tipos reais:
Tipo
Real
Single
Faixa
dependente da plataforma
Dígitos Significativos
---
#bytes
4 or 8
4
Double
8
Extended
Comp
10
8
Agora temos mais elementos para compreender o conceito de variável. Assim, ao
declararmos uma variável estamos fornecendo elementos ao compilador sobre a
natureza da célula de memória e orientando sobre as regras permitidas para o
manuseio deste espaço. No caso do compilador
é necessário observar as
diretivas de compilação que influenciam no tamanho de alguns tipos. O quadro a seguir
ilustra as alternativas oferecidas pelo compilador:
Figura 46: Modos do Compilador.
O acesso a estas opções é feito conforme ilustração a seguir:
Introdução à Programação: Conceitos e Práticas.
Página 105
Figura 47: Acesso a tela com as diretivas de compilação.
Por exemplo, se compilarmos o programa exemplo, com as declarações de variáveis
indicadas, tem-se as seguintes informações:
Program exemplo;
Var
A : Integer;
B : LongInt;
C : Word;
D : Byte;
X : Real;
Y : Double;
Z : Extended;
I,
J,
K : Integer;
Soma,
Produto : Real;
#bytes
4
4
2
1
8
8
10
4
4
4
8
8
Endereço de Memória
Var
Decimal
Hexa Offset
@A
4243456 40C000
4
@B
4243460 40C004
4
@C
4243464 40C008
2
@D
4243466 40C00A
6
@X
4243472 40C010
8
@Y
4243480 40C018
8
@Z
4243488 40C020
12
@I
4243500 40C02C
4
@J
4243504 40C030
4
@K
4243508 40C034
4
@Soma
4243512 40C038
8
@Produto 4243520 40C040
8
65
72
A coluna
indica a quantidade de bytes efetivamente ocupada pela variável. As
colunas
e
indicam o endereço de memória associado a cada variável no
momento da execução. A coluna
indica a diferença dos endereços de duas
variáveis alocadas consecutivamente. Teoricamente este número deveria coincidir com
a coluna
, o que não ocorre na prática em função do compilador alinhar as
variáveis em posições de memória que forneça o melhor desempenho de acesso.
Introdução à Programação: Conceitos e Práticas.
Página 106
Normalmente isto ocorre quando posicionadas em endereços múltiplos de
ou ,
conforme o tipo da variável. A tabela abaixo indica as alocações, bem como os bytes de
preenchimentos:
End.
1 40C000
Var
Célula
A
End.
Var
25 40C018
Célula
Y
End.
49 40C030
2 40C001
26 40C019
50 40C031
3 40C002
27 40C01A
51 40C032
4 40C003
28 40C01B
52 40C033
29 40C01C
53 40C034
6 40C005
30 40C01D
54 40C035
7 40C006
31 40C01E
55 40C036
5 40C004
B
8 40C007
9 40C008
32 40C01F
C
10 40C009
33 40C020
57 40C038
58 40C039
35 40C022
59 40C03A
12 40C00B
36 40C023
60 40C03B
13 40C00C
37 40C024
61 40C03C
14 40C00D
38 40C025
62 40C03D
15 40C00E
39 40C026
63 40C03E
16 40C00F
40 40C027
64 40C03F
41 40C028
65 40C040
18 40C011
42 40C029
66 40C041
19 40C012
43 40C02A
67 40C042
20 40C013
44 40C02B
68 40C043
21 40C014
45 40C02C
22 40C015
46 40C02D
70 40C045
23 40C016
47 40C02E
71 40C046
24 40C017
48 40C02F
72 40C047
17 40C010
D
X
Célula
J
K
56 40C037
Z
34 40C021
11 40C00A
Var
I
Soma
Produto
69 40C044
Figura 48: Alocação das variáveis na memória.
Observar que a variável ocupa um byte de memória e que na sequência vem cinco
bytes de preenchimento a fim de posicionar a próxima variável ( ) em endereço
adequado. Esta estratégia pode variar conforme o compilador e a plataforma.
14.2. Constantes
Agora podemos utilizar estas células de memória para armazenar valores ou recuperálos conforme a conveniência da lógica do processamento. Para guardar valores, o
nome da variável deve aparecer à esquerda do comando de atribuição, enquanto que
Introdução à Programação: Conceitos e Práticas.
Página 107
do lado direito a referência a variável é substituída pelo seu valor. O seguinte exemplo
ilustra as formas mais usais de representar constantes numéricas:
Declaração das Variáveis
Program exemplo;
Var
A : Integer;
B : LongInt;
C : Word;
D : Byte;
X : Real;
Y : Double;
Z : Extended;
I,
J,
K : Integer;
Soma,
Produto : Real;
Programa Principal
Begin
A
B
C
D
X
Y
Z
I
Soma
Produto
X
End.
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
-1;
32767;
1000;
38;
1.25e+10;
-0.0003e-30;
30.67;
$3f8;
720;
-1000.;
:= 0.01;
As notações se assemelham muito ao que estamos habituados a utilizar na aritmética
convencional. Cabe destacar a notação de números inteiros em hexadecimal, onde o
símbolo
precede a constante. Os números reais aceitam a notação com potência de
, e neste caso deve se interpretar que o símbolo
ou
equivale a ―
‖.
Assim, a constante
equivale a
.
Apresentaremos na sequência três momentos distintos da execução deste programa e
os respectivos conteúdos de memória em hexadecimal a fim de melhor visualizar os
equivalentes binários:
Introdução à Programação: Conceitos e Práticas.
Página 108
i.
Início do programa, porém nenhuma instrução executada:
End.
1 40C000
Var
Célula
Var
Célula
Var
Célula
$00
25 40C018
$00
49 40C030
$00
26 40C019
$00
50 40C031
$00
3 40C002
$00
27 40C01A
$00
51 40C032
$00
4 40C003
$00
28 40C01B
$00
52 40C033
$00
$00
29 40C01C
$00
53 40C034
6 40C005
$00
30 40C01D
$00
54 40C035
$00
7 40C006
$00
31 40C01E
$00
55 40C036
$00
8 40C007
$00
32 40C01F
$00
56 40C037
$00
$00
33 40C020
$00
57 40C038
$00
34 40C021
$00
58 40C039
$00
$00
35 40C022
$00
59 40C03A
$00
12 40C00B
$00
36 40C023
$00
60 40C03B
$00
13 40C00C
$00
37 40C024
$00
61 40C03C
$00
14 40C00D
$00
38 40C025
$00
62 40C03D
$00
15 40C00E
$00
39 40C026
$00
63 40C03E
$00
16 40C00F
$00
40 40C027
$00
64 40C03F
$00
9 40C008
B
C
10 40C009
11 40C00A
17 40C010
D
X
Y
End.
2 40C001
5 40C004
A
End.
Z
J
K
Soma
$00
$00
$00
41 40C028
$00
65 40C040
18 40C011
$00
42 40C029
$00
66 40C041
$00
19 40C012
$00
43 40C02A
$00
67 40C042
$00
20 40C013
$00
44 40C02B
$00
68 40C043
$00
21 40C014
$00
45 40C02C
$00
69 40C044
$00
22 40C015
$00
46 40C02D
$00
70 40C045
$00
23 40C016
$00
47 40C02E
$00
71 40C046
$00
24 40C017
$00
48 40C02F
$00
72 40C047
$00
I
Produto
$00
$00
Observa-se que neste instante todos os bytes estão com o valor zero. O programador
não pode tomar como certa a inicialização de variáveis pela linguagem. Sempre que for
necessário assegurar um valor inicial, o programador deve explicitamente atribuir o
valor desejado.
Introdução à Programação: Conceitos e Práticas.
Página 109
ii.
Após a execução da primeira instrução (
End.
1 40C000
Var
Célula
$FF
25 40C018
2 40C001
$FF
3 40C002
$FF
4 40C003
Var
Célula
Var
Célula
49 40C030
26 40C019
$00
50 40C031
$00
27 40C01A
$00
51 40C032
$00
$FF
28 40C01B
$00
52 40C033
$00
$00
29 40C01C
$00
53 40C034
6 40C005
$00
30 40C01D
$00
54 40C035
$00
7 40C006
$00
31 40C01E
$00
55 40C036
$00
8 40C007
$00
32 40C01F
$00
56 40C037
$00
$00
33 40C020
$00
57 40C038
$00
34 40C021
$00
58 40C039
$00
$00
35 40C022
$00
59 40C03A
$00
12 40C00B
$00
36 40C023
$00
60 40C03B
$00
13 40C00C
$00
37 40C024
$00
61 40C03C
$00
14 40C00D
$00
38 40C025
$00
62 40C03D
$00
15 40C00E
$00
39 40C026
$00
63 40C03E
$00
16 40C00F
$00
40 40C027
$00
64 40C03F
$00
$00
41 40C028
$00
65 40C040
18 40C011
$00
42 40C029
$00
66 40C041
$00
19 40C012
$00
43 40C02A
$00
67 40C042
$00
20 40C013
$00
44 40C02B
$00
68 40C043
$00
21 40C014
$00
45 40C02C
$00
69 40C044
$00
22 40C015
$00
46 40C02D
$00
70 40C045
$00
23 40C016
$00
47 40C02E
$00
71 40C046
$00
24 40C017
$00
48 40C02F
$00
72 40C047
$00
9 40C008
B
C
10 40C009
11 40C00A
17 40C010
D
X
Y
End.
$00
5 40C004
A
End.
):
Z
I
J
K
Soma
Produto
$00
$00
$00
$00
Neste novo cenário logo após a execução da primeira instrução, onde é atribuído o
valor
à variável , pode ser observado que os bytes alocados para esta variável
passaram a conter
que equivale a
com o valor para cada
dígito binário. Isto decorre do fato que a variável está declarada como integer13 o que
a define como inteiro com sinal e tamanho de
. Assim, ao representar o
em
obtém-se esta sequência de bits, conforme ilustra a conversão
abaixo:
:
C-1:
C-2:
000...00001
111...11110
+
1
----------111...11111  Ok
13
O tamanho do tipo integer depende muitas vezes da plataforma computacional e é configurável. O tamanho
exato deve ser verificado.
Introdução à Programação: Conceitos e Práticas.
Página 110
Após a execução de todas as instruções, porém antes de encerrar o programa:
End.
Var
1 40C000
Célula
A
End.
$FF
25 40C018
2 40C001
$FF
3 40C002
4 40C003
Var
Célula
Var
Célula
$6E
49 40C030
26 40C019
$F2
50 40C031
$00
$FF
27 40C01A
$78
51 40C032
$00
$FF
28 40C01B
$5C
52 40C033
$00
$FF
29 40C01C
$4B
53 40C034
6 40C005
$7F
30 40C01D
$EC
54 40C035
$00
7 40C006
$00
31 40C01E
$F8
55 40C036
$00
8 40C007
$00
32 40C01F
$B8
56 40C037
$00
$E8
33 40C020
$29
57 40C038
$03
34 40C021
$5C
58 40C039
$00
$26
35 40C022
$8F
59 40C03A
$00
12 40C00B
$00
36 40C023
$C2
60 40C03B
$00
13 40C00C
$00
37 40C024
$F5
61 40C03C
$00
14 40C00D
$00
38 40C025
$28
62 40C03D
$80
15 40C00E
$00
39 40C026
$5C
63 40C03E
$86
16 40C00F
$00
40 40C027
$F5
64 40C03F
$40
$7B
41 40C028
$03
65 40C040
18 40C011
$14
42 40C029
$40
66 40C041
$00
19 40C012
$AE
43 40C02A
$00
67 40C042
$00
20 40C013
$47
44 40C02B
$00
68 40C043
$00
21 40C014
$E1
45 40C02C
$F8
69 40C044
$00
22 40C015
$7A
46 40C02D
$03
70 40C045
$40
23 40C016
$84
47 40C02E
$00
71 40C046
$8F
24 40C017
$3F
48 40C02F
$00
72 40C047
$C0
5 40C004
B
9 40C008
C
10 40C009
11 40C00A
D
17 40C010
X
Y
End.
Z
I
J
K
Soma
Produto
$00
$00
$00
$00
A configuração final mostra que todas as células (conjunto de bytes) foram alteradas
pelas atribuições, com exceção dos bytes de preenchimento. A título de exercício
vamos converter o valor de
para a forma binária, conforme padrão IEEE 754
(IEC 60559) já explicado anteriormente:
Tipo
Sinal Expoente Mantissa
Double extended
(80-bit)
1
15
64
Total
bits
80
Dígitos
Expoente
Bits
Significativos
bias
Precisão
Decimal
16383
64
~19.2
Detalhando o tipo Double Extended, tem-se a seguinte estrutura:
S
Expoente (15)
Introdução à Programação: Conceitos e Práticas.
Mantissa (64)
Página 111
Para
i.
Converter
30
14
ii.
16
1
1
para a base
0.67
0.72
0.52
0.32
0.12
0.92
0.72
0.52
0.32
0.12
0.92
0.72
0.53
0.50
16
0
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
x 16 =
10.720
11.5200
8.3200
5.1200
1.9200
14.7200
11.5200
8.3200
5.1200
1.9200
14.7207
11.5313
8.5000
8.0000
Normalizar
Observe que o padrão
difere um pouco do método didático apresentado,
pois há um ganho de
ao se normalizar como
em vez de
.
iii.
Enquadrar
Agora, resta enquadrar as partes de
no padrão estabelecido em binário.
Introdução à Programação: Conceitos e Práticas.
Página 112
S
Expoente (15)
Mantissa (64)
Onde a parte do Expoente foi obtida da seguinte forma:
, em
com
Observe que há uma diferença apenas no último bit, provavelmente decorrente da
precisão nos cálculos. Na memória os bytes são armazenados de forma invertida, ou
seja o byte menos significativo fica no endereço , conforme:
Fica a cargo de o leitor avaliar com mais detalhes os métodos de conversão das demais
variáveis.
14.3. Operadores Matemáticos
Vamos ampliar a capacidade de manipular dados através dos operadores aritméticos,
aplicados a um ou dois operandos para produzir um resultado.
Operador
Binário
Operação
Observação
Soma
Subtração
Multiplicação
Divisão
Divisão Inteira
Os operandos podem ser expressões com inteiro ou real. Se
ambos os operandos forem inteiros o resultado será inteiro. Se
um dos operandos for real, então o resultado será real.
Resto
Independente do tipo do operando o resultado será real.
Operandos e resultado são inteiros. Retorna o quociente da
divisão.
Operandos e resultado são inteiros. Retorna o resto da divisão.
Os operadores e também podem ser aplicados a apenas um operando, passando
a ter os seguintes significados:
Operador
Unário
Operação
Identidade
Inversão
Observação
+ Expressão retorna o mesmo valor de Expressão.
- Expressão retorna o valor de Expressão com sinal trocado.
Introdução à Programação: Conceitos e Práticas.
Página 113
Quando estiverem presentes em uma expressão vários operadores, a linguagem
executa primeiramente o operador com maior nível de precedência. De modo
semelhante ao habitual os operadores
tem precedência de execução em
relação a
e . A seguinte tabela antecipa os operadores e as respectivas
precedências:
Tabela 1: Precedência de Operadores.
Operador14
Precedência
Mais Alta (primeira)
Segunda
Terceira
Mais Baixa (Última)
Categoria
Operadores Unários
Operadores de Multiplicação
Operadores de Soma
Operadores Relacionais
Considere a seguinte expressão:
A operação de multiplicação é executada primeiro e depois a soma. Caso queira efetuar
primeiro a soma então se deve fazer uso de parêntesis, como na expressão:
Neste outro exemplo:
quando escrita em Pascal tem-se:
Foram utilizados dois níveis de parêntesis a fim de agrupar adequadamente as
operações.
14.4. Funções Matemáticas
A linguagem Pascal disponibiliza algumas funções aritméticas que podem ser utilizadas
na construção de expressões matemáticas. Segue uma descrição resumida de cada
uma delas:
1)
14
Alguns destes operadores fazem parte do Free Pascal e não do Pascal padrão.
Introdução à Programação: Conceitos e Práticas.
Página 114
Retorna o valor absoluto de uma variável. O resultado será do mesmo tipo do
argumento.
Exemplo:
Program ExABS;
Var
r : real;
i : integer;
begin
r := abs(-3.0);
i := abs(-65);
end.
{ r := 3.0 }
{ i := 65 }
2)
Retorna o ângulo cuja
é . O resultado será expresso em radianos.
Exemplo:
Program ExARCTAN;
Var R : Real;
begin
R:=ArcTan(0);
R:=ArcTan(1);
end.
{ R := 0.0 }
{ R := 0.785... que equivale a PI/4}
3)
Retorna o
de um ângulo , onde
deve estar em radianos.
Exemplo:
Program ExCOS;
Var R : Real;
begin
R := Cos(Pi);
R := Cos(Pi/2);
R := Cos(Pi/3);
R := Cos(0);
end.
{
{
{
{
R:=-1.0
R:=0.0
R:=0.5
R:=1.0
}
}
}
}
Introdução à Programação: Conceitos e Práticas.
Página 115
4)
Retorna o
de um ângulo , onde
deve estar em radianos.
Exemplo:
Program ExSIN;
Var R : Real;
begin
R := Sin(Pi);
R := Sin(Pi/2);
R := Sin(Pi/6);
R := Sin(0);
end.
{
{
{
{
R
R
R
R
:=
:=
:=
:=
0.0
1.0
0.5
0.0
}
}
}
}
{
{
{
{
R
R
R
R
:=
:=
:=
:=
0.0
1.0
0.5
0.0
}
}
}
}
5)
Retorna o valor de
Exemplo:
Program ExPI;
Var R : Real;
begin
R := Sin(Pi);
R := Sin(Pi/2);
R := Sin(Pi/6);
R := Sin(0);
end.
6)
Retorna o valor de
, onde
Exemplo:
Program ExEXP;
begin
Writeln (Exp(1)); { mostrará na tela o valor 2.7182818284590452}
end.
Introdução à Programação: Conceitos e Práticas.
Página 116
7)
Retorna a parte fracionária de .
Exemplo:
Program ExFRAC;
Var R : Real;
begin
Writeln (Frac (123.456)); { Mostrará O.456 }
Writeln (Frac (-123.456)); { Mostrará -O.456 }
end.
8)
Retorna a parte inteira de , como real.
Exemplo:
Program ExINT;
Var R : Real;
begin
Writeln (Int (123.456)); { Mostrará 123.0 }
Writeln (Int (-123.456)); { Mostrará -123.0 }
end.
9)
Retorna o
de
na base , onde
.e
deve ser positivo.
Exemplo:
Program ExLN;
begin
Writeln (Ln(1));
{ Mostrará 0 }
Writeln (Ln(Exp(1))); { Mostrará 1 }
end.
10)
Retorna o quadrado de . O resultado será do mesmo tipo que o argumento .
Introdução à Programação: Conceitos e Práticas.
Página 117
Exemplo:
Program ExSQR;
Var
r : real;
i : integer;
begin
r := sqr(-3.0);
i := sqr(-3);
end.
{ r := 9.0 }
{ i := 9 }
11)
Retorna a raiz quadrada de
( √ ), onde
deve ser positivo.
Exemplo:
Program ExSQRT;
Var
r : real;
begin
r := sqrt(4);
{ r := 2.0 }
r := sqrt(2.0); { r := 1.4142.. }
end.
12)
Retorna o arredondamento de para o inteiro mais próximo. Quando a parte
fracionária é , o arredondamento é feito na direção do par mais próximo.
Exemplo:
Program ExROUND;
begin
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
end.
(Round(1234.56));
(Round(-1234.56));
(Round(12.3456));
(Round(-12.3456));
(Round(2.5));
(Round(3.5));
{
{
{
{
{
{
Introdução à Programação: Conceitos e Práticas.
Mostrará
Mostrará
Mostrará
Mostrará
Mostrará
Mostrará
1235
}
-1235
}
12
}
-12
}
2 (para baixo) }
4 (para cima) }
Página 118
13)
Retorna a parte inteira de X.
Exemplo:
Program ExTRUNC;
begin
Writeln
Writeln
Writeln
Writeln
end.
(Trunc(123.456));
(Trunc(-123.456));
(Trunc(12.3456));
(Trunc(-12.3456));
{
{
{
{
Mostrará
Mostrará
Mostrará
Mostrará
123
-123
12
-12
}
}
}
}
14.5. Exemplos
Os exemplos que seguem apresentam algumas expressões na forma usual e o
respectivo programa:
Equação
i.
√
ii.
iii.
Que pode ser reescrita como:
Programa
Program EqA;
Var X, Y, Z : Real;
begin
Z := SQRT(SQR(X) + Y*Y*Y)/ABS(X+Y);
end.
Program EqA;
Var X, Y, Z : Real;
begin
Z := SQRT(X*X + Y*Y*Y)/ABS(X+Y);
end.
Program EqB;
Var X, Z : Real;
begin
Z := (1 + SIN(X))/(1 + COS(X));
end.
Program EqC;
Var X, Z : Real;
begin
Z := 1 + 1/X + 1/SQR(X) + 1/(X*X*X) +
1/(X*X*X*X);
end.
Program EqC;
Var X, Y, Z : Real;
Introdução à Programação: Conceitos e Práticas.
Página 119
(
(
(
)))
√
√
iv.
( )
( )
v.
√
√
Begin
Y := 1/X;
Z := 1 + Y*(1 + Y*(1 + Y*(1 + Y)));
end.
Program EqD;
Var X, Y, Z, W : Real;
Begin
W := X/Y;
Z := W – (X + SQR(W))/(Y – SQR(W));
end.
Program EqE;
Var X, Z : Real;
Begin
Z := SQRT(PI +
SQRT(EXP(3) +
SQRT(4 +
SQRT(X)
)));
end.
Observe na expressão do item
uma codificação alternativa a partir da reescrita da
expressão original. Além disso, uma variável auxiliar ( ) foi utilizada, o que evitou a
repetição de uma mesma operação ao longo da expressão.
Caso fossemos compilar e executar estes programas, não seria possível observar os
efeitos do código, visto que o programa não inclui nenhuma forma de interação com o
usuário. O fornecimento de dados via teclado e apresentação de resultados na tela do
computador são meios usuais de interação entre programa e usuário. Na sequência
serão apresentados os comandos que permitem incluir estes recursos.
Introdução à Programação: Conceitos e Práticas.
Página 120
15.
Comandos de Entrada e Saída
A seguinte figura ilustra um programa em execução interagindo com o usuário através
dos dispositivos básicos de Entrada e Saída, que são o teclado e o monitor de vídeo.
15.1. Entrada
O comando
ou
permite que o programa obtenha dados digitados pelo
usuário. Ao processar o programa o sistema operacional abre uma janela denominada
de ambiente de execução. Ao executar o comando
o programa fica
aguardando que o usuário digite uma linha com os dados e pressione a tecla
.
Em seguida, esta linha é interpretada e os dados são armazenados nas variáveis
(endereços de memória) indicadas.
A sintaxe do
para leitura do teclado é:
A lista de argumentos deve conter as variáveis (endereços de memória) onde o
deve armazenar os dados digitados.
Observe no exemplo da figura anterior que o comando
digitação de uma linha cujo conteúdo será armazenado como
Introdução à Programação: Conceitos e Práticas.
irá aguardar a
na variável .
Página 121
15.2. Saída
O comando
ou
permite que o programa escreva um ou mais valores
na tela do computador. Ao processar o programa o sistema operacional abre um
ambiente de execução com sua respectiva janela. Ao executar o comando
o
programa escreve a partir da posição atual do cursor os valores indicados nos
argumentos. A diferença entre o
eo
é que o
posiciona o
cursor no início da próxima linha após escrever os valores.
A sintaxe do
para escrita na tela:
A lista de argumentos deve conter as expressões cujos resultados o
escreverá na tela.
15.3. Exemplos
i.
Elaborar um programa que leia dados como Nome, Peso, Altura e Sexo; e calcule o
Índice de Massa Corpórea.
Figura 49: Programa fonte e janela de execução
Observe lado a lado o programa e a janela de execução. As setas indicam a relação
entre a instrução e o respectivo efeito na tela. O comando
faz com que uma
informação seja escrita na janela, e o comando
faz com que o texto digitado na
janela seja armazenado nas variáveis indicadas.
Na linha de código:
a variável IMC é escrita com o formato indicado
sendo duas para as casas decimais, o que resulta em:
Introdução à Programação: Conceitos e Práticas.
que significa seis posições,
Página 122
0 2 2 . 0 9
Caso não tivesse a formatação, a saída seria:
ii.
Idem ao problema anterior com algumas variações na formatação da tela. O uso do
em vez do
permite escrever um valor na tela mantendo o cursor na
mesma linha.
Introdução à Programação: Conceitos e Práticas.
Página 123
16.
Implementando Funções
Com os recursos já apresentados é possível construirmos nossas próprias funções em
complemento às disponibilizadas com a linguagem. O uso de funções é fundamental
tanto para a modularização dos programas quanto para facilitar a reutilização de
códigos já escritos. Assim, ao depararmos com um problema devemos pensar na forma
de decompô-lo em unidades funcionais simples, de modo que o programa final trata
apenas de integrá-los adequadamente.
No exemplo anterior, onde é calculado o
–
a partir do
peso e altura de uma pessoa, o conceito de função permite que escondamos os
cálculos atrás de um nome, complementado com os argumentos necessários à
realização das contas. Deste modo, sempre que for preciso calcular este
, basta
referenciar este nome com seus respectivos argumentos.
A forma geral de uma função é:
A seguinte figura ilustra os principais elementos e conceitos relacionados com funções:
Introdução à Programação: Conceitos e Práticas.
Página 124
Figura 50: Estrutura de uma função.
No exemplo que segue serão feitas associações entre o código em
conceitos apresentados nesta figura.
e os
16.1. Exemplos
O programa e a função para cálculo do
poderiam adquirir a seguinte estrutura:
Var Altura, Peso, IMC : Real;
function getIMC (P : Real; H : Real) : Real;
Begin
getIMC := P/Sqr(H);
End;
Begin
Writeln ('Entre com Peso e Altura');
Readln (Peso, Altura);
IMC := getIMC(Peso, Altura);
Writeln ('O seu Indice de Massa Corporea é: ', IMC:6:2);
Readln;
End.
Introdução à Programação: Conceitos e Práticas.
Página 125
O passo a passo deste programa, iniciando pelo programa principal, é dado por:
1) Writeln ('Entre com Peso e Altura');
Escrever na tela o texto 'Entre com Peso e Altura' e posicionar o cursor na
próxima linha.
2) Readln
(Peso, Altura);
Aguardar a digitação de uma linha até que seja teclado
, para em seguida
armazenar na memória conforme indicado nos argumentos, sendo o primeiro
número na variável
e o segundo número na variável
.
3) IMC := getIMC(Peso, Altura);
É feita a
para executar os cálculos com
e
. Estes
são copiados para
definidos no
. Neste ponto, a execução
programa passa o controle para a função
, que ao terminar,
, que copia o
para a variável
.
os
os
do
da
4) Writeln ('O seu Indice de Massa Corporea é: ', IMC:6:2);
Escrever
uma
linha
na
tela,
composta
, seguido pelo valor de
seis posições sendo duas casas decimais.
pelo
texto
formatado com
5) Readln;
Aguardar que o usuário tecle
. Esta linha serve para que o usuário tenha
tempo de avaliar o resultado apresentado na tela.
A estrutura da função
ficou:
1) function getIMC (P : Real; H : Real) : Real;
Éo
onde são definidos: o
, os
eo
. A forma de passagem dos parâmetros também é definida
no cabeçalho. Neste caso, temos:
a) Nome:
b) Parâmetros: são dois
do tipo real, onde:
 primeiro parâmetro chama-se e ficará vinculado com o
argumento;
Introdução à Programação: Conceitos e Práticas.
do primeiro
Página 126

segundo parâmetro chama-se
argumento;
c) Tipo do Resultado: Define que o
e ficará vinculado com o
será um
do segundo
.
2) Begin
Início do
.
3) getIMC := P/Sqr(H);
É uma lógica simples onde o cálculo é dado por
. Não foi necessário
utilizar variáveis locais. O
é atribuído ao seu
.
4) End;
O resultado da função é copiado para uma
chamador poderá acessá-lo. Também indica o fim do
onde o programa
.
16.2. Exercícios
i.
Elaborar um programa que calcule a distância entre dois pontos dados pelas suas
coordenadas
Var D, Ax, Ay, Bx, By : Real;
Function getDIST (X1, Y1, X2, Y2 : Real) : Real;
Begin
getDIST := Sqrt(Sqr(X2-X1)+Sqr(Y2-Y1));
End;
Begin
Writeln ('Entre com as coordenadas dos pontos:');
Readln (Ax, Ay, Bx, By);
D := getDIST(Ax, Ay, Bx, By);
Writeln ('Distancia = ', D:6:2);
Readln;
End.
O programa principal implementa uma interface simples, onde é solicitado ao usuário
informar as coordenadas
de dois pontos. As coordenadas informadas são
armazenadas nas variáveis
. Em seguida é atribuído à variável
o
resultado de uma expressão que contém apenas a chamada a função
com os
argumentos
. Na execução da função
os argumentos já estão
Introdução à Programação: Conceitos e Práticas.
Página 127
copiados para os parâmetros
os cálculos (
√
ii.
. A única linha de código faz efetivamente
) para obtenção da distância.
Escrever uma function que receba dois números (
e
) e retorne o valor de:
.
function power (base, expoente : real) : real;
begin
power := exp (expoente*ln(base));
end;
begin
writeln (power (2, 0.5):8:5);
writeln (power (exp(1), 1):8:5);
end.
O
não calcula diretamente o valor de uma base elevado a um expoente.
As funções prontas mais próximas disto são as funções
que corresponde
a
, e
que corresponde ao logaritmo neperiano ou natural. Assim,
lançaremos mão das seguintes transformações até que se chegue a uma
combinação destas funções.
(
)
(
A expressão final utiliza somente as funções
função
codifica esta lógica.
Introdução à Programação: Conceitos e Práticas.
)
e
disponíveis no
ea
Página 128
iii.
Escrever uma function que calcule a média aritmética entre dois números:
Program ExMEDIA;
function media(a, b : real) : real;
begin
media := (a+b)/2;
end;
var x, y, z : real;
begin
writeln ('entre com dois numeros');
readln (x, y);
z := media (x, y);
writeln ('media = ',z:8:5);
end.
Especificamente para a linha
copiados para os
e ; a função
final é copiado para a variável .
iv.
os
e
são
é executada e o resultado
Escrever uma function que calcule a média aritmética entre quatro números:
Program ExMEDIA;
function media (a, b : real) : real;
begin
media := (a+b)/2;
end;
function media4 (a, b, c, d : real) : real;
begin
media4 := media(media (a,b), media (c,d));
end;
var x, y, u, v, z : real;
begin
writeln ('entre com quatro numeros');
readln (x, y, u, v);
Introdução à Programação: Conceitos e Práticas.
Página 129
z := media4 (x, y, u, v);
writeln ('media = ', z:8:5);
end.
A solução adotada para a média aritmética de quatro números foi o de aproveitar
a função já pronta que calcula a média de dois números, ou seja:
(
v.
)
Escrever uma function que calcule o seno de um ângulo utilizando a seguinte série:
⋯
Vamos limitar a série aos cinco primeiros termos, pois não temos recursos
adequados para ir muito além de forma estruturada.
Program ExSENO;
function power (base, expoente : real) : real;
begin
power := exp (expoente*ln(base));
end;
Function GrausToRad (G : Real) : Real;
Begin
GrausToRad := G*PI/180;
End;
Function MySin (X : Real) : Real;
Begin
MySin := + X
Introdução à Programação: Conceitos e Práticas.
Página 130
+
+
Power(X,
Power(X,
Power(X,
Power(X,
3)/(3*2)
5)/(5*4*3*2)
7)/(7*6*5*4*3*2)
9)/(9*8*7*6*5*4*3*2);
End;
Var Graus, Rad, Y1, Y2 : Real;
Begin
Writeln ('Entre com um ângulo em graus');
Readln (Graus);
Rad := GrausToRad (Graus);
Y1 := Sin
(Rad);
Y2 := MySin (Rad);
Writeln ('Seno Real (',Graus:5:1,') = ', Y1:15:12);
Writeln ('Seno Meu (',Graus:5:1,') = ', Y2:15:12);
End.
Para calcular o
pela série dada, o ângulo
deve estar em radianos. O
programa principal, que testará a lógica, solicitará ao usuário que forneça um
ângulo para o cálculo do
. Não é razoável que o programa requeira a
entrada em radianos, uma vez que não é a forma mais direta de compreensão.
Assim, o programa solicita a entrada de um número que representa o ângulo em
graus. Em seguida, uma expressão invocando a função
converte o
ângulo para radianos e armazena na variável
. As duas linhas que seguem
calculam o
pela função da biblioteca ( ) e pela função implementada
(
). Na sequência os resultados são apresentados na tela. Observe a
interface abaixo com três execuções seguidas, para os ângulos
e
graus.
Entre com um ângulo em graus
30
Seno Real ( 30.0) = 0.500000000000
Seno Meu ( 30.0) = 0.500000000020
Entre com um ângulo em graus
60
Seno Real ( 60.0) = 0.866025403784
Seno Meu ( 60.0) = 0.866025445100
Entre com um ângulo em graus
1110
Seno Real (1110.0) = 0.500000000000
Seno Meu (1110.0) = 877678.043396671000
Podemos observar que os resultados para
e
graus apresentam uma boa
precisão, mesmo com a grande simplificação feita nos cálculos. Porém, para o
ângulo de
graus, cujo seno deveria ser o mesmo que o seno de
graus
Introdução à Programação: Conceitos e Práticas.
Página 131
tem-se uma discrepância alarmante. Isto se deve ao fato de que a série possui
termos do tipo . No caso de
temos uma convergência rápida dos
termos. Quando o valor de for muito grande os cálculos divergem e levam a
valores como o visto acima. A solução seria reduzir o ângulo para os quadrantes
iniciais através da seguinte operação com o ângulo em radianos:
(
)
A seguinte solução acrescenta a função que faz a redução do ângulo (
e inclui este cálculo (
) na função
:
)
Program ExSENO;
function power (base, expoente : real) : real;
begin
power := exp (expoente*ln(base));
end;
Function Reduzir (X : Real) : Real;
Begin
Reduzir := Frac(X/(2*PI))*(2*PI);
End;
Function GrausToRad (G : Real) : Real;
Begin
GrausToRad := G*PI/180;
End;
Function MySin (X : Real) : Real;
Begin
X := Reduzir (X);
MySin := + X
- Power(X, 3)/(3*2)
+ Power(X, 5)/(5*4*3*2)
- Power(X, 7)/(7*6*5*4*3*2)
+ Power(X, 9)/(9*8*7*6*5*4*3*2);
End;
Var Graus, Rad, Y1, Y2 : Real;
Begin
Writeln ('Entre com um ângulo em graus');
Readln (Graus);
Rad := GrausToRad (Graus);
Y1 := Sin
(Rad);
Y2 := MySin (Rad);
Writeln ('Seno Real (',Graus:5:1,') = ', Y1:15:12);
Writeln ('Seno Meu (',Graus:5:1,') = ', Y2:15:12);
Introdução à Programação: Conceitos e Práticas.
Página 132
End.
Processando novamente este programa para as entradas de dados para os
ângulos
e
graus tem-se:
Entre com um ângulo em graus
30
Seno Real ( 30.0) = 0.500000000000
Seno Meu ( 30.0) = 0.500000000020
Entre com um ângulo em graus
60
Seno Real ( 60.0) = 0.866025403784
Seno Meu ( 60.0) = 0.866025445100
Entre com um ângulo em graus
1110
Seno Real (1110.0) = 0.500000000000
Seno Meu (1110.0) = 0.500000000020
O seno de
de
graus.
graus pela função
ficou mais adequado e igual ao
Mesmo com todos estes ajustes, esta forma de implementação da lógica do seno
ainda é muito primitiva e será consideravelmente melhorada na medida em que
forem conhecidos outros recursos da linguagem.
Introdução à Programação: Conceitos e Práticas.
Página 133
17.
Passagem de Parâmetros
O método de passagem de parâmetros estabelece como se dá a ligação entre
argumento e parâmetro. A linguagem Pascal permite duas formas de passagem de
parâmetros, sendo elas por
e por
.
17.1. Por Cópia
A passagem de parâmetro por cópia é o método
conceito será detalhado a partir do seguinte exemplo:
na linguagem Pascal. O
function foo(a : integer; b : integer) : integer;
1 begin
a := a + 1;
b := 2*b;
foo := a + b;
2 end;
var x, y, z : integer;
begin
x := 7;
y := 3;
z := foo(x, y);
Writeln (x);
3
Writeln (y);
Writeln (z);
end.
Neste exemplo, tem-se a função
que trabalha com dois parâmetros ( e ) e um
programa principal que utiliza esta função através da linha de código:
.A
figura a seguir ilustra o contexto da função
e de sua utilização.
Introdução à Programação: Conceitos e Práticas.
Página 134
Figura 51: Contexto da chamada da função foo.
A ligação entre os argumentos e os parâmetros se dá pelo método da
, onde simplesmente o valor do
é copiado para o
. Neste exemplo, no momento da chamada
o valor do
primeiro argumento ( ) é copiado para o parâmetro , o mesmo acontecendo para o
segundo argumento, cujo valor é copiado para o parâmetro .
Ao executar este programa, a seguinte tela de saída será gerada decorrente dos
:
7
3
14
Para melhor compreender estes valores, vamos apresentar a configuração de memória
em três momentos distintos, destacados no código fonte como pontos
e .
i.
Início da função
:
Neste momento os valores dos argumentos foram copiados para os parâmetros.
Nesta forma de passagem de parâmetro não há compartilhamento de memória.
Introdução à Programação: Conceitos e Práticas.
Página 135
Figura 52: Ponto 1 – Passagem por Cópia.
ii.
Final da função
:
Neste momento a função inteira já foi processada. Os valores dos parâmetros
e foram alterados e não afetam os argumentos, pois são áreas distintas de
memória. A área destinada ao resultado da função contém o valor final.
Figura 53: Ponto 2 – Passagem por Cópia.
iii.
Após a execução da linha de código que utiliza a função
:
Após o término da função e retorno ao programa chamador
as
áreas de memória destinadas aos parâmetros e resultado da função são
liberadas. Particularmente o resultado da função é copiado para uma área
temporária onde o programa chamador pode acessar o valor e armazenar em
uma área definitiva, no caso a variável .
Introdução à Programação: Conceitos e Práticas.
Página 136
Figura 54: Ponto 3 – Passagem por Cópia.
17.2. Por Referência
Outra forma de passagem de parâmetros é por
, onde o argumento deve ser
necessariamente uma variável (endereço de memória) e o parâmetro ficará vinculado a
este argumento.
.
Na linguagem
o programador define esta forma de passagem de parâmetro
acrescentando o termo
a frente do nome do parâmetro. Segue um exemplo
semelhante ao programa anterior.
function foo(var a : integer; b : integer) : integer;
1 begin
a := a + 1;
b := 2*b;
foo := a + b;
2 end;
var x, y, z : integer;
begin
x := 7;
y := 3;
z := foo(x, y);
3
Writeln (x);
Writeln (y);
Writeln (z);
end.
Observe que a única alteração no código foi o uso do
na definição do parâmetro .
Ao executar este programa, a seguinte tela de saída será gerada decorrente dos
:
8
3
Introdução à Programação: Conceitos e Práticas.
Página 137
14
A diferença em relação ao programa anterior está na variável , que passou a conter o
valor . Isto foi consequência do método de passagem de parâmetro. Observar na
sequência a visualização do comportamento do programa, nos pontos
e , perante
esta modificação.
i.
Início da função
:
O diagrama abaixo apresenta uma diferença visual entre as duas formas de
passagem de parâmetros. O parâmetro utiliza o mecanismo de passagem por
referência e o parâmetro
utiliza o mecanismo de passagem por cópia. A
característica principal da passagem de parâmetro por referência está no
. Logo, a
representação gráfica utiliza uma única célula para destacar esta característica.
As referências ao parâmetro afetam diretamente a célula da variável .
Figura 55: Ponto 1 – Passagem por Referência.
ii.
Final da função
:
Neste momento a função já foi processada. Os valores dos parâmetros e
foram alterados. Devido à forma distinta de passagem dos parâmetros, a
alteração em
afeta , enquanto que a alteração em
não afeta . A área
destinada ao resultado da função contém o valor final.
Introdução à Programação: Conceitos e Práticas.
Página 138
Figura 56: Ponto 2 – Passagem por Referência.
iii.
Após a execução da linha de código que utiliza a função
:
Após o término da função e retorno ao programa chamador
as
áreas de memória destinadas aos parâmetros e resultado da função são
liberadas. Particularmente o resultado da função é copiado para uma área
temporária onde o programa chamador pode acessar o valor e armazenar em
uma área definitiva, no caso a variável . A variável
que foi utilizada como
argumento reterá o último valor do parâmetro a, como consequência da forma de
passagem de parâmetro.
Figura 57: Ponto 3 – Passagem por Referência.
Assim, fica demonstrada a razão por que
processamento da função.
apresentará o valor
ao final do
A passagem de parâmetro por referência é utilizada quando se deseja capturar os
cálculos feitos por um módulo. Nesta situação, basta o programador utilizar uma
variável como argumento e estabelecer a ligação argumento/parâmetro pelo método de
passagem por referência.
Quando o módulo produz apenas um resultado que interessa ao programa chamador, é
usual que o programador utilize uma
para implementar a solução. Porém, se o
módulo deve produzir mais de um resultado que interessa ao programa chamador,
então a passagem de parâmetro por referência pode ser utilizada para capturar estes
valores.
Introdução à Programação: Conceitos e Práticas.
Página 139
Nesta situação, recomenda-se codificar o módulo sob a forma de
e não de
. A diferença básica entre estas duas formas é que a procedure não permite
associar um resultado ao seu nome, não podendo assim, ser invocada dentro de uma
expressão.
Dois bons exemplos de
são os módulos
e
. A
utiliza o mecanismo de passagem por referência para os seus parâmetros. Isto
explica a exigência para que os argumentos do
sejam variáveis (endereços de
memória). A
utiliza o mecanismo de passagem por cópia e por esta
razão seus argumentos podem ser expressões. Cada uma das expressões é avaliada
no momento da chamada e um valor é produzido para o argumento.
Introdução à Programação: Conceitos e Práticas.
Página 140
18.
Implementando Procedures
No tópico anterior sobre passagem de parâmetros foi visto que o mecanismo de
passagem por referência combinado com
permite que sejam transferidos
vários resultados internos da
para o módulo chamador.
O problema do cálculo das raízes de uma equação do segundo grau ilustra bem o caso
de um módulo que deve produzir mais de um resultado. É esperado que uma lógica
deste tipo produzisse pelo menos as duas raízes. Assim, segue uma solução para o
problema de obter as raízes de uma equação do segundo grau a partir dos coeficientes
, e .
As raízes são calculadas pela expressão:
√
Segue a primeira versão de um programa para o cálculo das raízes.
procedure raizes (a, b, c : real; var r1, r2 : real);
var d : real;
1 begin
d := b*b - 4*a*c;
r1 := (-b + sqrt(d))/(2*a);
r2 := (-b - sqrt(d))/(2*a);
2 end;
var x1, x2 : real;
begin
raizes (1, -12, 35, x1, x2);
writeln ('raiz 1 = ', x1:8:4);
3
writeln ('raiz 2 = ', x2:8:4);
end.
A solução adotada utiliza procedure, onde os parâmetros , e são passados por
cópia e os parâmetros
e
são por referência. Estes últimos parâmetros servirão
também como mecanismo para transferir o resultado para o programa chamador, que
neste caso é o programa principal. O diagrama mais adiante ilustra o contexto da
.
Introdução à Programação: Conceitos e Práticas.
Página 141
Observar na sequência a visualização do comportamento do programa, nos pontos
e :
i.
Início da procedure
:
O diagrama abaixo destaca as duas formas de passagem de parâmetros. Os
parâmetros ,
e
utilizam o mecanismo de passagem por cópia e os
parâmetros
e
utilizam o mecanismo de passagem por referência. A
chamada da
no programa principal é dada por:
Os argumentos
e
são copiados para os parâmetros , e , enquanto
que as variáveis
e
são passadas por referências, ficando ligadas aos
parâmetros
e . Os valores iniciais de
e
são desconhecidos, uma vez
que não foram inicializadas.
Figura 58: Ponto 1 – Calculo Raizes.
Introdução à Programação: Conceitos e Práticas.
Página 142
ii.
Final da procedure
:
Neste momento a procedure já foi processada. As raízes foram calculadas e
armazenadas nos parâmetros
e .
Figura 59: Ponto 2 – Calculo Raizes.
iii.
Após a execução da linha de código que utiliza a procedure
:
Após o término da execução da procedure e retorno ao programa chamador,
imediatamente após a linha
as áreas de memória
destinadas aos parâmetros e variáveis locais são liberadas. As variáveis
e
que foram utilizadas como argumentos reterão os últimos valores dos parâmetros
e , como consequência da forma de passagem de parâmetro.
Introdução à Programação: Conceitos e Práticas.
Página 143
Figura 60: Ponto 3 – Calculo Raizes.
Ao imprimir os valores de
e
, será visualizada a seguinte tela:
raiz 1 =
raiz 2 =
Introdução à Programação: Conceitos e Práticas.
7.0000
5.0000
Página 144
19.
Expressões Textuais
As expressões textuais expandem nossa capacidade de processar informações para
além da manipulação de números. A linguagem
apresentava nas suas
primeiras versões uma característica bem marcante que era a vocação para codificar
fórmulas matemáticas. Porém, a demanda por programas que inclui a necessidade de
tratamento de textos impulsionou as linguagens no sentido de prover estes recursos.
Desta maneira, as expressões textuais permitem combinar constantes, variáveis,
operadores e funções de tal forma a prover transformações sobre este tipo de dados.
19.1. Tipos Textuais
Os tipos de dados básicos para manipulação de textos disponíveis no
são
15
o
e a
. O tipo
ocupa
de memória e permite armazenar um
caractere
. O tipo
ocupa até
de memória e permite armazenar
uma sequencia de caracteres
.
19.2. Constantes
Observe o seguinte exemplo, onde são apresentadas as declarações de variáveis do
tipo
e
, bem como as formas de se representar um valor literal,
ou
.
As variáveis , , ,
uma delas. As variáveis
15
,
,
e
e
são do tipo
são do tipo
e ocupam
de memória cada
e foram definidas de tal forma a
Não disponível no Pascal padrão, mas disponível nas principais implementações.
Introdução à Programação: Conceitos e Práticas.
Página 145
ocuparem
,
e
de memória e permitem armazenar textos com até
,
e
caracteres. Ao não indicar o tamanho de uma variável
, é assumido o
comprimento máximo de
caracteres acrescido de
caractere para controle da
linguagem totalizando
de memória.
De modo semelhante ao que foi feito com as variáveis numéricas, vamos apresentar o
mapa de memória resultante das atribuições feitas. A seguinte tabela apresenta os
endereços de memória para cada uma das variáveis bem como a quantidade de
ocupa por elas.
Program exemplo;
Var
C1 : Char;
C2 : Char;
C3 : Char;
C4 : Char;
C5 : Char;
C6 : Char;
S1 : String;
S2 : String[30];
S3 : String[80];
Total
#bytes
1
1
1
1
1
1
256
31
81
Var
@C1
@C2
@C3
@C4
@C5
@C6
@S1
@S2
@S3
374
Endereço de Memória
Decimal
Hexa
Offset
4243456
40C000
1
4243457
40C001
1
4243458
40C002
1
4243459
40C003
1
4243460
40C004
1
4243461
40C005
1
4243462
40C006
256
4243718
40C106
31
4243749
40C125
81
374
A coluna
indica a diferença entre os endereços de duas variáveis declaradas em
sequência, permitindo observar se foram utilizados bytes de preenchimento decorrentes
do alinhamento de endereço. Neste caso, tanto o tipo
, quanto o tipo
não
tem seus endereços iniciais alinhados.
Introdução à Programação: Conceitos e Práticas.
Página 146
i.
Início do programa, porém nenhuma instrução executada:
End.
Var
Célula
End.
Var
Célula
End.
Var
Célula
1 40C000
C1
$00
25 40C018
$00
298 40C129
$00
2 40C001
C2
$00
26 40C019
$00
299 40C12A
$00
3 40C002
C3
$00
263 40C106
$00
300 40C12B
$00
4 40C003
C4
$00
264 40C107
$00
301 40C12C
$00
5 40C004
C5
$00
265 40C108
$00
302 40C12D
$00
6 40C005
C6
$00
266 40C109
$00
303 40C12E
$00
7 40C006
S1
S2
$00
267 40C10A
$00
304 40C12F
$00
8 40C007
$00
268 40C10B
$00
305 40C130
$00
9 40C008
$00
269 40C10C
$00
306 40C131
$00
10 40C009
$00
270 40C10D
$00
307 40C132
$00
11 40C00A
$00
271 40C10E
$00
308 40C133
$00
12 40C00B
$00
272 40C10F
$00
309 40C134
$00
13 40C00C
$00
273 40C110
$00
310 40C135
$00
14 40C00D
$00
274 40C111
$00
311 40C136
$00
15 40C00E
$00
275 40C112
$00
312 40C137
$00
16 40C00F
$00
276 40C113
$00
313 40C138
$00
17 40C010
$00
277 40C114
$00
314 40C139
$00
18 40C011
$00
278 40C115
$00
315 40C13A
$00
19 40C012
$00
279 40C116
$00
316 40C13B
$00
20 40C013
$00
280 40C117
$00
317 40C13C
$00
21 40C014
$00
294 40C125
$00
318 40C13D
$00
22 40C015
$00
295 40C126
$00
319 40C13E
$00
23 40C016
$00
296 40C127
$00
320 40C13F
$00
24 40C017
$00
297 40C128
$00
321 40C140
$00
S3
Pode ser observado que os
estão com valor zero, porém cabe reforçar que esta
pode não ser a ação de outros compiladores, ficando a recomendação para que o
programador inicialize explicitamente as variáveis.
A tabela ilustra apenas a parte inicial do espaço de memória ocupado pelas variáveis
,
e
a fim de não tornar muito extenso o quadro.
Introdução à Programação: Conceitos e Práticas.
Página 147
ii.
Todas as variáveis do tipo char inicializadas:
End.
Var
Célula
End.
Var
Célula
End.
Var
Célula
1 40C000
C1
$61
25 40C018
$00
298 40C129
$00
2 40C001
C2
$5B
26 40C019
$00
299 40C12A
$00
3 40C002
C3
$A7
263 40C106
$00
300 40C12B
$00
4 40C003
C4
$A8
264 40C107
$00
301 40C12C
$00
5 40C004
C5
$03
265 40C108
$00
302 40C12D
$00
6 40C005
C6
$41
266 40C109
$00
303 40C12E
$00
7 40C006
S1
S2
$00
267 40C10A
$00
304 40C12F
$00
8 40C007
$00
268 40C10B
$00
305 40C130
$00
9 40C008
$00
269 40C10C
$00
306 40C131
$00
10 40C009
$00
270 40C10D
$00
307 40C132
$00
11 40C00A
$00
271 40C10E
$00
308 40C133
$00
12 40C00B
$00
272 40C10F
$00
309 40C134
$00
13 40C00C
$00
273 40C110
$00
310 40C135
$00
14 40C00D
$00
274 40C111
$00
311 40C136
$00
15 40C00E
$00
275 40C112
$00
312 40C137
$00
16 40C00F
$00
276 40C113
$00
313 40C138
$00
17 40C010
$00
277 40C114
$00
314 40C139
$00
18 40C011
$00
278 40C115
$00
315 40C13A
$00
19 40C012
$00
279 40C116
$00
316 40C13B
$00
20 40C013
$00
280 40C117
$00
317 40C13C
$00
21 40C014
$00
294 40C125
$00
318 40C13D
$00
22 40C015
$00
295 40C126
$00
319 40C13E
$00
23 40C016
$00
296 40C127
$00
320 40C13F
$00
24 40C017
$00
297 40C128
$00
321 40C140
$00
S3
Este segundo quadro permite que seja visualizado o efeito das atribuições realizadas às
variáveis do tipo char.
Instrução
C1 := 'a';
C2 := '[';
C3 := #167;
C4 := #$A8;
C5 := ^C;
Comentário
A célula apresenta o valor hexadecimal $61 (97) que corresponde ao
código ASCII da letra 'a'.
A célula apresenta o valor hexadecimal $5B (91) que corresponde ao
código ASCII do caractere '['.
A célula apresenta o valor hexadecimal $A7 (167) que corresponde ao
código ASCII do caractere 'º'.
A célula apresenta o valor hexadecimal $A8 (168) que corresponde ao
código ASCII do caractere '¿'.
A célula apresenta o valor hexadecimal $08 (8) que corresponde ao código
Introdução à Programação: Conceitos e Práticas.
Página 148
C6 := 'A';
ASCII do caractere '♥'. Equivale a Ctrl+Letra C.
A célula apresenta o valor hexadecimal $41 (65) que corresponde ao
código ASCII da letra 'A'.
Uma constante
pode ser escrita de várias formas, sendo que as atribuições
ilustradas apresentam as mais usuais. A forma direta é envolver o caractere desejado
entre apóstrofe. A segunda maneira é indicar o código
precedido pelo caractere
Os caracteres com código
inferior a
podem ser designados pelo caractere
(equivalente a tecla
) seguido por uma letra do alfabeto
iii.
Após a execução de todas as instruções, porém antes de encerrar o programa:
End.
Var
Célula
End.
Var
Célula
End.
Var
Célula
1 40C000
C1
$61
25 40C018
$00
298 40C129
$00
2 40C001
C2
$5B
26 40C019
$00
299 40C12A
$00
3 40C002
C3
$A7
263 40C106
$00
300 40C12B
$00
4 40C003
C4
$A8
264 40C107
$00
301 40C12C
$00
5 40C004
C5
$03
265 40C108
$00
302 40C12D
$00
6 40C005
C6
$41
266 40C109
$00
303 40C12E
$00
7 40C006
S1
$00
267 40C10A
$00
304 40C12F
$00
8 40C007
$00
268 40C10B
$00
305 40C130
$00
9 40C008
$00
269 40C10C
$00
306 40C131
$00
10 40C009
$00
270 40C10D
$00
307 40C132
$00
11 40C00A
$00
271 40C10E
$00
308 40C133
$00
12 40C00B
$00
272 40C10F
$00
309 40C134
$00
13 40C00C
$00
273 40C110
$00
310 40C135
$00
14 40C00D
$00
274 40C111
$00
311 40C136
$00
15 40C00E
$00
275 40C112
$00
312 40C137
$00
16 40C00F
$00
276 40C113
$00
313 40C138
$00
17 40C010
$00
277 40C114
$00
314 40C139
$00
18 40C011
$00
278 40C115
$00
315 40C13A
$00
19 40C012
$00
279 40C116
$00
316 40C13B
$00
20 40C013
$00
280 40C117
$00
317 40C13C
$00
21 40C014
$00
294 40C125
$00
318 40C13D
$00
22 40C015
$00
295 40C126
$00
319 40C13E
$00
23 40C016
$00
296 40C127
$00
320 40C13F
$00
24 40C017
$00
297 40C128
$00
321 40C140
$00
S2
S3
Agora temos um quadro completo incluindo a configuração de memória para as
variáveis do tipo
. Os detalhes da atribuição
, são
Introdução à Programação: Conceitos e Práticas.
Página 149
apresentados no mapa a seguir. O primeiro byte está na posição
[ ] e o primeiro
caractere na posição
[ ]. O primeiro byte está reservado para a linguagem e é
utilizado para armazenar o comprimento da
, que é dado pela quantidade de
caracteres atribuídos à variável. Assim, o texto
possui dezesseis
caracteres, o que fez surgir na posição [ ] o valor
que equivale a
em decimal.
As demais posições contém o valor numérico correspondente ao código
do
caractere atribuído.
40C01B
S1
$10
s1[0]
40C01C
$4C
s1[1]
L
40C01D
$69
s1[2]
i
40C01E
$6E
s1[3]
n
40C01F
$67
s1[4]
g
40C020
$75
s1[5]
u
40C021
$61
s1[6]
a
40C022
$67
s1[7]
g
40C023
$65
s1[8]
e
40C024
$6D
s1[9]
m
40C025
$20
s1[10]
40C026
$50
s1[11]
P
40C027
$61
s1[12]
a
40C028
$73
s1[13]
s
40C029
$63
s1[14]
c
40C02A
$61
s1[15]
a
40C02B
$6C
s1[16]
l
40C02C
$00
s1[17]
Fica para o leitor analisar os efeitos na memória e na tela das atribuições em
seus respectivos
.
e
e
S2 := 'Ola Mundo'#33;
S3 := 'Linha 1'#10'Linha 2'#10'Linha 3';
19.3. Operadores
O operador disponível para textos é o de concatenação representado pelo símbolo
.
São necessários dois operandos do tipo texto, a esquerda e a direita, produzindo como
resultado um texto formado pela junção dos caracteres destes operandos. O seguinte
exemplo ilustra esta operação:
Introdução à Programação: Conceitos e Práticas.
Página 150
Var Sa, Sb, Sc : String;
Begin
Sa := 'Ciencia';
Sb := 'Computacao';
Sc := Sa + ' da ' + Sb;
Writeln (Sc);
End.
A variável
irá conter
. É comum pressupor que a
linguagem adiciona um espaço em branco entre os textos concatenados, o que não é
fato em Pascal, ficando ao programador a incumbência de codificar este caractere
separador, caso seja necessário.
19.4. Funções
A linguagem Pascal disponibiliza algumas funções e procedimentos que podem ser
utilizadas na manipulação de textos. Segue uma descrição resumida de cada uma
delas:
1)
Retorna o comprimento (quantidade de caracteres) de uma
comprimento máximo é
e uma
vazia tem comprimento zero.
. O
Exemplo:
Program ExLENGTH;
Var Sa : String;
N : Integer;
Begin
Writeln ('Entre com uma frase');
Readln (Sa);
N := Length(Sa);
Writeln ('O comprimento deste texto é: ', N);
Writeln ('O ultimo caractere é: ', Sa[N]);
end.
A interface de entrada e saída para o programa é:
Entre com uma frase
Ola mundo belo
O comprimento deste texto é: 14
O ultimo caractere é: o
Introdução à Programação: Conceitos e Práticas.
Página 151
2)
Retorna o equivalente maiúsculo de um
somente ao tipo char, enquanto que no
argumento
.
. No
padrão se aplica
é aceito também um
Exemplo:
Program ExUPCASE;
Var Sa : String;
Ch : Char;
Begin
Writeln ('Entre com uma frase toda em minuscula');
Readln (Sa);
Ch := UpCase(Sa[1]);
Writeln ('O equivalente maiusculo do primeiro char é: ', Ch);
end.
A interface de entrada e saída para o programa é:
Entre com uma frase toda em minuscula
ola mundo belo
O equivalente maiusculo do primeiro char é: O
3)
Retorna o caractere correspondente a posição
na tabela
.
Exemplo:
Program ExCHR;
Var I : Integer;
Ch : Char;
Begin
Writeln ('Entre com um número entre 32 e 128');
Readln (I);
Ch := Chr(I);
Writeln ('O caractere ASCII numero ', I, ' é o ''', Ch,'''');
end.
A interface de entrada e saída para o programa é:
Entre com um número entre 32 e 128
76
O caractere ASCII numero 76 é o 'L'
Introdução à Programação: Conceitos e Práticas.
Página 152
4)
Retorna o valor inteiro utilizado para representar o ordinal. São considerados
ordinais os tipos
,
,
e
. No caso do tipo
é
retornada a posição na tabela
.
Exemplo:
Program ExORD;
Var B : Integer;
Ch : Char;
Begin
B := Ord('a')- Ord('A');
Writeln ('A distancia entre ''a'' e ''A'' = ', B);
Ch := Chr (Ord('D') + B);
Writeln ('O minúsculo da letra ''D'' = ''', Ch, '''');
Writeln ('False = ', Ord(False));
end.
A interface de entrada e saída para o programa é:
A distancia entre 'a' e 'A' = 32
O minúsculo da letra 'D' = 'd'
False = 0
5)
Retorna a posição inicial de uma string em outra. Caso
contida em , então zero é retornado.
Substr
S
o
1
l
2
a
3
4
m
u n d o
m
5
u n d o
b e l o
6 7 8 9 10 11 12 13 14
não esteja
Pos = 5
Exemplo:
Program ExPOS;
Introdução à Programação: Conceitos e Práticas.
Página 153
Var B : Integer;
S : String;
Ch : Char;
Begin
Readln (S);
Ch := UpCase(S[1]);
B := Pos (Ch, 'AEIOU');
Writeln (B);
//
//
//
//
//
Obter uma string
Ch := maiusculo do primeiro caractere.
B := posicao de Ch em 'AEIOU'
Imprimirá zero se Ch não for vogal ou
a posição de Ch na string dada.
end.
A interface de entrada e saída para o programa é:
Ola Mundo Belo
4
6)
Retorna uma parte de uma
caracteres de a partir da posição
. O resultado é uma cópia dos
.
index = 5
S
o
1
l
2
a
3
4
m
5
u n d o
b e l o
6 7 8 9 10 11 12 13 14
Count = 4
m
u n d
Exemplo:
Program ExCOPY;
Var Sx,
S : String;
Begin
S := 'ola mundo belo';
Sx := Copy (S, 5, 4);
Writeln (Sx);
Introdução à Programação: Conceitos e Práticas.
// imprimirá 'mund'
Página 154
end.
A interface de entrada e saída para o programa é:
mund
7)
A procedure
converte um número para o formato
. O primeiro
parâmetro é um valor inteiro ou real e o segundo parâmetro deve ser a variável
que receberá a
. Uma especificação de formato pode ser adicionada ao
número.
Exemplo:
Program ExSTR;
Function IntToStr (I : Longint) : String;
Var S : String;
begin
Str (I, S);
IntToStr := S;
end;
Function RealToStr (R : Real) : String;
Var S : String;
begin
Str (R:9:6, S);
RealToStr := S;
end;
Var L : String;
begin
L :='[' + IntToStr(-475) + ']';
Writeln (L);
L :='[' + RealToStr(PI) + ']';
Writeln (L);
end.
A interface de entrada e saída para o programa é:
[-475]
[ 3.141593]
8)
Introdução à Programação: Conceitos e Práticas.
Página 155
A procedure
converte uma
para número. O primeiro parâmetro é a
cujo conteúdo se deseja converter para o seu equivalente numérico. O
segundo parâmetro é o endereço de memória onde será armazenado o valor
convertido. O terceiro parâmetro é o endereço de memória onde será
depositado um número inteiro que indica o
da conversão. Caso a
conversão foi bem sucedida, este último parâmetro conterá zero, caso contrário
conterá a posição do primeiro caractere que violou a conversão.
Exemplo:
Program ExVAL;
Var S, Sx : String;
X, P1, P2, C : Integer;
Begin
S := '>>>>>> [368] <<<<<<';
P1 := Pos ('[', S);
P2 := Pos (']', S);
Sx := Copy(S, P1+1, P2-P1-1);
Val (Sx, X, C);
Writeln (X);
End.
Neste exemplo, uma
possui em qualquer posição um número escrito
entre colchetes. Utilizando
são obtidas as posições (
e
) dos
caracteres [ e ] . Em seguida é utilizada a função
para obter uma
( ) contendo somente o número em formato texto (
). Por fim, a procedure
converte este texto para número, armazena em , e imprime na tela.
A interface de entrada e saída para o programa é:
368
19.5. Exemplos
i.
Elaborar um programa que isola a primeira palavra de uma
. Considerar que o
texto dado contenha várias palavras separadas por um espaço em branco. Incluir
também a lógica que retorna uma cópia da
sem a primeira palavra.
A solução proposta utiliza uma função denominada
para obter a primeira palavra de
uma
, e a função
para retornar o texto sem a primeira palavra.
A lógica da função
é dada por:
Function Car (S : String) : String;
Introdução à Programação: Conceitos e Práticas.
Página 156
Var P : Integer;
Begin
P := Pos (' ', S);
Car := Copy (S, 1, P-1);
End;
A linha de código
espaço em branco. A função
armazenado em .
computa a posição em da primeira ocorrência do
é utilizada par obter esta informação. O resultado é
Com o valor de P já é possível obter a primeira palavra, bastando para isto copiar um
pedaço de , iniciando na primeira posição e quantidade de caracteres igual a
, tal
como codificado na linha
.
A função
tem lógica semelhante. Segue implementação completa.
Program ExCAR;
Function Car (S : String) : String;
Var P : Integer;
Begin
P := Pos (' ', S);
Car := Copy (S, 1, P-1);
End;
Function Cdr (S : String) : String;
Var P : Integer;
Begin
P := Pos (' ', S);
Cdr := Copy (S, P+1, 255);
End;
var L : String;
Begin
L := 'Ola Mundo Belo';
Writeln (Car (L));
Writeln (Cdr (L));
End.
A interface de entrada e saída para o programa é:
Ola
Mundo Belo
ii.
Partindo das funções já codificadas, pede-se: elaborar uma solução que forneça
separadamente a segunda palavra e a terceira palavra de uma
. O texto
informado é composto por pelo menos três palavras separadas por um espaço em
branco.
Introdução à Programação: Conceitos e Práticas.
Página 157
Program ExCAR2;
Function Car (S : String) : String;
Var P : Integer;
Begin
P := Pos (' ', S);
Car := Copy (S, 1, P-1);
End;
Function Cdr (S : String) : String;
Var P : Integer;
Begin
P := Pos (' ', S);
Cdr := Copy (S, P+1, 255);
End;
Function Car2 (S : String) : String;
Begin
Car2 := car(cdr(S));
End;
Function Car3 (S : String) : String;
Begin
Car3 := car(cdr(cdr(S)));
End;
var L : String;
Begin
L := 'esta frase tem mais de tres palavras';
Writeln (Car2 (L));
Writeln (Car3 (L));
End.
O código do exemplo anterior foi completado com as funções
e
que retornam
respectivamente a segunda palavra e a terceira palavra de uma
. Observar que a lógica
utiliza uma combinação das funções
e
para obter o processamento desejado. Os
detalhes sobre a posição do espaço em branco e da cópia do texto desejado ficam apenas nas
funções
e
.
A segunda palavra de uma string pode ser obtida, primeiramente tomando a
original sem
sua primeira palavra
e desta string isolando a primeira palavra
. A
mesma estratégia pode ser empregada para a função
, que retorna a terceira palavra.
A interface de entrada e saída para o programa é:
frase
tem
Introdução à Programação: Conceitos e Práticas.
Página 158
20.
Expressões Lógicas
Expressão lógica é um recurso fundamental nas linguagens de programação, pois é
elemento presente na construção de qualquer algoritmo significativo. O tipo de dado
e os operadores lógicos formam a base para estas expressões. Os operadores
lógicos trabalham sobre os valores
e , que representam condições
ou
, produzindo resultados deste mesmo conjunto.
20.1. Tipo de Dado Boolean
Em
, o tipo de dado
admite os valores {
exemplo ilustra o tipo
.
é a base para as expressões lógicas. Uma variável
} e ocupa
de memória. O seguinte
Program ExBoolean;
Var B : Boolean;
Begin
B := False;
Writeln (Ord (B));
B := True;
Writeln (Ord (B));
End.
Observe no exemplo a atribuição dos valores
e
à variável . O tipo
é um ordinal, sendo que o
é zero e o
é . É importante observar
que as constantes são
e
sem o uso de apóstrofes.
De forma semelhante ao descrito anteriormente, uma expressão lógica combina
variáveis, operadores lógicos, constantes e funções a fim de produzir um resultado que
também é um valor lógico.
20.2. Operadores Lógicos
O tipo de dado
verdade:
admite as seguintes operações lógicas e respectivas tabelas
Operadores
i.
O resultado é
quando todos
os operandos forem
.
Introdução à Programação: Conceitos e Práticas.
Tabelas-Verdade
AND F
F
F
T
F
T
F
T
AND
A B X
F F F
Página 159
F
T
T
T
F
T
F
F
T
A
F
F
T
T
OR
B
F
T
F
T
X
F
T
T
T
A
F
F
T
T
OR
B
F
T
F
T
X
F
T
T
F
ii.
O resultado é
quando
todos os operandos forem
.
OR
F
T
F
F
T
T
T
T
OR
F
T
F
F
T
T
F
NOT F
T
T
F
iii.
É um
exclusivo, ou seja difere
do
quando os dois operandos
forem
, produzindo neste
caso um resultado
.
iv.
Retorna a negação do valor do
operando.
NOT
A X
F
T F
O seguinte exemplo ilustra o uso de operadores lógicos:
Var B : Boolean;
Begin
B := (True Or False) And (True Xor True);
Writeln (B); // imprimirá False
B := Not B;
Writeln (B); // imprimirá True
End.
A expressão
Introdução à Programação: Conceitos e Práticas.
é avaliada da seguinte forma:
Página 160
O operador
também é chamado de
e o operador
de
. Esta denominação permite compreender melhor a prioridade na execução
das operações. O operador
é executado antes que o operador
quando
estiverem no mesmo nível na expressão. O parêntesis deve ser utilizado quando se
deseja priorizar outra ordem.
Está claro que codificar expressões lógicas operando somente sobre constantes
e
não permitirá construir programas práticos. Assim, normalmente utilizamos os
para produzir os valores
e
que necessitamos em
uma expressão lógica.
20.3. Operadores Relacionais
Os operadores relacionais funcionam como se fossem perguntas feitas sobre seus
operandos a fim de produzir respostas do tipo
ou
. A sintaxe destes
operadores demanda a presença de dois operandos, sendo um à esquerda e outro à
direita do operador. Os operandos podem ser expressões de qualquer tipo, porém
compatíveis entre si. Assim, se um operando é de natureza textual (
ou
), o
outro também deverá ser do tipo textual. Da mesma forma, se um operando produz um
valor numérico (
ou
), o outro também deverá ser do tipo numérico. Os
operadores relacionais do
são:
e
, cuja descrição é:
Operador Relacional
i.
Exemplos
Var FA, FB, FC : Boolean;
S : String;
A : Integer;
X : Real;
Ch : Char;
Avalia se o valor do primeiro argumento é
ao valor do segundo argumento.
Aplica-se tanto a valores numéricos quanto
textuais.
Begin
ii.
Avalia se o valor do primeiro argumento é
que o valor do segundo argumento.
No caso de argumentos
o
entendimento é o que normalmente
utilizamos em matemática. Quando os
argumentos forem
, o termo
se
aplica a posição do elemento na tabela
. Um char é
que outro quando
ocupa uma posição superior na tabela
.
Se os argumentos forem
, o termo
equivale a perguntar se o primeiro
argumento vem após o segundo argumento
no caso de ordem alfabética, também
orientada pela tabela
.
iii.
l)
Introdução à Programação: Conceitos e Práticas.
// FA será True se a string S conter
// 'Joao' e a variável A for maior
// que 30 e X diferente de zero.
FA := (S = 'Joao') And
(A > 30) And
(X <> 0);
// FB será True se o char em Ch for o
// caractere 'a' ou 'e' ou 'i'
FB := (Ch = 'a') Or
(Ch = 'e') Or
(Ch = 'i');
// FC será True se o char em Ch
// estiver entre o caractere '0'
// e '9' na tabela ASCII.
FC := (Ch >= '0') And (Ch <= '9');
Página 161
Explicação semelhante ao
.
iv.
Explicação semelhante ao .
v.
Explicação semelhante ao
.
vi.
Explicação semelhante ao
// FA será True se o valor de X
// for maior que raiz quadrada de 2
// e menor que raiz quadrada de 3
FA := (X > Sqrt(2)) And
(X < Sqrt(3));
// FB será True se o valor de X
// for menor ou igual a
// OU maior ou igual a
FB := (X <= PI/2) OR
(X >= PI);
//
//
//
//
//
FC será True se a string S
contiver uma sequencia de
caracteres que resulte
alfabeticamente a frente (maior)
da string 'Pedro'
FC := (S > 'Pedro');
//
//
//
//
FA será True se o primeiro
caractere da string S estiver
entre o caracter 'a' e 'z' na
tabela ASCII.
FA := (S[1] >= 'a') AND
(S[1] <= 'z');
End.
20.4. Exemplos
i.
Elaborar um programa que informa se um determinado caractere é uma vogal.
A solução proposta utiliza uma função chamada
que avalia se o caractere dado
é ou não uma vogal. O programa principal serve para testar alguns casos com o objetivo
de validar a lógica. A função
pode ser codificada de várias maneiras, utilizando
apenas os recursos já apresentados.
Program ExLOGICA;
Function IsVogal0 (Ch : Char) : Boolean;
Begin
Ch := UpCase (Ch);
IsVogal0 := Pos(Ch, 'AEIOU') <> 0;
End;
Function IsVogal (Ch : Char) : Boolean;
Begin
Ch := UpCase (Ch);
IsVogal := (Ch = 'A') OR (Ch = 'E') OR
(Ch = 'I') OR (Ch = 'O') OR
(Ch = 'U');
End;
Introdução à Programação: Conceitos e Práticas.
Página 162
Begin
Writeln
Writeln
Writeln
Writeln
End.
(IsVogal('a'));
(IsVogal('O'));
(IsVogal('0'));
(IsVogal('T'));
A primeira versão da função
utiliza a função
para determinar se um
caractere é vogal ou não. Neste caso a pergunta que se faz é se a posição do caractere
na string
é diferente de zero. O caso afirmativo indica que
é um dos
caracteres indicados, ou seja, é uma vogal. Observar que antes disso o conteúdo da
variável
é substituído pelo seu equivalente maiúsculo, com o uso da função
.
A segunda solução utiliza uma expressão lógica completa composta por cinco
perguntas, sendo cada uma delas avaliando se o caractere é uma das vogais. Um
principiante em programação normalmente pergunta se a expressão não poderia ser
escrita na forma:
A resposta é
não do tipo
, pois os operadores lógicos necessitam de operandos booleanos e
como utilizado.
A interface de entrada e saída para o programa é:
TRUE
TRUE
FALSE
FALSE
ii.
Elaborar um programa que informa se um determinado caractere é uma consoante.
A solução proposta utiliza duas funções de apoio, sendo uma a
e outra a
que avalia se um caractere é ou não uma letra do alfabeto. Assim, um caractere
será uma consoante se for ao mesmo tempo uma letra e não for vogal. O programa
principal serve para testar alguns casos com o objetivo de validar a lógica.
Program ExLOGICA;
Function IsLetra (Ch : Char) : Boolean;
Begin
Ch := UpCase (Ch);
IsLetra := (Ch >= 'A') AND (Ch <= 'Z');
End;
Function IsVogal (Ch : Char) : Boolean;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 163
Ch := UpCase (Ch);
IsVogal := (Ch = 'A') OR (Ch = 'E') OR
(Ch = 'I') OR (Ch = 'O') OR
(Ch = 'U');
End;
Function IsConsoante (Ch : Char) : Boolean;
Begin
Ch := UpCase (Ch);
IsConsoante := IsLetra(Ch) And (Not IsVogal(Ch));
End;
Begin
Writeln
Writeln
Writeln
Writeln
End.
A função
(IsConsoante('a'));
(IsConsoante('B'));
(IsConsoante('x'));
(IsConsoante('3'));
testa se um caractere está entre o
eo
combina adequadamente as funções
na tabela
e
. A função
através da
expressão:
A função
retornar
retornará
se
retornar
e
.
A interface de entrada e saída para o programa é:
FALSE
TRUE
TRUE
FALSE
Introdução à Programação: Conceitos e Práticas.
Página 164
21.
Instruções de Controle
Até o momento foram apresentados recursos de programação que permitem escrever
algoritmos compostos por linhas de código cuja execução ocorre em sequência, uma
linha após a outra. Ao concluir o processamento de uma linha a próxima será
executada, e assim sucessivamente. A seguinte figura ilustra o fluxo de processamento
de um módulo contendo apenas instruções executadas em
.
O processamento inicia no
até alcançar o final do módulo no
e flui executando cada uma das linhas de código,
.
Estas linhas de código, com os recursos vistos, podem ser do tipo comandos de
atribuição ou chamadas de procedures. O lado direito dos comandos de atribuição pode
incluir expressões com funções. Assim, quando uma linha de código invoca uma
ou
, tem-se um fluxo semelhante ao da figura que segue:
Ainda nesta situação, tem-se o seguinte fluxo único para a execução do programa.
Os problemas práticos demandam programas robustos o suficiente, que não produzam
erros de execução que causam a parada do sistema. Isto significa dizer que as lógicas
devem ser completas no sentido de incluir o tratamento adequado de possíveis erros e
quando possível prevenir que instruções sejam executadas na iminência de falhas.
Como exemplo, citamos a lógica já implementada de cálculo das duas raízes de uma
equação do segundo grau. A lógica codifica apenas as expressões que levam ao
cálculo das raízes. Porém, há erros potenciais que podem se manifestar quando as
Introdução à Programação: Conceitos e Práticas.
Página 165
expressões forem avaliadas, tais como a divisão por zero e a raiz de um delta negativo.
Assim, o programador deve pensar na lógica que desvie o fluxo de processamento para
um caminho seguro que evita a avaliação das expressões nos casos que levam a erro
de execução. As linguagens de programação disponibilizam instruções que permitem
ao programador fazer a
entre caminhos alternativos de processamento.
Outra categoria de problemas práticos requer a codificação de cálculos que repetem um
mesmo padrão da lógica por inúmeras vezes. Um exemplo deste comportamento é o
cálculo da função
através de uma série, onde as parcelas possuem uma forma
padrão. Para estes problemas o algoritmo normalmente submete a forma padrão a um
processamento repetitivo de cálculo. Assim, é fundamental que a linguagem permita
que uma ou mais instruções sejam processadas várias vezes sem que o programador
tenha que duplicar códigos semelhantes. A estrutura que permite este recurso é
denominada de
.
Em síntese, uma linguagem de programação de alto nível deve prover mecanismos de
controle do fluxo de execução que se enquadrem nas seguintes categorias:



;
;e
.
Assim, é possível codificar qualquer problema computável combinando estas três
construções de controle.
21.1. Seleção – IF-THEN-ELSE
O
disponibiliza uma instrução de seleção que possibilita ao usuário definir dois
caminhos alternativos que serão escolhidos no momento da execução do programa
dependendo do valor de uma expressão lógica. Como a expressão lógica admite dois
valores possíveis, então um caminho de processamento é associado ao valor
eo
outro caminho é associado ao valor
.
21.1.1.
Sintaxe e Semântica
A sintaxe da instrução é:
Desenhando um diagrama para melhor visualizar a estrutura da
, tem-se:
Introdução à Programação: Conceitos e Práticas.
Página 166
Se qualquer um dos caminhos tiver mais de uma instrução associada, então as
instruções deverão estar definidas como blocos através do uso do
⋯
.
A execução do
inicia com a avaliação da expressão lógica e em
seguida com o teste do valor resultante. Caso o valor da expressão seja
então
serão processadas as instruções associadas ao caminho
. Caso contrário, serão
executadas as instruções associadas ao caminho
.
A cláusula
é opcional, o que proporciona uma variação da instrução:
O diagrama para a
é dado por:
A execução do
inicia com a avaliação da expressão lógica e em seguida com
o teste do valor resultante. Caso o valor da expressão seja
então serão
processadas as instruções associadas ao caminho
. Caso contrário, o
processamento segue para a próxima instrução após a instrução
.
Introdução à Programação: Conceitos e Práticas.
Página 167
21.1.2.
Exemplos
Os exemplos abaixo relacionados apresentam várias formas de utilização da instrução de
controle
a partir de diagramas com as lógicas.
Diagrama
Programa
Program exIF_THEN;
Var X, Y : Real;
A, B : Integer;
Begin
If X > Y
Then A := 1
Else A := 2;
i.
// Se a expressão
for
// executada a instrução
// será executada a instrução
If X >
Begin
A :=
B :=
End
Else
então será
caso contrário
.
10 Then
1;
2;
A := B + 1;
ii.
// Se a expressão
for
então
// serão executadas as duas instruções
// associadas a cláusula
, caso contrário
// será executada a única instrução associada ao
//
. Observe o
⋯
envolvendo as
// duas instruções associadas ao
.
iii.
Introdução à Programação: Conceitos e Práticas.
If X <= 10
Then A := 1
Else Begin
A := 2;
B := 1;
End;
// Observe a ausência do
antes do
Página 168
If X >= 10 Then
Begin
A := -1;
B := -2;
End
Else Begin
A := 3;
B := 4;
End;
iv.
End.
anteriores que o
presença de
. Observe nos exemplos
nunca vem precedido deste símbolo. Outra situação de destaque é a
, como nos seguintes casos:
If X > Y Then
If X <> 0
Then A := 1
Else A := 2;
If X > Y Then
If X <> 0
Then A := 1
Else A := 2;
Observe que as soluções acima são idênticas, pois possuem exatamente a mesma sequência
de palavras (
). O deslocamento (
) do texto mais para esquerda ou para a
direita não afeta em nada a forma como a linguagem interpreta a sentença. Assim, uma das
duas construções não representa o diagrama correspondente. Está claro no desenho que são
lógicas distintas. Este caso ficou conhecido no Algol como
. A linguagem
resolve esta ambiguidade afirmando que na dúvida a que
pertence o
, o
fica
vinculado ao
mais interno. Havendo a necessidade em vincular o
ao
mais externo,
um bloco
⋯
deverá ser utilizado, como indicado no código abaixo:
If X > Y Then
Begin
If X <> 0
Then A := 1
End
Else A := 2;
Introdução à Programação: Conceitos e Práticas.
If X > Y Then
If X <> 0
Then A := 1
Else A := 2;
Página 169
v.
Calcular as raízes
e
de uma equação do segundo grau a partir dos coeficientes ,
e . A solução deverá produzir um valor
que indica o
dos cálculos de
acordo com a seguinte convenção:



0  sem erro: raízes calculadas
1  se
2  se
A solução adotada anteriormente para o cálculo das raízes poderá em fim ser
completada com o tratamento adequado das condições que poderiam levar a um erro na
execução da lógica.
Assim, devemos construir uma nova lógica que desvia o fluxo de execução do módulo
para que não ocorram nem
nem
.
Observe no diagrama abaixo proposto, que a cláusula
é utilizada para
testar inicialmente o valor do coeficiente e desviar para o cálculo das raízes somente
no caso de passar pelo teste de
. Superado este primeiro teste, o
é
calculado e um novo teste é feito direcionando o fluxo para o cálculo das raízes somente
em caso de
. Nos casos de falha nos testes a cláusula else é executada
atribuindo ao parâmetro
a condição do erro.
Figura 61: Diagrama lógico para o cálculo das raízes de uma equação do 2º grau.
Program ExRaizes;
procedure raizes (a, b, c : real;
var r1, r2 : real;
var code : integer);
var d : real;
begin
Introdução à Programação: Conceitos e Práticas.
Página 170
if a <> 0 then
begin
d := b*b - 4*a*c;
if d >= 0 then
begin
code := 0;
r1 := (-b + sqrt(d))/(2*a);
r2 := (-b - sqrt(d))/(2*a);
end
else code := 2;
end
else code := 1;
end;
procedure show (code : integer; x1, x2 : real);
begin
If code = 0 Then
begin
Writeln ('Raiz 1 = ', x1:8:4);
Writeln ('Raiz 2 = ', x2:8:4);
end
Else If Code = 1
Then writeln ('erro: a = 0')
Else If Code = 2
Then writeln ('erro: delta < 0');
end;
var a1, b1, c1, x1, x2 : real;
code : integer;
begin
Writeln ('Entre com os coeficientes A, B e C:');
Readln (a1, b1, c1);
raizes (a1, b1, c1, x1, x2, code);
show (code, x1, x2);
end.
A solução proposta inclui o módulo
do processamento da seguinte forma:



Se
Se
Se
que permite apresentar na tela os resultados
 mostrar as raízes calculadas
 mostrar a mensagem
 mostrar a mensagem
Introdução à Programação: Conceitos e Práticas.
Página 171
A seguinte tela mostra os resultados de quatro processamentos independentes do
programa completo:
Entre com os coeficientes A, B e C:
1 4 4
Raiz 1 = -2.0000
Raiz 2 = -2.0000
Entre com os coeficientes A, B e C:
1 6 3
Raiz 1 = -0.5505
Raiz 2 = -5.4495
Entre com os coeficientes A, B e C:
4 6 3
erro: delta < 0
Entre com os coeficientes A, B e C:
0 3 5
erro: a = 0
vi.
Uma família de problemas muito comum em situações reais é a relacionada com a
manipulação de datas. Assim, este exemplo pede uma solução para o cálculo da
quantidade de dias de um determinado mês e ano.
A solução consiste em retornar a quantidade de dias conforme o valor do parâmetro
mês. Para os meses
e
a quantidade de dias é ; para os meses
e
a quantidade de dias é ; e para o mês a quantidade de dias é
para anos
normais e
para ano bissexto. Assim, a solução proposta inclui uma função para
indicar se um ano é bissexto ou não.
Em função das inúmeras alterações que o calendário foi submetido ao longo dos
tempos, acabou sendo consolidado o padrão solar. O ano solar, ou seja, o tempo que a
leva para completar um ciclo em torno do
te a duração de
ou
dias. Para sincronizar o calendário e o tempo solar foi introduzido, pelos
imperadores
e
, o ano bissexto para compensar a fração de dia não
considerada no total de dias do ano. Esta mudança fez com que os anos que fossem
múltiplos de 4 passassem a ter
dias, e os demais
dias. Mesmo com esta
alteração, a diferença entre a duração média do novo calendário com
dias e o
valor real de
conduzia a defasagem significativa no longo prazo. Deste modo,
o
, em
, suprimiu
dias do calendário e
determinou que o dia
fosse seguido pelo dia
. As regras para
foram ajustadas e ficou estabelecido que16:



de
de
de
em anos é ano bissexto.
em
anos não é ano bissexto.
em
anos é ano bissexto.
16
http://pt.wikipedia.org/wiki/Ano_bissexto
Leap Years: the rule. U.S. Naval Observatory (14 September 2007).
Introdução à Programação: Conceitos e Práticas.
Página 172

prevalecem as últimas regras sobre as primeiras.
De forma simplificada os anos múltiplos de são bissextos. Os anos múltiplos de
são excluídos, e os múltiplos de
incluídos novamente. Segue a implementação
proposta:
Program exDATA;
Function IsLeap (A : Integer) : Boolean;
Begin
IsLeap := (A Mod 4 = 0) And
((A Mod 100 <> 0) Or (A Mod 400 = 0));
End;
Function NumberOfDays (M, A : Integer) : Integer;
Begin
If (M = 1) OR (M = 3) OR (M = 5) OR (M = 7) OR
(M = 8) OR (M = 10) OR (M = 12) Then
NumberOfDays := 31
Else If (M = 4) OR (M = 6) OR (M = 9) OR (M = 11) Then
NumberOfDays := 30
Else If (M = 2) Then
If IsLeap (A) Then
NumberOfDays := 29
Else
NumberOfDays := 28
Else
NumberOfDays := 0;
End;
Begin
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
End.
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
( 2,
( 1,
( 2,
(12,
( 2,
(15,
2000));
1996));
1996));
1600));
2013));
2000));
A saída para o programa é:
29
31
29
31
28
0
O seguinte
pode ser substituído por uma expressão:
Introdução à Programação: Conceitos e Práticas.
Página 173
If IsLeap (A)
Then NumberOfDays := 29
Else NumberOfDays := 28
A função
retorna
seguinte expressão:
ou
, que se convertido para
ou
pode dar origem a
NumberOfDays := 28 + Ord(IsLeap (A));
A expressão
faz a conversão do valor
para inteiro ( ou ). Assim, a função ficaria conforme segue:
retornado por
Function NumberOfDays (M, A : Integer) : Integer;
Begin
If (M = 1) OR (M = 3) OR (M = 5) OR (M = 7) OR
(M = 8) OR (M = 10) OR (M = 12) Then
NumberOfDays := 31
Else If (M = 4) OR (M = 6) OR (M = 9) OR (M = 11) Then
NumberOfDays := 30
Else If (M = 2) Then
NumberOfDays := 28 + Ord(IsLeap (A))
Else
NumberOfDays := 0;
End;
vii.
Implementar uma solução que incrementa em um dia uma data válida (dia, mês e ano).
A solução consiste em incrementar o dia em , e testar se o resultado não extrapolou a
quantidade de dias permitida para o mês. Em caso positivo, o dia passa para e o mês
é incrementado de , testando agora se o mês não excedeu aos
permitidos para o
ano. Em caso positivo, o mês passa para e o ano é incrementado de . Segue esta
solução:
Program exDATA;
Function IsLeap (A : Integer) : Boolean;
{ igual a implementação anterior}
Function NumberOfDays (M, A : Integer) : Integer;
{ igual a implementação anterior}
Procedure IncDate (Var D, M, A : Integer);
Begin
Inc (D);
If D > NumberOfDays (M, A) Then
Begin
D := 1;
Introdução à Programação: Conceitos e Práticas.
Página 174
Inc (M);
If M > 12 Then
Begin
M := 1;
Inc (A);
End;
End;
End;
Var Dia, Mes, Ano : Integer;
Begin
Writeln
Readln
IncDate
Writeln
End.
('Entre com uma data: dd mm aaaa');
(Dia, Mes, Ano);
(Dia, Mes, Ano);
('O dia seguinte é: ', Dia, Mes:3, Ano:5);
A solução adotada utiliza
como opção, uma vez que a melhor modelagem
para este problema é fornecer três variáveis para a rotina e esperar que a lógica da
modifique estas variáveis com os novos valores para a data adiantada em um
dia. Em função disso, a
adotada é a
,
permitindo que toda alteração nos parâmetros possa ser captada pelos argumentos.
Os módulos
e
tiveram seus códigos omitidos para melhor
visualização da solução. A seguinte tela ilustra as entradas e saídas para alguns testes:
Entre com uma data: dd mm aaaa
1 1 2000
O dia seguinte é: 2 1 2000
Entre com uma data: dd mm aaaa
10 10 2010
O dia seguinte é: 11 10 2010
Entre com uma data: dd mm aaaa
31 1 2012
O dia seguinte é: 1 2 2012
Entre com uma data: dd mm aaaa
31 12 2009
O dia seguinte é: 1 1 2010
Introdução à Programação: Conceitos e Práticas.
Página 175
21.2. Seleção – CASE
A construção de controle do tipo
proporciona dois caminhos
alternativos para o fluxo de processamento. Uma expressão do tipo
é utilizada
como ponto de decisão para a escolha do trajeto a ser tomado. Um dos caminhos está
associado ao valor
e o caminho alternativo está associado ao valor
.
Em determinados problemas é comum que o código resultante se enquadre em um
aninhamento (estruturas embutidas) de
, como o visto na função
. Especificamente para situações semelhantes, a linguagem
disponibiliza a construção
que permite a escolha de um entre múltiplos caminhos
possíveis. O ponto de decisão deixa de ser uma expressão booleana, que admite
apenas dois valores, e passa a ser uma expressão ordinal, que no caso dos inteiros e
char, admitem múltiplos valores.
21.2.1.
Sintaxe e Semântica
A sintaxe da construção de controle
é dada por:
A versão original do
não apresenta a cláusula
. Algumas versões de
compiladores
aceitam a palavra
como variação do
. Se várias
instruções estiverem associadas à condição, então deve ser utilizado o bloco
⋯
para envolver as instruções. O seguinte diagrama ilustra o significado da
construção
:
Introdução à Programação: Conceitos e Práticas.
Página 176
Figura 62: Instrução CASE
Em grande parte dos problemas a expressão ordinal utilizada para direcionar o
é
do tipo inteiro ou char. Além destes, a expressão pode ser do tipo enumerado, cujo
conceito será visto mais adiante. Não é permitido o uso de expressão do tipo
ou
, pois estes tipos não são ordinais.
O diagrama anterior indica que o
inicia com uma expressão ordinal, cujo resultado
é testado quanto a pertinência a um conjunto de valores, que em caso positivo as
instruções associadas serão executadas. Em caso negativo, é feito o teste seguinte em
relação a outro conjunto de valores, que em caso positivo as instruções associadas
serão executadas, e assim sucessivamente. Opcionalmente, pode ser incluída uma
cláusula
que será executada no caso de falha dos testes anteriores.
Os exemplos que seguem destacam as formas de uso desta construção.
Introdução à Programação: Conceitos e Práticas.
Página 177
21.2.2.
i.
Exemplos
Refazer o programa que informa se um determinado caractere é uma consoante.
As funções
e
código listado abaixo:
serão reescrita utilizando a construção
, conforme o
Program ExLOGICA;
Function IsLetra (Ch : Char) : Boolean;
Begin
Case UpCase(Ch) Of
'A'..'Z' : IsLetra := True;
Else
IsLetra := False;
End;
End;
Function IsVogal (Ch : Char) : Boolean;
Begin
Case UpCase(Ch) Of
'A', 'E', 'I', 'O', 'U' : IsVogal := True;
Else
IsVogal := False;
End;
End;
Function IsConsoante (Ch : Char) : Boolean;
Begin
Ch := UpCase (Ch);
IsConsoante := IsLetra(Ch) And (Not IsVogal(Ch));
End;
Begin
Writeln
Writeln
Writeln
Writeln
End.
O
tabela
(IsConsoante('a'));
(IsConsoante('B'));
(IsConsoante('x'));
(IsConsoante('3'));
utilizado na função
:
testa se um caractere está entre o
e o
na
Case UpCase(Ch) Of
'A'..'Z' : IsLetra := True;
Else
IsLetra := False;
End;
Introdução à Programação: Conceitos e Práticas.
Página 178
A expressão avaliada é dada por
. O primeiro e único teste é pela
pertinência deste valor no conjunto de valores dado pelos elementos formados pelos
caracteres de
a
. O uso de dois pontos seguidos
equivale ao
conjunto formado por todos elementos neste intervalo. Se este teste falhar, será
executada a instrução associada à cláusula
.
O
utilizado na função
formado pelas vogais.
avalia se o caractere dado pertence ao conjunto
Case UpCase(Ch) Of
'A', 'E', 'I', 'O', 'U' : IsVogal := True;
Else
IsVogal := False;
End;
A expressão avaliada é dada novamente por
. O primeiro e único teste é
pela pertinência deste valor no conjunto formado pelas vogais {
}.
A função
não foi alterada, e retornará
for
e o resultado de
for
.
se o resultado de
A saída para o programa é:
FALSE
TRUE
TRUE
FALSE
ii.
Refazer o programa para o cálculo da quantidade de dias de um determinado mês e
ano.
Segue a solução proposta:
Program exDATA;
Function IsLeap (A : Integer) : Boolean;
Begin
IsLeap := (A Mod 4 = 0) And
((A Mod 100 <> 0) Or (A Mod 400 = 0));
End;
Function NumberOfDays (M,
Begin
Case M Of
1, 3, 5, 7, 8, 10, 12
4, 6, 9, 11
2
Else
A : Integer) : Integer;
: NumberOfDays := 31;
: NumberOfDays := 30;
: NumberOfDays := 28 + Ord(IsLeap(A))
Introdução à Programação: Conceitos e Práticas.
Página 179
NumberOfDays := 0;
End;
End;
Procedure IncDate (Var D, M, A : Integer);
Begin
Inc (D);
If D > NumberOfDays (M, A) Then
Begin
D := 1;
Inc (M);
If M > 12 Then
Begin
M := 1;
Inc (A);
End;
End;
End;
Var Dia, Mes, Ano : Integer;
Begin
Writeln
Readln
IncDate
Writeln
End.
('Entre com uma data: dd mm aaaa');
(Dia, Mes, Ano);
(Dia, Mes, Ano);
('O dia seguinte é: ', Dia, Mes:3, Ano:5);
Observe que a função
, reescrita com o
melhora na legibilidade em relação a versão anterior com
iii.
, apresenta uma sensível
.
Fornecer uma solução para a conversão de um número decimal de a
para o dígito
hexadecimal em forma de caractere. Incluir também a conversão de um caractere
contendo um dígito hexadecimal ( a ) em seu equivalente inteiro decimal.
Segue a solução proposta:
Program ExHEXA;
Function HexDigToDec (Ch : Char) : Integer;
Begin
Ch := UpCase (Ch);
Case Ch Of
'0'..'9' : HexDigToDec := Ord(Ch) - Ord('0');
'A'..'F' : HexDigToDec := Ord(Ch) - Ord('A') + 10;
Else
HexDigToDec := -1;
End;
Introdução à Programação: Conceitos e Práticas.
Página 180
End;
Function DecToHexDig (X : Integer) : Char;
Begin
Case X Of
0..9
: DecToHexDig := Chr(Ord('0') + X);
10..15 : DecToHexDig := Chr(Ord('A') + X - 10);
Else
DecToHexDig := 'X';
End;
End;
Begin
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
End.
(HexDigToDec
(HexDigToDec
(HexDigToDec
(HexDigToDec
('A'));
('0'));
('f'));
('B'));
(DecToHexDig
(DecToHexDig
(DecToHexDig
(DecToHexDig
(DecToHexDig
(0 ));
(10));
(9 ));
(15));
(20));
A função
recebe um caractere qualquer e o processa de acordo com a
convenção para os dígitos hexadecimais, ou seja:

Se for um dos caracteres de
, onde
, que subtraído de
desejado.

Se for um dos caracteres de
a
então o resultado é o valor da expressão
, onde
é o número com a posição de
na
tabela
, que subtraído de
, fornecerá um valor de
a , que
somado com , retornará o resultado de
a , conforme desejado.

Qualquer outro caractere resultará em
a
então o resultado é o valor da expressão
é o número com a posição de
na tabela
, fornecerá o resultado de 0 a 9, conforme
.
A função
codifica o comportamento inverso da função anterior. Fica a
cargo de o leitor estudar e entender a lógica utilizada.
Introdução à Programação: Conceitos e Práticas.
Página 181
A saída para o programa é:
10
0
15
11
0
A
9
F
X
As conversões pedidas podem ter lógicas alternativas utilizando outros recursos já
apresentados. Segue outra versão possível:
Program ExHEXA;
Function HexDigToDec (Ch : Char) : Integer;
Begin
HexDigToDec := Pos (UpCase(Ch), '0123456789ABCDEF') - 1;
End;
Function DecToHexDig (X : Integer) : Char;
Var S : String;
Begin
S := '0123456789ABCDEF';
Case X Of
0..15
: DecToHexDig := S[X+1];
Else
DecToHexDig := 'X';
End;
End;
Begin
{mesmo programa principal anterior}
End.
A solução para
utiliza a função
para obter a posição do caractere
na
, cujo resultado será um número de a , dependendo
do caractere. Para obter o equivalente decimal basta subtrair
deste valor. Caso o
caractere não seja nenhum dos relacionados na
, então
retornará
que
subtraído , resultará em
para esta condição.
A
função
retorna um dos caracteres da
de apoio
quando o valor de estiver entre 0 e 15. O caractere desejado é
o que se encontrar na posição
, uma vez que quando
é , o caractere
correspondente se encontra na posição .
Introdução à Programação: Conceitos e Práticas.
Página 182
Quando se deseja apenas um caractere de uma
,
, mas
sim o
. Por exemplo, se for necessário atribuir a variável
o caractere
que está na posição
de , a forma
[ ] é preferível em relação a
.
21.3. Repetição – FOR⋯DO
A estrutura de repetição completa os recursos de uma linguagem tipo
e amplia
as possibilidades de controle sobre o fluxo de execução de um programa. A estrutura
de repetição permite que uma ou mais instruções sejam executadas várias vezes de
acordo com a necessidade do problema. Assim, ao modelar um problema e desenhar o
algoritmo, deve ser pensada uma lógica que represente a situação de uma forma geral.
Por exemplo, se é necessário obter as notas de
alunos para calcular a média da
turma, não é razoável construir uma lógica com
. Deve haver um
mecanismo que determine a repetição de
vezes a instrução desejada.
As linguagens da família
elas:


disponibilizam várias estruturas de repetição, sendo
Repetição controlada por contador;
Repetição controlada por expressão lógica;
o Pré-teste;
o Pós-teste
A repetição controlada por contador também é conhecida como estrutura tipo
apresentada neste tópico.
21.3.1.
,eé
Sintaxe e Semântica
A sintaxe da instrução de repetição tipo FOR é:
Onde,



é uma variável do tipo ordinal denominada
da repetição (
) ou
apenas
;
é uma expressão ordinal compatível com o tipo de , cujo resultado indica o valor
inicial de ;
é uma expressão ordinal compatível com o tipo de , cujo resultado indica o valor
final de ;
Introdução à Programação: Conceitos e Práticas.
Página 183
A seguinte figura ilustra os componentes da instrução
, bem como destaca a
dinâmica da estrutura com os vários ciclos de execução da instrução controlada, onde
cada ciclo tem o valor do contador incrementado de .
Figura 63: Repetição do tipo FOR.
O seguinte diagrama lógico permite visualizar o fluxo do processamento:
Figura 64: Estrutura de Controle do tipo FOR
Neste diagrama podemos verificar o funcionamento da instrução
. A variável de
controle é inicializada com o valor , em seguida é realizado um teste para certificar
que
. Sendo verdadeiro, então as instruções controladas são executadas e o
valor de é incrementado de . O fluxo é novamente direcionado para a pergunta sobre
o valor de em relação a . A repetição se encerra quando
.
Introdução à Programação: Conceitos e Práticas.
Página 184
21.3.2.
i.
Exemplos
Implementar a seguinte somatória para N termos:
⋯
A série possui termos, onde pode ser qualquer valor maior que um. Os termos da
série possuem a seguinte forma geral:
Assim, é necessário agora formular uma solução para gerar cada um dos termos, e
somá-los a fim de atender a especificação do problema. Segue solução implementada:
Program ExSERIE;
Function SomaSerie (N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 1 To N Do
S := S + 1/I;
SomaSerie := S;
End;
Begin
Writeln (SomaSerie(2) :8:6);
Writeln (SomaSerie(5) :8:6);
Writeln (SomaSerie(100):8:6);
End.
A função
utiliza duas variáveis, sendo a variável de controle do
ea
variável
para acumular os termos gerados em cada ciclo de execução. A função
recebe como parâmetro a quantidade de termos que se pretende considerar para a
série. A seguinte tabela ilustra os cinco ciclos de execução da chamada
.
I
Instrução
S
1
S := S + 1/I;
S := 0 + 1/1
1
2
S := S + 1/I;
S := 1 + 1/2
1.5
3
S := S + 1/I;
S := 1.5 + 1/3
1.833333
4
S := S + 1/I;
S := 1.8333 + 1/4
2.083333
5
S := S + 1/I;
S := 2.0833 + 1/5
2.283333
Introdução à Programação: Conceitos e Práticas.
Página 185
A coluna
contém os valores da variável de controle em cada ciclo. A coluna
apenas reforça que a cada ciclo a mesma instrução é executada. A
coluna
destaca como a variável vai sendo atualizada a cada ciclo pela atribuição do
valor da expressão a direita e acumulando o valor de cada termo. Ao final do
processamento do
, a variável conterá o valor
.
A saída para o programa é:
1.500000
2.283333
5.187378
ii.
Implementar a seguinte somatória para
termos:
⋯
Esta série difere da anterior pela alternância dos sinais dos termos. Uma solução
possível é utilizar a instrução
com a variável de controle assumindo os valores
{
}, e para cada um destes valores escrever um mecanismo para produzir o
termo e o respectivo sinal, bem como acumular estas parcelas.
Assim, é necessário agora formular uma solução para gerar cada um dos termos, e
soma-los a fim de atender a especificação do problema. Segue a implementação desta
lógica:
Program ExSERIE;
Function SomaSerie (N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 1 To N Do
If I Mod 2 = 0
Then S := S - 1/I
Else S := S + 1/I;
SomaSerie := S;
End;
Begin
Writeln (SomaSerie(2) :8:6);
Writeln (SomaSerie(5) :8:6);
Writeln (SomaSerie(100):8:6);
End.
Introdução à Programação: Conceitos e Práticas.
Página 186
A lógica adotada aproveita o valor de para deduzir o sinal da parcela. Assim, quando
for par o termo deve ser diminuído (negativo) de e quando for impar deve ser somado
(positivo). O teste se é par é feito avaliando o resto da divisão de por .
Uma alternativa a esta lógica se baseia no uso de uma variável adicional para fornecer o
sinal correto a cada ciclo. Segue esta versão:
Function SomaSerie (N : Integer) : Real;
Var I : Integer;
S : Real;
T : Integer;
Begin
S := 0;
T := 1;
For I := 1 To N Do
Begin
S := S + T/I;
T := -T;
End;
SomaSerie := S;
End;
A variável é inicializa com e a cada ciclo a instrução
é executada com o
objetivo de alternar o valor de entre
e
. As parcelas passam a apresentar o
seguinte termo geral
, que constrói exatamente os termos com o sinal.
A saída para o programa é:
0.500000
0.783333
0.688172
iii.
Implementar a seguinte somatória para a quantidade de termos indicada:
⋯
Esta série poderia ser reescrita para ficar explícita a ordem de cada termo, como segue:
⋯
O termo geral desta série tem a seguinte forma:
Introdução à Programação: Conceitos e Práticas.
Página 187
Uma solução possível é utilizar a instrução
com a variável de controle assumindo
os valores {
}, e para cada um destes valores escrever um mecanismo para
produzir o termo geral, bem como acumular estas parcelas. A função
implementada anteriormente pode ser utilizada para compor a expressão que constrói
cada um dos termos.
Program ExSERIE;
function power (base, expoente : real) : real;
begin
power := exp (expoente*ln(base));
end;
Function SomaSerie (X : Real; N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 0 To N Do
S := S + Power (X, I);
SomaSerie := S;
End;
Begin
Writeln (SomaSerie(2, 2) :8:6);
Writeln (SomaSerie(2, 5) :8:6);
Writeln (SomaSerie(1, 100):8:6);
End.
Neste exemplo, a variável de controle assume valores de a , tendo associação direta
com o expoente do termo geral. A lógica fica reduzida a acumular em
o valor de
.
A desvantagem desta solução é que a cada ciclo é calculado integralmente o valor de
, o que torna esta lógica ineficiente. Por exemplo, quando
, o termo
é
calculado de forma completa, com as nove multiplicações. Porém, no ciclo anterior foi
calculado o valor de , caso fosse aproveitado o esforço computacional feito, bastaria
agregar mais uma multiplicação no ciclo atual para chegar em . Assim, a seguinte
lógica melhora a eficiência para esta série:
Function SomaSerie (X : Real; N : Integer) : Real;
Var I : Integer;
P : Real;
S : Real;
Begin
S := 0;
P := 1;
For I := 0 To N Do
Introdução à Programação: Conceitos e Práticas.
Página 188
Begin
S := S + P;
P := P*X;
End;
SomaSerie := S;
End;
Esta solução utiliza dois acumuladores: e . A variável representa cada parcela, que
é calculada acumulando o produto de ao longo dos ciclos. Esta lógica está codificada
na instrução
. O cuidado que deve ser tomado ao acumular um produto, é o
de inicializar a variável adequadamente, que neste caso é inicializado com . A variável
acumula a soma das parcelas (
).
Uma nova variante para a implementação desta série é dada pela seguinte
transformação, para alguns termos:
(
(
(
)))
Assim, a seguinte lógica melhora o desempenho para esta série:
Function SomaSerie (X : Real; N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 0 To N Do
S := S*X + 1;
SomaSerie := S;
End;
Esta solução é a mais eficiente, pois apresenta
por ciclo de execução do
.
,
e
A saída para o programa é:
7.000000
63.000000
101.000000
iv.
Implementar uma solução para o cálculo do fatorial de um
inteiro:
⋯
Introdução à Programação: Conceitos e Práticas.
Página 189
O fatorial de um é o produto de todos os inteiros entre e . A proposta é utilizar a
instrução
com a variável de controle produzindo os valores {
}, e para
cada um destes valores utilizar a técnica de acumular o produto de em uma variável. O
seguinte código implementa o cálculo do fatorial.
Program ExFATORIAL;
Function Fat (N : Integer) : LongInt;
Var F : LongInt;
I : Integer;
Begin
F := 1;
For I := 1 To N Do
F := F*I;
Fat := F;
End;
Var K : Integer;
Begin
For K := 0 To 30 Do
Writeln (K:3, ' ', Fat(K));
End.
Porém há um problema crítico, que reside no fato que o cálculo do fatorial produz um
rápido crescimento dos valores, uma vez que há um acúmulo de multiplicação. A função
retorna um resultado do tipo
, que tem
de comprimento e admite
uma faixa de
a
. Este tamanho em bits para o resultado
limita ao valor , a partir da qual há um estouro de capacidade. A solução é utilizar
um tipo com faixa maior. Assim, a função foi testada para os tipos
e
. As
seguintes saídas foram obtidas para cada um destes tipos:
LongInt
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
1932053504
1278945280
2004310016
2004189184
-288522240
-898433024
109641728
Int64
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
Introdução à Programação: Conceitos e Práticas.
Real
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
Página 190
20 -2102132736
21 -1195114496
22 -522715136
...
30 1409286144
20 2432902008176640000
21 -4249290049419214848
22 -1250660718674968576
...
30 -8764578968847253504
20
21
22
...
30
31
32
33
34
35
...
97
98
99
100
2432902008176640000
51090942171709400000
1124000727777610000000
265252859812191000000000000000000
8222838654177920000000000000000000
263130836933694000000000000000000000
8.68331761881189E+036
2.95232799039604E+038
1.03331479663861E+040
9.61927596824821E+151
9.42689044888324E+153
9.33262154439441E+155
9.33262154439441E+157
A linha sublinhada indica o valor de
a partir da qual há um estouro de capacidade.
Assim, a opção é pela versão abaixo com o uso do tipo
para o retorno da função:
Function Fat (N : Integer) : Real;
Var F : Real;
I : Integer;
Begin
F := 1;
For I := 1 To N Do
F := F*I;
Fat := F;
End;
O programador deve observar no manual do compilador quais são os tipos de dados
mais adequados entre os vários da família
.
A listagem para o tipo
também chama atenção para o fato de que a partir de certo
valor perde-se a precisão, pois a quantidade de dígitos significativos é bastante
limitada, mesmo que a faixa de representação admita números de alta magnitude. Para
o tipo
escolhido neste exemplo a capacidade é de
dígitos significativos, e
fica evidente na listagem o complemento feito com zeros a partir de igual a .
A recomendação é sempre evitar algoritmos que acumulem extensos produtos que
podem levar ao estouro de capacidade. A indicação é buscar mecanismos que
aproveitam os cálculos de ciclos anteriores, e observar se há possibilidade de priorizar
operações na expressão que contribua para manter os resultados intermediários dentro
de limites seguros. Isto pode ser obtido em algumas situações priorizando divisões antes
das multiplicações. Por exemplo, na seguinte expressão:
Na situação em que os valores de , ,
e
estejam próximos ao limite do tipo
definido, é praticamente certo que os produtos levarão ao estouro de capacidade e
consequentemente a um erro de lógica ou de execução. Esta mesma expressão pode
ser reescrita para avaliar primeiro as divisões:
Introdução à Programação: Conceitos e Práticas.
Página 191
v.
Refazer o programa que calcula o seno de um ângulo através da série:
⋯
A lógica do
já codificada foi limitada aos primeiros seis termos e se resumiu a
transcrição da série em uma expressão aritmética com a soma explícita de todas as seis
parcelas. Agora, com o recurso da repetição podemos calcular o seno com melhor
precisão. A primeira versão será a mais básica e intuitiva, pois utilizará
e
para gerar os termos.
Program ExSENO;
function power (base, expoente : Extended) : Extended;
begin
If base <> 0
Then power := exp (expoente*ln(base))
Else power := 0;
end;
Function Reduzir (X : Extended) : Extended;
Begin
Reduzir := Frac(X/(2*PI))*(2*PI);
End;
Function GrausToRad (G : Extended) : Extended;
Begin
GrausToRad := G*PI/180;
End;
Function Fat (N : Integer) : Extended;
Var F : Extended;
I : Integer;
Begin
F := 1;
For I := 1 To N Do
F := F*I;
Fat := F;
End;
Function MySin (X : Extended) : Extended;
Var S : Extended;
T, I : Integer;
Begin
X := Reduzir (X);
Introdução à Programação: Conceitos e Práticas.
Página 192
T := 1;
S := 0;
For I := 1 To 15 Do
Begin
S := S + T*Power (X, 2*I-1)/Fat(2*I-1);
T := -T;
End;
MySin := S;
End;
Var Graus, Rad, Y1 : Extended; Y2 : Extended;
I : Integer;
Begin
For I := 0 To 24 Do
Begin
Graus := I*15;
Rad := GrausToRad (Graus);
Y1 := Sin
(Rad);
Y2 := MySin (Rad);
Writeln (I:4, ' ', Graus:4:0, Y1:21:20, Y2:21:20, Y1-Y2:21:20);
End;
End.
A função
inclui uma repetição para o cálculo de
tem a seguinte forma:
termos, onde o termo geral
A menos da obtenção do sinal, a expressão que codifica cada termo tem exatamente
este formato. O sinal foi gerado a partir da variável que alterna entre
e
a cada
ciclo. Isto evita utilizar
apenas para obter
e
.
O
testa a função
em comparação à função
interna do
, e apresenta os valores dos senos e a diferença entre estes valores. O
de
vezes ( a ) serve para gerar os ângulos de a
de
em
graus, através da
expressão
.
A saída obtida foi:
I
0
1
2
3
4
5
6
7
X
0
15
30
45
60
75
90
105
SIN(X)
0.00000000000000000
0.25881904510252076
0.50000000000000000
0.70710678118654752
0.86602540378443865
0.96592582628906829
1.00000000000000000
0.96592582628906829
MYSIN(X)
ERRO
0.00000000000000000 0.00000000000000000
0.25881904510252076 0.00000000000000000
0.50000000000000000 0.00000000000000000
0.70710678118654752 0.00000000000000000
0.86602540378443865 0.00000000000000000
0.96592582628906829 0.00000000000000000
1.00000000000000000 0.00000000000000000
0.96592582628906829 -0.00000000000000000
Introdução à Programação: Conceitos e Práticas.
Página 193
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
120
135
150
165
180
195
210
225
240
255
270
285
300
315
330
345
360
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
-0.00000000000000000
-0.25881904510252076
-0.50000000000000000
-0.70710678118654752
-0.86602540378443865
-0.96592582628906829
-1.00000000000000000
-0.96592582628906829
-0.86602540378443865
-0.70710678118654752
-0.50000000000000000
-0.25881904510252076
0.00000000000000000
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
0.00000000000000000
-0.25881904510252076
-0.49999999999999997
-0.70710678118654721
-0.86602540378443635
-0.96592582628905322
-0.99999999999991161
-0.96592582628859701
-0.86602540378213313
-0.70710678117611210
-0.49999999995598198
-0.25881904492839897
0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
-0.00000000000000000
-0.00000000000000000
-0.00000000000000001
-0.00000000000000003
-0.00000000000000031
-0.00000000000000230
-0.00000000000001506
-0.00000000000008839
-0.00000000000047127
-0.00000000000230552
-0.00000000001043543
-0.00000000004401802
-0.00000000017412179
0.00000000000000000
A diferença em relação a função da biblioteca aumenta a medida que o ângulo se
aproxima de .
A lógica implementada é ineficiente, pois não aproveita os cálculos feitos no ciclo
anterior, o que aumenta consideravelmente a quantidade de multiplicações e divisões
para obter o resultado final. Este mesmo resultado pode ser obtido usando uma
onde um termo atual pode ser definido em função do termo
calculado anteriormente. Observa-se nas equações abaixo, que dois termos
consecutivos possuem uma relação entre eles cujo estilo se conserva ao longo da série.
𝑥
𝑥
𝑥
𝑥
𝑥
𝑥
𝑥
𝑥
𝑥
⋯
𝑥
O termo atual é o termo anterior multiplicado por
e dividido pelo produto de dois
números, que também podem ser generalizados em função da posição do termo na
série. Assim, temos a seguinte relação de recorrência:
Onde:
Assim, a seguinte solução é preferida em relação a anterior que utiliza
e
:
Program ExSENO;
Function Reduzir (X : Extended) : Extended;
Introdução à Programação: Conceitos e Práticas.
Página 194
{igual a anterior}
Function GrausToRad (G : Extended) : Extended;
{igual a anterior}
Function MySin (X : Extended) : Extended;
Var P, S : Extended;
I : Integer;
Begin
X := Reduzir (X);
S := 0;
P := X;
For I := 1 To 15 Do
Begin
S := S + P;
P := -P*X*X/((2*I)*(2*I+1));
End;
MySin := S;
End;
Var Graus, Rad, Y1 : Extended; Y2 : Extended;
I : Integer;
Begin
{igual ao programa principal anterior}
End.
A saída obtida foi:
I
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
X
0
15
30
45
60
75
90
105
120
135
150
165
180
195
210
225
240
255
270
285
300
SIN(X)
0.00000000000000000
0.25881904510252076
0.50000000000000000
0.70710678118654752
0.86602540378443865
0.96592582628906829
1.00000000000000000
0.96592582628906829
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
-0.00000000000000000
-0.25881904510252076
-0.50000000000000000
-0.70710678118654752
-0.86602540378443865
-0.96592582628906829
-1.00000000000000000
-0.96592582628906829
-0.86602540378443865
MYSIN(X)
0.00000000000000000
0.25881904510252076
0.50000000000000000
0.70710678118654752
0.86602540378443865
0.96592582628906829
1.00000000000000000
0.96592582628906829
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
0.00000000000000000
-0.25881904510252076
-0.49999999999999996
-0.70710678118654721
-0.86602540378443634
-0.96592582628905323
-0.99999999999991161
-0.96592582628859700
-0.86602540378213311
Introdução à Programação: Conceitos e Práticas.
ERRO
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
-0.00000000000000000
-0.00000000000000000
-0.00000000000000004
-0.00000000000000031
-0.00000000000000230
-0.00000000000001506
-0.00000000000008839
-0.00000000000047128
-0.00000000000230554
Página 195
21
22
23
24
315 -0.70710678118654752 -0.70710678117611212 -0.00000000001043541
330 -0.50000000000000000 -0.49999999995598203 -0.00000000004401797
345 -0.25881904510252076 -0.25881904492839899 -0.00000000017412177
360 0.00000000000000000 0.00000000000000000 0.00000000000000000
Além da sensível redução na quantidade de cálculos esta solução apresentou um erro
levemente menor em relação a função interna quando comparado ao erro apresentado
pela lógica anterior. Mais adiante, no tópico seguinte, será apresentada uma solução
que reduz ainda mais o erro.
vi.
Elaborar um programa que leia vários números fornecidos via teclado e apresente ao
final a somatória destes valores. Considere este esboço de interface:
A lógica deste problema é bastante simples e consiste em um loop onde deve ser lido
um dado e acumulado em uma variável. Ao encerrar a repetição o resultado é impresso.
Segue a solução proposta:
Program ExLERDADOS;
Procedure LerDados (N : Integer);
Var I : Integer;
X, S : Real;
Begin
S := 0;
Writeln ('Entre com os dados');
For I := 1 To N Do
Begin
Readln (X);
S := S + X;
End;
Writeln ('SOMA = ', S:7:2);
End;
Begin
LerDados (10);
End.
Introdução à Programação: Conceitos e Práticas.
Página 196
A seguinte figura ilustra uma saída real:
Entre com os dados
10
23
54
98
102
75
98
17
34.5
56.25
SOMA = 567.75
vii.
Elaborar um programa semelhante ao anterior, porém o usuário pode interromper a
entrada de dados fornecendo o valor
.
A lógica do problema anterior é adaptada para encerrar o loop antes do seu final,
testando pelo valor de .
O recurso da linguagem que permite encerrar o
e desviar o processamento para a
próxima instrução após o fim do
é a instrução
. Normalmente o
vem
combinado com um teste de condição, que em caso positivo desvia o fluxo para fora do
. O seguinte diagrama ilustra visualmente a instrução
inserida em um
.
Figura 65: Instrução BREAK.
Segue a solução proposta:
Program ExLERDADOS;
Introdução à Programação: Conceitos e Práticas.
Página 197
Procedure LerDados (N : Integer);
Var I : Integer;
X, S : Real;
Begin
S := 0;
Writeln ('Entre com os dados');
For I := 1 To N Do
Begin
Readln (X);
If X = -1
Then Break;
S := S + X;
End;
Writeln ('SOMA = ', S:7:2);
End;
Begin
LerDados (10);
End.
A seguinte figura ilustra uma saída real:
Entre com os dados
10
20
30
40
10.5
20.5
30.5
-1
SOMA = 161.50
viii.
Elaborar um programa semelhante ao anterior, porém fornecendo ao final a soma e a
média aritmética dos valores fornecidos.
O cálculo da média é feito dividindo a soma dos dados pela quantidade de dados
fornecidos. A primeira impressão poderia levar a uma solução utilizando o valor do ,
variável de controle do loop, acreditando que ela reterá a quantidade de termos. Porém
esta não é uma boa prática de programação, pois não há garantias para o uso da
variável de controle fora do
. Ao encerrar a repetição, esta variável não contém um
valor confiável. Assim, a solução demanda que dentro do loop resolvamos esta questão.
Segue a solução proposta:
Program ExLERDADOS;
Procedure LerDados (N : Integer);
Var I, T : Integer;
Introdução à Programação: Conceitos e Práticas.
Página 198
X, S, M : Real;
Begin
S := 0; T:= N;
Writeln ('Entre com os dados');
For I := 1 To N Do
Begin
Readln (X);
If X = -1 Then
Begin
T := I-1;
Break;
End;
S := S + X;
End;
M := S/T;
Writeln ('SOMA = ', S:7:2);
Writeln ('MEDIA = ', M:7:2);
End;
Begin
LerDados (10);
End.
Observe que antes de sair do
com o
, vem a instrução
armazena em
o número de termos dado por
. Se o término do
naturalmente, sem o
, a variável permanecerá com o valor inicial
que foram lidos dados. A seguinte figura ilustra uma saída real:
que
ocorrer
, indicando
Entre com os dados
10
20
30
10.5
20.5
30.5
-1
SOMA = 121.50
MEDIA =
20.25
ix.
Elaborar um programa semelhante ao anterior, porém fornecendo ao final a soma, a
média aritmética e o maior valor dentre os valores fornecidos.
Deve ser agregada ao programa anterior a lógica para obter o maior entre os números
fornecidos. A estratégia consiste em inicializar uma variável com um valor pequeno, e
dentro do loop atualizar esta variável toda vez que um valor fornecido ( ) for superior ao
atual maior. Segue a lógica proposta:
Program ExLERDADOS;
Introdução à Programação: Conceitos e Práticas.
Página 199
Procedure LerDados (N : Integer);
Var I, T : Integer;
Maior, X, S, M : Real;
Begin
S := 0; T:= N;
Writeln ('Entre com os dados');
Maior := 0;
For I := 1 To N Do
Begin
Readln (X);
If X = -1 Then
Begin
T := I-1;
Break;
End;
If X > Maior
Then Maior := X;
S := S + X;
End;
M := S/T;
Writeln ('SOMA = ', S:7:2);
Writeln ('MEDIA = ', M:7:2);
Writeln ('MAIOR = ', Maior:7:2);
End;
Begin
LerDados (10);
End.
No código acima foram destacadas as linhas que tratam a lógica do maior:

Inicializa a variável que conterá o maior valor:
Maior := 0;

Para cada valor fornecido, verificar se o mesmo é maior que o maior atual, e em
caso positivo faça a substituição:
If X > Maior
Then Maior := X;
Introdução à Programação: Conceitos e Práticas.
Página 200
A seguinte figura ilustra uma saída real:
Entre
20
30
10
30.5
20.5
10.5
-1
SOMA
MEDIA
MAIOR
com os dados
=
=
=
121.50
20.25
30.50
Esta lógica tem um problema quando os valores fornecidos forem todos negativos.
Neste cenário, o programa informará que o maior número é zero. Uma melhoria na
estratégia seria inicializar a variável
com o primeiro número informado, pois assim
fica assegurada a consistência da lógica.
Program ExLERDADOS;
Procedure LerDados (N : Integer);
Var I, T : Integer;
Maior, X, S, M : Real;
Begin
S := 0; T := N;
Writeln ('Entre com os dados');
Readln (X);
Maior := X;
For I := 1 To N Do
Begin
If X = -1 Then
Begin
T := I-1;
Break;
End;
If X > Maior
Then Maior := X;
S := S + X;
If I < N
Then Readln (X);
End;
M := S/T;
Writeln ('SOMA = ', S:7:2);
Writeln ('MEDIA = ', M:7:2);
Writeln ('MAIOR = ', Maior:7:2);
End;
Introdução à Programação: Conceitos e Práticas.
Página 201
Begin
LerDados (10);
End.
A alteração introduzida para melhorar a lógica do
consiste em efetuar uma leitura de
dados antes de iniciar a repetição, e deslocar a leitura interna à repetição para o final do
.
Com isto fica resolvido o problema da inicialização da variável
. Foi adicionado um teste
para evitar a
leitura, já que uma leitura válida foi
realizada antes de iniciar a repetição.
21.4. Repetição – WHILE⋯DO
A estrutura de controle do tipo repetição controlada por expressão lógica é essencial
em uma linguagem de programação do paradigma imperativo ou procedural, da qual
e
fazem parte. O objetivo desta construção de controle é prover um
mecanismo onde uma ou mais instruções são executadas zero ou mais vezes
dependendo do valor de uma expressão lógica. O ciclo é repetido enquanto o valor da
expressão lógica for
.
21.4.1.
Sintaxe e Semântica
A sintaxe da instrução de repetição tipo
Onde
é:
é a condição que determina o controle da repetição.
A seguinte figura ilustra os componentes da instrução
, bem como destaca que a
dinâmica da estrutura inclui vários ciclos de execução da instrução controlada, onde o
fim da repetição ocorre quanto a expressão lógica assume o valor
.
O seguinte diagrama lógico permite visualizar o fluxo do processamento:
Introdução à Programação: Conceitos e Práticas.
Página 202
O valor da expressão lógica do
é testado. Caso seja
o fluxo do
processamento segue para as instruções controladas, retornando ao final para um novo
teste do valor da expressão lógica. O loop é encerrado quando o valor da expressão
lógica for
.
Introdução à Programação: Conceitos e Práticas.
Página 203
21.4.2.
i.
Exemplos
Refazer a lógica da leitura dos dados e cálculo da soma, da média aritmética e do maior
valor dentre os valores fornecidos, porém utilizando a repetição controlada por
expressão lógica. A única forma de encerrar a entrada de dados é através do dado
.
A utilização da instrução
irá simplificar a última implementação feita com o
,
pois deverá dispensar o
. A permanência no loop será definida pela condição
. Segue a lógica proposta:
Program ExLERDADOS;
Procedure LerDados;
Var T : Integer;
Maior, X, S, M : Real;
Begin
S := 0;
T := 0;
Writeln ('Entre com os dados');
Readln (X);
Maior := X;
While X <> -1 Do
Begin
Inc (T);
If X > Maior
Then Maior := X;
S := S + X;
Readln (X);
End;
M := S/T;
Writeln ('SOMA = ', S:7:2);
Writeln ('MEDIA = ', M:7:2);
Writeln ('MAIOR = ', Maior:7:2);
End;
Begin
LerDados;
End.
A procedure
foi alterada, pois o parâmetro que indica a quantidade de dados a
serem lidos não é mais necessária. O final da repetição se dá unicamente pela entrada
do valor
. A lógica tem as seguintes características:


São inicializadas as variáveis e . Não há mais contador, assim a variável
armazenará a quantidade de dados válidos digitados. É útil para o cálculo da
média;
É feita uma leitura antes da repetição, que servirá de inicialização para a variável
;
Introdução à Programação: Conceitos e Práticas.
Página 204


ii.
Dentro do
a variável é incrementada de a cada entrada válida.
A saída de dados na tela é semelhante aos programas anteriores.
Elaborar um programa que converta um número inteiro decimal em uma
contendo o equivalente
.
A seguinte figura ilustra o processo de conversão da base decimal para a binária. São
feitas divisões sucessivas do número que se deseja converter pela base destino. Os
restos destas divisões fornecem os dígitos binários, e o processo se encerra quando o
quociente alcançar zero:
Figura 66: Conversão Decimal - Binário
Segue a lógica proposta:
Program ExBASE;
Function DecToBin (X : Integer) : String;
Var S : String;
Begin
S := '';
While X <> 0 Do
Begin
If X Mod 2 = 0
Then S := '0' + S
Else S := '1' + S;
X := X Div 2;
End;
DecToBin := S;
End;
Begin
Writeln (DecToBin(15));
Writeln (DecToBin(67));
Introdução à Programação: Conceitos e Práticas.
Página 205
Writeln (DecToBin(1030));
Writeln (DecToBin(255));
End.
A função
codifica a lógica de conversão. A
que conterá o binário
convertido é inicializado com vazio (
)17. A repetição se encerra quando for igual
a zero, e este é atualizado ao final do
com o novo quociente. Antes, porém, o
resto da divisão de por é utilizado para decidir se deve ser adicionado o caractere
ou
a esquerda de a fim de montar o resultado corretamente.
A saída para o programa é:
1111
1000011
10000000110
11111111
iii.
Elaborar um programa que converta um número inteiro decimal em uma
contendo o equivalente
.
A lógica é semelhante ao do problema anterior bastando substituir o divisor pela base
desejada. Segue a lógica proposta:
Program ExBASE;
Function DecToHexDig (X : Integer) : Char;
Begin
Case X Of
0..9
: DecToHexDig := Chr(Ord('0') + X);
10..15 : DecToHexDig := Chr(Ord('A') + X - 10);
Else
DecToHexDig := 'X';
End;
End;
Function DecToHex (X : Integer) : String;
Var S : String;
Begin
S := '';
While X <> 0 Do
Begin
S := DecToHexDig (X Mod 16) + S;
X := X Div 16;
End;
DecToHex := S;
17
Observar que são dois caracteres ' (apóstrofe) seguidos sem espaço intermediário.
Introdução à Programação: Conceitos e Práticas.
Página 206
End;
Begin
Writeln
Writeln
Writeln
Writeln
End.
(DecToHex(15));
(DecToHex(67));
(DecToHex(1030));
(DecToHex(255));
A principal modificação em relação à conversão para binário, é no trecho que obtém o
caractere da base desejada. Na conversão para base , resolveu-se o problema com um
simples
, em função do binário ter dois símbolos. A conversão para hexadecimal
utiliza a função já codificada anteriormente
que fornece um digito
hexadecimal a partir do valor decimal de a .
A saída para o programa é:
F
43
406
FF
iv.
Elaborar um programa que complete uma string com brancos a esquerda a fim de
ajustar o tamanho do texto para uma quantidade estabelecida de caracteres. Faça o
mesmo para complemento a direita.
Segue a lógica proposta:
Program ExPAD;
Function PadLeft (S : String; N : Integer) : String;
Begin
While Length(S) < N Do
S := ' ' + S;
PadLeft := S;
End;
Function PadRight (S : String; N : Integer) : String;
Begin
While Length(S) < N Do
S := S + ' ';
PadRight := S;
End;
Begin
Writeln ('[', PadLeft ('Ola Mundo', 30),']');
Writeln ('[', PadRight ('Ola Mundo', 30),']');
Introdução à Programação: Conceitos e Práticas.
Página 207
End.
A lógica principal para a função
consiste em concatenar o caractere espaço em
branco a esquerda da
até que ela fique com o comprimento definido. A função
recebe a
inicial e o comprimento desejado. A repetição é encerrada
quando o comprimento do novo
alcançar , e em cada ciclo o comprimento de
é incrementado pela concatenação de um caractere a esquerda. A mesma lógica é
utilizada para a função
. O programa principal imprime a
envolvida com
os símbolos [ e ] para melhor visualização dos efeitos das funções.
A saída para o programa é:
[
[Ola Mundo
v.
Ola Mundo]
]
Elaborar um programa que calcule a raiz quadrada ( √ ) de um número pelo método de
.
O método de
calcula a raiz quadrada de um através de um método
iterativo (repetitivo) onde cada ciclo calcula um novo valor a partir do valor do ciclo
anterior, convergindo em direção ao resultado desejado. A fórmula de recorrência é
dada por:
(
)
A repetição deve ser encerrada quando a diferença entre o valor atual e o anterior for
inferior a um determinado
. Normalmente o erro estabelecido é o menor número
possível de ser representado na arquitetura em que o programa está rodando. Este erro
pode ser obtido por uma função que executa divisões sucessivas a partir de
até
alcançar o
, sendo que o valor anterior ao
é o menor número representável
naquela arquitetura. A solução proposta é dada por:
Program ExSQRT;
Function GetEPS : Extended;
Var EPS, X : Extended;
Begin
X := 1;
While X <> 0 Do
Begin
EPS := X;
X := X/2;
End;
GetEPS := EPS;
Introdução à Programação: Conceitos e Práticas.
Página 208
End;
Function Raizq (X : Extended) : Extended;
Var EPS, R, Rant : Extended;
begin
If X >= 0 Then
Begin
RAnt := 0; R := 1;
EPS := GetEPS;
While ABS (R - RAnt) >= EPS Do
Begin
RAnt := R;
R := (Rant + X / Rant) / 2;
End;
End Else R := 0;
Raizq := R;
End;
Eegin
Writeln (Raizq(2));
Writeln (Sqrt (2));
End.
Na função
, antes de caminhar para o cálculo da raiz, o valor de é testado para
evitar o processamento de número negativo. A lógica principal da função é semelhante a
fórmula apresentada:

Os valores das variáveis que representam o valor da raiz no ciclo atual ( ) e o
valor do ciclo anterior (
) são inicializados com valores distintos para que o
erro (
) seja diferente de
.
RAnt := 0; R := 1;

A variável que estabelece qual a precisão requerida para o cálculo é inicializada
com o
) da máquina, que é o menor número real antes de chegar ao
zero.
EPS := GetEPS;

O
principal determina que seja calculada uma nova raiz a cada ciclo
a diferença entre o valor do ciclo atual e o do ciclo anterior seja
superior à precisão estabelecida. A
é muito semelhante
à expressão codificada.
While ABS (R - RAnt) >= EPS Do
Begin
RAnt := R;
Introdução à Programação: Conceitos e Práticas.
Página 209
(
R := (Rant + X / Rant) / 2;
)
End;
A saída para o programa é:
1.4142135623730950E+0000
1.4142135623730950E+0000
Os valores calculados pela função implementada e pela função interna do
idênticos.
vi.
Elaborar um programa que calcule a raiz
.
são
( √ ) de um número pelo método de
O método de
calcula a raiz
de um
através de um método
iterativo (repetitivo), similar ao método da raiz quadrada. A fórmula de recorrência é
dada por:
(
)
Segue a solução proposta:
Program ExRAIZN;
Function GetEPS : Extended;
Var EPS, X : Extended;
Begin
X := 1;
While X <> 0 Do
Begin
EPS := X;
X := X/2;
End;
GetEPS := EPS;
End;
Function PowerInt (X : Extended; T : Integer) : Extended;
Var P : Extended; I : Integer;
Begin
P := 1;
For I := 1 To T Do
P := P*X;
PowerInt := P;
End;
Introdução à Programação: Conceitos e Práticas.
Página 210
Function RaizN (X : Extended; N : Integer) : Extended;
var EPS, R, Rant : Extended;
begin
If X >= 0 Then
Begin
RAnt := 0; R := 1;
EPS := GetEPS;
while ABS (R - RAnt) >= EPS do
begin
RAnt := R;
R := ((N-1)*Rant + X / PowerInt(Rant, N-1)) / N;
End;
End Else R := 0;
RaizN := R;
end;
Var Y : Extended;
begin
Y := RaizN (25, 3);
Writeln (Y);
Writeln (PowerInt(Y, 3));
end.
A
utiliza um cálculo do tipo
na parte
. Como o
expoente é um número inteiro positivo, preferiu-se implementar uma versão da função
exclusivamente para este caso (
), evitando o uso das funções
e .
A saída para o programa é:
2.9240177382128661E+0000
2.5000000000000000E+0001
No programa principal, o teste foi feito calculando os valores de
e de
√
valores apresentados indicam que o cálculo foi realizado com boa precisão.
. Os
A função
pode ser implementada de outra forma, tal como a que segue,
(I)
baseada no exemplo do
, publicado pelo prof. Niklaus Wirth.
Function PowerInt (X : Extended; T : Integer) : Extended;
Var W, Z : Extended; I : Integer;
Begin
W := X;
Z := 1;
i := T;
While I <> 0 Do
Introdução à Programação: Conceitos e Práticas.
Página 211
Begin
If Odd (i)
Then Z := Z*W;
I := I Div 2;
W := W*W;
End;
PowerInt := Z;
End;
vii.
Refazer o programa que calcula o seno de um ângulo a fim de que não tenha diferença
com a função interna do
:
Para zerar o erro em relação a função interna do
, faremos uma transformação no
cálculo do seno. A série será mais rapidamente convergente nos casos que
,
e de preferência com o ângulo mais perto de zero. Assim, faremos algumas
transformações para reduzir o ângulo a um menor valor equivalente. Segue a
transformação proposta:
( )
( )√
A equação indica que se calcularmos o
expressão, ou seja:
(
)
( )(
)
( )(
)
podemos chegar ao
(√
pela última
)
Onde:
( )
Segue a solução proposta, cujos detalhes ficam a cargo do leitor analisar:
Program ExSENO;
Function Reduzir (X : Extended) : Extended;
Begin
Reduzir := Frac(X/(2*PI))*(2*PI);
End;
Function GrausToRad (G : Extended) : Extended;
Introdução à Programação: Conceitos e Práticas.
Página 212
Begin
GrausToRad := G*PI/180;
End;
Function MySinx (X : Extended) : Extended;
Var P, S, SAnt : Extended;
I : Integer;
Begin
S := 0;
SAnt := X;
P := X;
I := 2;
While S <> SAnt Do
Begin
SAnt := S;
S := S + P;
P := -P*X*X/(I*(I+1));
I := I + 2;
End;
MySinx := S;
End;
Function MySin (X : Extended) : Extended;
Var S : Extended;
Begin
X := Reduzir(X)/4;
S := MySinx(X);
S := 4*S*Sqrt(1-S*S)*(1-2*S*S);
MySin := S;
End;
Var Graus, Rad, Y1 : Extended; Y2 : Extended;
I : Integer;
Begin
For I := 0 To 24 Do
Begin
Graus := I*15;
Rad := GrausToRad (Graus);
Y1 := Sin
(Rad);
Y2 := MySin (Rad);
Writeln (I:4, ' ', Graus:4:0, Y1:21:20, Y2:21:20, Y1-Y2:21:20);
End;
End.
A função que calcula o seno de um ângulo implementa uma lógica indireta, onde
primeiro o ângulo é reduzido ao primeiro quadrante (
). Na sequência
o seno desejado é obtido levando este valor de para a expressão que relaciona
e
, conforme indica o código abaixo:
Introdução à Programação: Conceitos e Práticas.
Página 213
A lógica do módulo principal, que calcula o valor da série, foi alterada para utilizar o
, sendo o critério de parada a situação em que dois cálculos sucessivos não
acrescentam precisão alguma ao resultado.
Observar na saída obtida que o erro foi zerado.
I
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
viii.
X
0
15
30
45
60
75
90
105
120
135
150
165
180
195
210
225
240
255
270
285
300
315
330
345
360
SIN(X)
0.00000000000000000
0.25881904510252076
0.50000000000000000
0.70710678118654752
0.86602540378443865
0.96592582628906829
1.00000000000000000
0.96592582628906829
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
-0.00000000000000000
-0.25881904510252076
-0.50000000000000000
-0.70710678118654752
-0.86602540378443865
-0.96592582628906829
-1.00000000000000000
-0.96592582628906829
-0.86602540378443865
-0.70710678118654752
-0.50000000000000000
-0.25881904510252076
0.00000000000000000
MYSIN(X)
0.00000000000000000
0.25881904510252076
0.50000000000000000
0.70710678118654752
0.86602540378443865
0.96592582628906829
1.00000000000000000
0.96592582628906829
0.86602540378443865
0.70710678118654752
0.50000000000000000
0.25881904510252076
0.00000000000000000
-0.25881904510252076
-0.50000000000000000
-0.70710678118654752
-0.86602540378443865
-0.96592582628906829
-1.00000000000000000
-0.96592582628906829
-0.86602540378443865
-0.70710678118654753
-0.50000000000000000
-0.25881904510252076
0.00000000000000000
ERRO
0.00000000000000000
0.00000000000000000
-0.00000000000000000
0.00000000000000000
-0.00000000000000000
-0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
-0.00000000000000000
0.00000000000000000
-0.00000000000000000
-0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
0.00000000000000000
0.00000000000000000
0.00000000000000000
-0.00000000000000000
0.00000000000000000
Elaborar um programa que formate uma
. O filtro para a formatação é a
eliminação dos caracteres espaço em branco duplicados em sequência. Qualquer
sequência de mais de um espaço em branco deverá ser substituída por apenas um
caractere.
A solução proposta utiliza a função
para localizar a primeira ocorrência de dois
espaços em branco. Uma vez encontrada é devolvida uma string com apenas um destes
dois caracteres. O processo deve se repetir até não haver mais espaços em branco em
sequência. Segue o código proposto:
Program ExBRANCO;
Function Erase (S : String; Ini, N : Integer) : String;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 214
Erase := Copy (S, 1, Ini-1) + Copy (S, Ini+N, 255);
End;
Function Repete (Ch : Char; N : Integer) : String;
Var S : String;
Begin
S := '';
While N > 0 Do
Begin
S := S + Ch;
Dec (N);
End;
Repete := S;
End;
Function DelSpace (S : String) : String;
Var P : Integer;
Begin
P := Pos (' ', S);
While P <> 0 Do
Begin
S := Erase (S, P, 1);
P := Pos (' ', S);
End;
DelSpace := S;
End;
Var S, Sx : String;
Begin
S := 'OLA
MUNDO
BELO ';
Sx := Repete ('X', Length(S));
Writeln ('[', Sx,']');
Writeln ('[', S, ']');
Writeln ('[', DelSpace (S),']');
End.
A saída para o programa é:
[XXXXXXXXXXXXXXXXXXXXX]
[OLA
MUNDO
BELO ]
[OLA MUNDO BELO ]
Nesta saída, o primeiro texto impresso é uma série de caracteres repetidos apenas para
dar uma referência para a contagem de caracteres nas linhas que seguem. A
com caracteres repetidos foi gerada a partir da função
.
Introdução à Programação: Conceitos e Práticas.
Página 215
A lógica da função
inicializada com vazio
, perfazendo ao final uma
utiliza uma estrutura com
. Uma
é
e em cada repetição é concatenado em S um caractere
com caracteres iguais a
.
A função
faz a filtragem da
, onde a lógica é localizar uma sequência
de dois caracteres branco
e atualizar para que receba a mesma
porém eliminado um dos caracteres. A função
, ilustrada abaixo, codifica a
lógica que dada uma
, uma posição
e uma quantidade , é gerada uma
sem os
caracteres a partir da posição
. A lógica utilizada concatena os textos a
esquerda e a direita de um dos espaços em branco.
Ini
S
x x .. x
1 2 3 ..
z
z ... z
z
z
N
Copy (S, 1, Ini-1)
Erase
Copy (S, Ini+N, 255)
x x .. x
z
z ... z
z
z
21.5. Repetição – REPEAT⋯UNTIL
O objetivo da construção de controle do tipo
é prover um mecanismo
onde uma ou mais instruções são executadas uma ou mais vezes dependendo do valor
de uma expressão lógica. O ciclo é repetido até que o valor da expressão lógica seja
.
21.5.1.
Sintaxe e Semântica
A sintaxe da instrução de repetição tipo
Onde
é:
é a condição que determina o controle da repetição.
A seguinte figura ilustra os componentes da instrução
, bem como destaca que
a dinâmica da estrutura inclui vários ciclos de execução da instrução controlada, onde o
fim da repetição ocorre quanto a expressão lógica assume o valor
.
Introdução à Programação: Conceitos e Práticas.
Página 216
As instruções controladas são executas uma vez. Em seguida o valor da expressão
lógica do
é testado. Caso seja
o fluxo do processamento é desviado
para o início das instruções controladas. O loop é encerrado quando o valor da
expressão lógica for
.
21.5.2.
i.
Exemplos
Refazer a lógica da leitura dos dados e cálculo da soma e a média, sendo que o usuário
digitará o texto
para indicar que deseja finalizar a entrada de dados.
Neste exemplo, a entrada de dados não pode ser armazenada em uma variável
numérica, pois o usuário digitará o texto
para informar que não deseja prosseguir
com a entrada de dados. Assim, a linha a ser digitada pelo usuário deverá ser
armazenada em uma variável do tipo
. Desta forma, o programa aceitará qualquer
texto como entrada sem provocar erro de execução. Porém, para efetuar o acúmulo dos
valores fornecidos, será necessário converter o texto de entrada para uma variável
numérica. O acúmulo deste valor só é feito após certificar que o conteúdo do texto
fornecido é compatível com um dado numérico. Segue a lógica proposta:
Program ExRUNTIL;
Function IsNumber (L : String) : Boolean;
Var X : Real; Code : Integer;
Begin
Val (L, X, Code);
IsNumber := Code = 0;
End;
Introdução à Programação: Conceitos e Práticas.
Página 217
Function Str2Real (L : String) : Real;
Var X : Real; Code : Integer;
Begin
Val (L, X, Code);
Str2Real := X;
End;
Procedure LerDados;
Var T : Integer;
M, S : Real;
Linha : String;
Begin
S := 0;
T := 0;
Writeln ('Entre com os dados e digite ''fim'' para encerrar');
Repeat
Readln (Linha);
If IsNumber (Linha) Then
Begin
S := S + Str2Real (Linha);
Inc (T);
End;
Until Linha = 'fim';
If T <> 0 Then
Begin
M := S/T;
Writeln ('SOMA = ', S:7:2);
Writeln ('MEDIA = ', M:7:2);
End Else
Writeln ('Não há dados disponíveis');
End;
Begin
LerDados;
End.
As funções
e
auxiliam na construção da lógica principal. A função
testa se o conteúdo de uma
satisfaz as regras de formação de um
número real. A função
recebe uma string como entrada e retorna como
resultado o equivalente numérico. Assim, a lógica principal se apresenta de forma
bastante legível e de fácil compreensão.
Introdução à Programação: Conceitos e Práticas.
Página 218
Uma saída exemplo para o programa é:
Entre com os dados e digite 'fim' para encerrar
10.5
20.5
10.5
fim
SOMA =
41.50
MEDIA =
13.83
ii.
Escrever um programa que faz a leitura de várias linhas que representam uma redação
qualquer, e informa a quantidade de vogais contidas em todo o texto. O usuário digitará
para indicar que deseja finalizar a entrada de dados. Segue a lógica proposta:
Program ExREDACAO;
Function IsVogal (Ch : Char) : Boolean;
Begin
Case UpCase(Ch) Of
'A', 'E', 'I', 'O', 'U' : IsVogal := True;
Else
IsVogal := False;
End;
End;
Function ContaVogal (L : String) : Integer;
Var I, C : Integer;
Begin
C := 0;
For I := 1 To Length (L) Do
C := C + Ord (IsVogal(L[I]));
ContaVogal := C;
End;
Procedure LerDados;
Var
V : Integer; Linha : String;
Begin
V := 0;
Writeln ('Entre com os textos e digite ''fim'' para encerrar');
Repeat
Readln (Linha);
If Linha <> 'fim'Then
V := V + ContaVogal (Linha);
Until Linha = 'fim';
Writeln ('VOGAIS = ', V);
End;
Introdução à Programação: Conceitos e Práticas.
Página 219
Begin
LerDados;
End.
As funções
e
auxiliam na construção da lógica principal. A função
testa se um
é um dos caracteres ASCII que representam vogais. A função
recebe uma string como entrada e retorna como resultado a quantidade de
caracteres que são vogais.
A função
é implementada incluindo uma lógica de contagem. A variável de
contagem é inicializada com zero
. A estrutura principal é uma repetição por
uma quantidade de vezes que é dada pelo número de caracteres da
fornecida
. A instrução repetida se resume em incrementar a variável
de contagem de ou . O valor ou é obtido convertendo o resultado
do
teste de cada caractere da string
[]
para número utilizando a função
. Assim, a lógica principal se apresenta de forma bastante legível e de fácil
compreensão.
Uma saída exemplo para o programa é:
Entre com os textos e digite 'fim' para encerrar
OLA mundo
BELO
fim
VOGAIS = 6
Introdução à Programação: Conceitos e Práticas.
Página 220
22.
Array
Os tipos de dados vistos até o momento são de natureza escalar, ou seja, permitem
definir variáveis com capacidade para representar apenas um elemento. Uma variável
do tipo
tem capacidade para armazenar apenas um número em determinado
instante. O conteúdo pode ser alterado, porém sempre será apenas um elemento. O
mesmo acontece com os demais tipos escalares:
,
,
e
. O tipo
antecipou o conceito de
, e é um tipo de dado que permite representar um
agregado de elementos escalares, no caso uma sequência de
.
Uma série de problemas práticos conduz a situações onde é fundamental manter
simultaneamente na memória uma coleção de elementos de uma determinada
natureza. Alguns exemplos seriam: nomes de alunos de uma turma, disciplinas de um
curso, notas de uma turma de uma disciplina em um bimestre, notas de uma turma de
uma disciplina em todos os bimestres, relação de professores de um curso,
temperaturas diárias em um ano, cotação da bolsa em cinco anos, vendas diárias de
uma loja, vendas diárias de todas as filiais, medições de grandezas, salários de
empregados de uma empresa, e etc.
Os exemplos citados poderiam ser submetidos a lógicas para obter: média de cada
aluno em uma disciplina ordenados de várias formas, livro de chamada, relação de
professores por curso, disciplina que mais reprova, regressão linear de grandezas
medidas, semana com a menor temperatura média, folha de pagamento, e etc.
Assim, é importante que uma linguagem de programação permita modelar e processar
entidades que representam uma coleção de dados. Em contraste ao tipo escalar, o tipo
de dado voltado para representar simultaneamente vários elementos é denominado tipo
vetorial.
A linguagem Pascal disponibiliza o tipo
para definir variáveis capazes de
armazenar uma coleção de elementos. Com este tipo de dado é possível modelar
problemas que precisam dos conceitos de
e
.
Introdução à Programação: Conceitos e Práticas.
Página 221
22.1. Vetor
Um vetor é uma estrutura composta por uma quantidade conhecida de elementos,
sendo todos do mesmo tipo. O vetor também é chamado de agregado homogêneo. A
seguinte figura compara uma variável
com uma variável do
:
X:
V:
Tabela 2: Comparação Escalar x Vetor
A variável é do tipo escalar (p. ex.
) e a variável
é do tipo vetor ou
.
Apenas uma célula de memória está disponível para uso através de , enquanto que
através de
várias células estão disponíveis para o programa. A variável
foi
declarada como
, e declarada como
A linguagem
é essencialmente escalar, sendo que as expressões refletem esta
característica e operam somente sobre dados escalares18. Assim, as células de um
vetor devem ser refenciadas individualmente, o que demanda que a variável
seja
complementada com uma informação que identifique especificamente uma célula. Este
complemento é o
, que indica a sua posição no vetor. Por exemplo, a
primeira célula poderia ser [ ], a segunda [ ] e assim sucessivamente. Agora temos
a definição completa do endereço de memória referente a uma célula vinculada ao
vetor. Esta célula individualizada preenche todos requisitos de uma variável escalar, e
também é denominada
.
18
O tipo string não é um tipo primitivo do Pascal. Os dialetos Pascal incluem facilidades para manipular strings, que
no detalhe é um array de char.
Introdução à Programação: Conceitos e Práticas.
Página 222
22.2. Sintaxe e Semântica
O vetor é um
com apenas uma dimensão, também denominado unidimensional.
A sintaxe simplificada para a definição do tipo vetor é:
[
]
A natureza do
é necessariamente ordinal, ou seja, o índice de
19
20
um
deve ser do tipo
,
,
ou
. Variáveis podem
ser criadas a partir desta definição.
O seguinte exemplo ilustra as várias possibilidades de declaração de uma variável do
tipo
. À direita são apresentadas algumas atribuições às células de cada
,
permitindo também compreender o processo de indexação.
Declaração das variáveis
Var
Va
Vb
Vc
Vx
Vt
Vq
Vr
Vs
Vn
:
:
:
:
:
:
:
:
:
Array[1..100]
Array[0..499]
Array[-10..10]
Array[1..1000]
Array[0..10000]
Array['a'..'z']
Array['0'..'9']
Array[False..True]
Array[Boolean]
Of
Of
Of
Of
Of
Of
Of
Of
Of
Integer;
LongInt;
Word;
Real;
Char;
Real;
Real;
Integer;
Integer;
Programa Principal
Begin
Va[3]
Vb[35]
Vc[-5]
Vx[300]
Vt[0]
Vq['d']
Vr['4']
Vs[False]
Vn[True]
End.
:=
:=
:=
:=
:=
:=
:=
:=
:=
-1;
80;
$ffff;
1.28;
'x';
3.26;
-1.32e10;
-43;
43;
A seguinte tabela ilustra a quantidade de memória que cada vetor ocupa, bem como
destaca o número de elementos e o tamanho de cada elemento que compõe o
.
Declaração
Va
Vb
Vc
Vx
Vt
Vq
19
20
:
:
:
:
:
:
Array[1..100]
Array[0..499]
Array[-10..10]
Array[1..1000]
Array[0..10000]
Array['a'..'z']
#bytes
do
#elementos
Elemento
Of Integer;
2
100
Of LongInt;
4
500
Of Word;
2
21
Of Real;
8
1000
Of Char;
1
10001
Of Real;
8
26
#bytes do
array
200
2000
42
8000
10001
208
Inclui as variações dos inteiros.
O tipo enumerado será apresentado mais adiante.
Introdução à Programação: Conceitos e Práticas.
Página 223
Vr : Array['0'..'9']
Of Real;
Vs : Array[False..True] Of Integer;
Vn : Array[Boolean]
Of Integer;
8
2
2
10
2
2
80
4
4
A forma utilizada para especificar o tamanho de um
é estabelecendo uma faixa
para o índice. O primeiro elemento da faixa é o índice da primeira célula, e o último
elemento da faixa é o índice para a última célula. As células serão de tamanho
suficiente para acomodar um elemento do tipo base.
Nos exemplos acima, temos que o
foi definido com
elementos do
tipo
, sendo que a primeira célula é índice e a última é índice
.O
foi definido com
elementos do tipo
, sendo que o primeiro é índice
e o último é índice . O índice do
é do tipo
, sendo que a primeira
célula é identificada pelo
e a última pelo
, perfazendo ao todo
elementos. Os índices do tipo
devem ser interpretados como similares a
índices inteiros equivalentes a posição do caractere na tabela
. A seguinte figura
ilustra estes conceitos para a variável
:
O índice de um
deve ser uma expressão compatível com o tipo utilizado na
definição da dimensão. Seguem alguns exemplos de índices com expressões cujo
resultado é de tipo compatível com a definição do índice.
Var
Va :
Vq :
Vs :
Vt :
I :
Begin
Array[1..100]
Array['a'..'z']
Array[False..True]
Array[0..10000]
Integer;
Of
Of
Of
Of
Integer;
Real;
Integer;
Char;
Introdução à Programação: Conceitos e Práticas.
Página 224
Va[I-1]
:= -125;
Vq[Chr(Ord('a') + I Mod 27)] := -2.16e-32;
Vs[I Mod 2 = 0]
:= 27;
Vt[3*Va[I]+120]
:= Chr (Vs[False] mod 45);
End.
A figura a seguir faz a conexão entre a definição da variável do tipo
e a linha de
código com o comando de atribuição. Observe que no caso da variável
, o índice é
definido como
e na expressão de atribuição o acesso a célula é feito
com uma expressão
[
] Ainda em
, o tipo de cada elemento é definido
como
e o valor atribuído também é
. O mesmo ocorre com a variável
, onde o índice é definido como
e na expressão de atribuição o acesso
a célula é feito com uma expressão do tipo
[
] para o
índice. Ainda em , o tipo de cada elemento é definido como real e o valor atribuído na
expressão também é
. A compatibilidade é mantida para
e .
Figura 67: Correspondência entre Definição do Vetor e a Atribuição.
O tipo
é de fato um vetor ou
de char, que em função da sua importância
em grande parte dos problemas, fez com que a maioria das versões de
trouxessem facilidades embutidas para processamento. A principal facilidade é a
atribuição, onde uma instrução do tipo
faz com que os caracteres
sejam armazenados em sequência a partir da célula [ ].
22.3. Exemplos
i.
Reescrever o programa que lê vários números fornecidos via teclado e apresente ao
final algumas estatísticas, tais como: somatória destes valores, média, maior valor, e etc.
A lógica deste problema será alterada em relação às várias versões já implementadas. A
parte de entrada de dados será separada da parte de processamento dos dados. Assim,
um módulo fará a leitura dos dados e os armazenará em um vetor e outros módulos
Introdução à Programação: Conceitos e Práticas.
Página 225
farão os cálculos que forem necessários. O programa principal fará a junção destes
módulos para atender ao requisito do problema. Segue a solução proposta:
Program ExLERVETOR;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
Var X : Real;
Begin
Writeln ('Entre com os dados');
N := 0;
Readln (X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (X);
End;
End;
Function SomaVet (V : TVReal; N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 1 To N Do
S := S + V[I];
SomaVet := S;
End;
Function MaiorVet (V : TVReal; N : Integer) : Real;
Var I : Integer;
M : Real;
Begin
M := V[1];
For I := 2 To N Do
If V[I] > M
Then M := V[I];
MaiorVet := M;
End;
Var Vx : TVReal;
Nx : Integer;
Soma, Media, Maior : Real;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 226
LerDados (Vx, Nx);
Soma := SomaVet (Vx, Nx);
Media := Soma/Nx;
Maior := MaiorVet (Vx, Nx);
Writeln ('SOMA = ', Soma :7:2);
Writeln ('MEDIA = ', Media:7:2);
Writeln ('MAIOR = ', Maior:7:2);
End.
O problema foi modularizado e deu origem a três rotinas: a procedure
e as
funções
e
. O programa principal organiza as chamadas a fim de
atender a especificação do problema. Observe que no programa principal, inicialmente é
invocada a procedure
, que interage com o usuário fazendo a aquisição de
dados e armazenando na memória. Em seguida, três linhas de código fazem os cálculos
da
,
e do
. Seguem os comentários de cada módulo:
A procedure
está definida através do seguinte cabeçalho:
Procedure LerDados (Var V : TVReal; Var N : Integer);
Esta definição informa que são necessários dois parâmetros passados pelo método por
referência. Isto indica que o trabalho feito pela rotina será devolvido ao programa
chamador através dos parâmetros e . É importante destacar que será prática comum
na manipulação de arrays que além da variável
com os elementos, também
acompanhará a variável que indica a quantidade de elementos efetivamente em uso.
Isto ocorre normalmente pelo fato da definição da variável array sempre reservar um
tamanho máximo fixo, e de fato as lógicas trabalham com qualquer quantidade de
elementos até este limite máximo. Esta quantidade deve ser indicada para as rotinas
que processarão o vetor.
Voltando à rotina
, temos que o primeiro parâmetro é do tipo
segundo é do tipo
. Caso não houvesse restrição por parte do
cabeçalho seria o seguinte:
e o
, o
Procedure LerDados (Var V : Array[1..100] Of Real; Var N : Integer);
Porém, o
requer que o tipo de um parâmetro seja expresso por apenas uma
palavra, e não por uma sentença. Assim, deve ser utilizado um recurso da linguagem,
que permite fazer associação de tipos. É possível criar um novo tipo a partir de outros já
existentes. Deste modo, o programador contorna esta situação utilizando a cláusula
, como em:
Type TVReal = Array[1..100] Of Real;
Com esta definição colocada no topo do programa, podemos então criar variáveis ou
parâmetros do tipo
. O uso de
também é aceito por vários
compiladores, porém será estimulada a prática de definição de um novo tipo.
Introdução à Programação: Conceitos e Práticas.
Página 227
Apresentado e esclarecido este conceito, então a especificação do módulo
é
efetuar a leitura de alguns números via teclado e armazená-los no parâmetro . Além
disso, a quantidade de dados lidos será armazenada no parâmetro . Assim, ao invocar
esta procedure, os argumentos deverão ser variáveis (
) e ao
retornar ao chamador, estes argumentos terão os mesmos conteúdos atribuídos aos
parâmetros.
A lógica interna de
consiste em:
Writeln ('Entre com os dados');
N := 0;
Readln (X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (X);
End;
Escrever mensagem na tela
Zerar o contador de elementos
Ler dado e armazenar em X
Loop enquanto valor digitado ≠ -1
Para um X válido
Incrementar o contador de elementos
Armazenar elemento X na célula V[N]
Ler dado e armazenar em X
Voltar para início do loop.
O seguinte diagrama lógico ilustra graficamente o fluxo do processamento:
Vamos supor que o programa está em execução e durante a sessão de execução o
usuário entrou com os seguintes números:
e
. Nestas condições
apresentamos na sequência o comportamento da memória nos vários ciclos da
repetição:
Introdução à Programação: Conceitos e Práticas.
Página 228
Primeiro Ciclo
N:
0/1
V:
V[1] := X
X:
25
inc(N)
25
?
?
?
?
V[1]
V[2]
V[3]
V[4]
V[5]
N:
X:
32
inc(N)
X <> -1
True
False
V[96]
V[97]
V[98]
V[99]
V[100]
?
?
?
?
?
fim
V[1]
V[2]
V[3]
V[4]
V[5]
V[96]
V[97]
V[98]
V[99]
V[100]
fim
Terceiro Ciclo
2/3
V:
V[3] := X
X:
25
32
?
?
?
False
?
?
?
?
?
N:
V:
...
True
1/2
V[2] := X
...
X <> -1
Segundo Ciclo
18.2
inc(N)
V[1]
V[2]
V[3]
V[4]
V[5]
N:
3
X:
-1
V:
X <> -1
True
False
25
32
18.2
?
?
V[1]
V[2]
V[3]
V[4]
V[5]
...
True
25
32
18.2
?
?
...
X <> -1
Término do Loop
False
?
?
?
?
?
V[96]
V[97]
V[98]
V[99]
V[100]
fim
?
?
?
?
?
V[96]
V[97]
V[98]
V[99]
V[100]
fim
a) Incialmente
é zero, o usuário fornece o número , a condição do loop é testada, o
processamento entra no bloco
, incrementa que passa a conter , armazena o
valor de
na célula [ ] e ainda no interior do
faz uma nova leitura de dado.
Introdução à Programação: Conceitos e Práticas.
Página 229
b) O usuário fornece o número , a condição do loop é testada, o processamento entra no
bloco
, incrementa que passa a conter , armazena o valor de
na célula
[ ] e ainda no interior do
faz uma nova leitura de dado.
c) O usuário fornece o número
, a condição do loop é testada, o processamento entra
no bloco
, incrementa
que passa a conter , armazena o valor de
na
célula [ ] e ainda no interior do loop faz uma nova leitura de dado.
d) O usuário fornece o número
repetição.
, a condição do loop é testada e indica o fim da
Após o final do loop a variável
conterá , indicando a quantidade de elementos
armazenados, e as três primeiras células do vetor conterão os dados fornecidos. O
fluxo de execução retorna para a unidade chamadora, que neste caso é o programa
principal, e avança para a próxima linha de código.
Begin
LerDados (Vx, Nx);
Soma := SomaVet (Vx, Nx);
Media := Soma/Nx;
Maior := MaiorVet (Vx, Nx);
Writeln ('SOMA = ', Soma :7:2);
Writeln ('MEDIA = ', Media:7:2);
Writeln ('MAIOR = ', Maior:7:2);
End.
Chamar LerDados com Vx e Nx
Obter a soma com SomaVet com Vx e Nx
Obter a média
Obter o maior com MaiorVet com Vx e Nx
Mostrar a soma
Mostrar a média
Mostrar o maior
A atribuição
inicia com a avaliação da expressão que
contém apenas a chamada a função SomaVet com os argumentos
e
.
A lógica interna de
consiste em:
Function SomaVet (V : TVReal;
N : Integer) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := 1 To N Do
S := S + V[I];
O primeiro parâmetro é um vetor e o segundo
parâmetro é um inteiro que indica a
quantidade de elementos do vetor.
Variáveis para o For e para acumular a soma.
SomaVet := S;
End;
Resultado da função em S
Zerar a soma
Repetir N vezes
Acumula em S o valor de V[I]
Encerrada a chamada de
o controle volta para a unidade chamadora que é o
programa principal, que completa o processamento da linha, atribuindo o resultado de
à variável
.
Introdução à Programação: Conceitos e Práticas.
Página 230
Na sequência é executada a linha
que avalia a expressão indicada,
calculando a divisão da soma pelo número de termo, e armazena o resultado em
.
A próxima linha é
os argumentos
e
consiste em:
que invoca a função
copiando
para os parâmetros desta função. A lógica interna de
Function MaiorVet (V : TVReal;
N : Integer) : Real;
Var I : Integer;
M : Real;
Begin
M := V[1];
For I := 2 To N Do
If V[I] > M
Then M := V[I];
MaiorVet := M;
End;
O primeiro parâmetro é um vetor e o segundo
parâmetro é um inteiro que indica a
quantidade de elementos do vetor.
Variáveis para o For e para armazenar o
maior
Iniciar Maior com o primeiro elemento de V
Repetir para I de 2 até N
Se o elemento V[I] > do que o maior atual
Então faça V[I] ser o maior
Resultado da função em maior
Encerrada a chamada de
o controle volta para a unidade chamadora que é o
programa principal, que completa o processamento da linha, atribuindo o resultado de
à variável
.
As próximas três linhas:
Writeln ('SOMA = ', Soma :7:2);
Writeln ('MEDIA = ', Media:7:2);
Writeln ('MAIOR = ', Maior:7:2);
escrevem na tela os conteúdos das três variáveis
,
e
. A seguinte
interface de entrada e saída ilustra a interação do programa com o usuário:
Entre
25
32
18.2
-1
SOMA
MEDIA
MAIOR
com os dados
=
=
=
Introdução à Programação: Conceitos e Práticas.
75.20
25.07
32.00
Página 231
ii.
Escrever um programa que calcule o valor de
e de um valor de :
a partir dos coeficientes do polinômio
⋯
A sugestão para este problema é estruturar a lógica nos módulos para:
a) Entrada de dados que obtém via teclado os valores de
de e os armazena na memória;
b) Cálculo do valor de
a partir de
c) Apresentar o vetor e os resultados na tela.
⋯
e
Segue a solução proposta:
Program ExPOLI;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
Var X : Real;
Begin
Writeln ('Entre com os dados');
N := 0;
Readln (X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (X);
End;
End;
Procedure MostrarVet (V : TVReal; N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
Writeln ('V[', I:2,'] = ', V[I]:8:3);
End;
Function Polinomio (V : TVReal; N : Integer; X : Real) : Real;
Var I : Integer;
S : Real;
Begin
S := 0;
For I := N DownTo 1 Do
S := S*X + V[I];
Polinomio := S;
Introdução à Programação: Conceitos e Práticas.
Página 232
End;
Var Vx
Nx
X, Y
: TVReal;
: Integer;
: Real;
Begin
LerDados (Vx, Nx);
Write ('Entre com X = '); Readln (X);
Y := Polinomio (Vx, Nx, X);
MostrarVet (Vx, Nx);
Writeln ('P(', X:5:2, ') = ', Y:7:2);
End.
A procedure
é a mesma do exercício anterior. A função que calcula o valor de
foi implementada utilizando a seguinte forma, denominada fatoração de
:
(
(
(
⋯ )))
A lógica é semelhante ao código aplicado para solucionar os exercícios sobre séries.
Compare as duas lógicas e identifique a pequena alteração feita.
A procedure
apresenta na tela os coeficientes do polinômio permitindo ao
usuário inspecionar se foram considerados os dados certos.
O programa principal ordena as chamadas na sequência lógica estabelecida para este
problema, e proporciona a seguinte interface:
Entre com os dados
1
2
3
-1
Entre com X = 3
V[ 1] =
1.000
V[ 2] =
2.000
V[ 3] =
3.000
P( 3.00) =
34.00
iii.
Escrever um programa que localiza a posição de um elemento em um vetor.
Problemas de busca são corriqueiros em grande parte dos problemas. Isto faz com que
se estude muito sobre métodos eficientes para este propósito. Neste exercício faremos
implementações básicas, ficando fora do escopo métodos mais elaborados. Segue uma
solução para a busca por um elemento em um vetor não ordenado:
Program ExBUSCA;
Introdução à Programação: Conceitos e Práticas.
Página 233
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
{igual aos exemplos anteriores}
End;
{
Function Buscar (V : TVReal; N : Integer; X : Real) : Integer;
Var P, I : Integer;
Begin
P := 0;
For I := 1 To N Do
If V[I] = X Then
Begin
P := I;
Break;
End;
Buscar := P;
End;
Function Buscar (V : TVReal; N : Integer; X : Real) : Integer;
Var I : Integer;
Begin
I := 1;
While (I <= N) And (V[I] <> X) Do
Inc(I);
If I > N
Then Buscar := 0
Else Buscar := I;
End;
}
Function Buscar (V : TVReal; N : Integer; X : Real) : Integer;
Var I : Integer;
Begin
Inc (N);
V[N] := X;
I := 1;
While (V[I] <> X) Do
Inc(I);
If I = N
Then Buscar := 0
Else Buscar := I;
End;
Introdução à Programação: Conceitos e Práticas.
Página 234
Var Vx
X
: TVReal;
: Real;
Nx
P
: Integer;
: Integer;
Begin
LerDados
(Vx, Nx);
X := 28;
P := Buscar (Vx, Nx, X);
Writeln ('Posicao de ',X:5:1,' = ', P);
End.
Foram incluídas três versões distintas de uma busca linear, onde os elementos do vetor
são percorridos a fim de encontrar a primeira ocorrência do elemento . Caso este
elemento não seja encontrado a função retorna zero. Duas das funções estão como
comentário.
A primeira versão utiliza a seguinte lógica:
P := 0;
For I := 1 To N Do
If V[I] = X Then
Begin
P := I;
Break;
End;
Inicialmente a posição é definida como zero, e parte-se para percorrer todo o vetor em
busca do elemento , que uma vez encontrado á posição é salva, e a repetição é
encerrada.
A segunda versão utiliza a seguinte lógica:
I := 1;
While (I <= N) And (V[I] <> X) Do
Inc(I);
If I > N
Then Buscar := 0
Else Buscar := I;
A estratégia é a mesma da implementação anterior, porém o
com o
é
substituído pelo
. A expressão lógica que controla a repetição indica que o loop
deve ser encerrado assim que encontrar um [ ]
ou quando já percorreu todo o
vetor sem nada encontrar
. Ao terminar o
, o valor de é testado para
saber se o seu valor não extrapolou o tamanho do vetor, que em caso positivo significa
elemento não encontrado.
A terceira versão utiliza a seguinte lógica:
Inc (N);
V[N] := X;
Introdução à Programação: Conceitos e Práticas.
Página 235
I := 1;
While (V[I] <> X) Do
Inc(I);
If I = N
Then Buscar := 0
Else Buscar := I;
Esta função visa simplificar a expressão que controla o
, fazendo com que fique
apenas um teste. Para que isto seja feito com segurança, observe que as duas primeiras
linhas cuidam de inserir o elemento no final do vetor, e incrementar o comprimento do
vetor em . Assim, há a certeza de que pelo menos um elemento exista no vetor. Caso
a busca indique que o elemento encontrado está na posição do novo , então significa
que no vetor original o
não foi encontrado. Destaca-se também que a instrução
controlada pelo
é simplemente o incremento de , cujo significado é
simplesmente avançar a busca para o próximo elemento.
Segue uma interface de entrada e saída para um caso exemplo:
Entre com os dados
18
32
28
17
-1
Posicao de 28.0 = 3
iv.
Escrever um programa que ordene um vetor de números em ordem decrescente:
Segue a proposta de uma lógica bem simples:
Program ExORDENA;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
Begin
{igual ao exemplo anterior}
End;
Procedure MostrarVet (V : TVReal; N : Integer);
Begin
{igual ao exemplo anterior}
End;
Procedure Trocar (Var A, B : Real);
var T : Real;
Introdução à Programação: Conceitos e Práticas.
Página 236
Begin
T := A;
A := B;
B := T;
End;
Function GetPosMaior (V : TVReal; Ini, N : Integer) : Integer;
Var P, I : Integer;
Begin
P := Ini;
For I := Ini+1 To N Do
If V[I] > V[P]
Then P := I;
GetPosMaior := P;
End;
Procedure MaiorFirst (Var V : TVReal; Ini, N : Integer);
Var P, I : Integer;
Begin
P := GetPosMaior (V, Ini, N);
Trocar (V[Ini], V[P]);
End;
Procedure Ordenar (Var V : TVReal; N : Integer);
Var I : Integer;
Begin
For I := 1 To N-1 Do
MaiorFirst (V, I, N);
End;
Var Vx
Nx
: TVReal;
: Integer;
Begin
LerDados (Vx, Nx);
Ordenar (Vx, Nx);
MostrarVet (Vx, Nx);
End.
O programa principal indica a sequência da lógica mais abstrata, que é:
1. Ler os dados do vetor para a memória;
2. executar a ordenação; e
3. apresentar o resultado na tela.
Os módulos
e
são os mesmos do exemplo anterior. A procedure
encaminha o vetor
e seu tamanho
para o processo de ordenação. A
procedure
recebe estes argumentos nos parâmetros
e . A passagem de
Introdução à Programação: Conceitos e Práticas.
Página 237
parâmetro do vetor é por referência, implicando que toda alteração no parâmetro
reflete no argumento .
Procedure Ordenar (Var V : TVReal; N : Integer);
Var I : Integer;
Begin
For I := 1 To N-1 Do
MaiorFirst (V, I, N);
End;
A lógica da procedure
1.
2.
3.
4.
5.
é:
Trazer o maior elemento entre
Trazer o maior elemento entre
Trazer o maior elemento entre
...
Trazer o maior elemento entre
e
e
e
para a posição ;
para a posição ;
para a posição ;
e
para a posição
.
Ao final desta sequência o vetor estará em ordem decrescente. A forma geral desta
sequência é:

Trazer o maior elemento entre e
para a posição , com
. Esta lógica foi transformada em:
variando de
a
For I := 1 To N-1 Do
MaiorFirst (V, I, N);
A rotina
posições
abaixo:
e
faz o trabalho de identificar a posição do maior elemento entre as
e trazê-lo para a posição
do vetor , como indicado no código
Procedure MaiorFirst (Var V : TVReal; Ini, N : Integer);
Var P, I : Integer;
Begin
P := GetPosMaior (V, Ini, N);
Trocar (V[Ini], V[P]);
End;
A abstração está novamente presente nesta rotina, pois trazer para a posição
do
vetor o maior elemento entre
e , foi codificado em duas linhas, sendo uma que
chama
que retorna a posição do maior elemento de entre as posições
e . A segunda linha executa o módulo que
os conteúdos das células
e .
A função
tem o seguinte código:
Function GetPosMaior (V : TVReal; Ini, N : Integer) : Integer;
Var P, I : Integer;
Begin
P := Ini;
Introdução à Programação: Conceitos e Práticas.
Página 238
For I := Ini+1 To N Do
If V[I] > V[P]
Then P := I;
GetPosMaior := P;
End;
Neste módulo a lógica utilizada assume que o primeiro elemento do intervalo dado é a
posição do maior elemento, e em seguida o vetor é percorrido do segundo elemento do
intervalo até o seu final, perguntando se o elemento é maior que o maior atual. Em caso
positivo, a posição do novo elemento assume como a posição do maior. Ao final, este
valor é retornado como resultado da função.
A procedure
recebe dois parâmetros por referência, ou seja, dois endereços de
memória, e executa a troca destes conteúdos. O conteúdo da primeira variável é
copiado para a segunda e vice-versa. Uma variável auxiliar é utilizada para não haver
perda de conteúdo nas movimentações.
O programa principal ordena as chamadas na sequência lógica estabelecida para este
problema, e proporciona a seguinte interface:
Entre
6
8
3
9
2
7
-1
V[ 1]
V[ 2]
V[ 3]
V[ 4]
V[ 5]
V[ 6]
com os dados
=
=
=
=
=
=
9.000
8.000
7.000
6.000
3.000
2.000
A lógica utilizada é chamada de método de ordenação por seleção direta. Outros
métodos estão disponíveis e são objetos de disciplina específica. A título de exemplo,
segue o módulo que ordena pelo método denominado
:
Procedure BubbleSort (Var V : TVReal; N : Integer);
Var I, J : Integer;
Begin
For I := 2 To N-1 Do
For J := N DownTo I Do
If V[J-1] < V[J] Then
Trocar (V[J-1], V[J]);
End;
Para o vetor inicializado com os dados do caso exemplo, ilustramos na sequência o
passo a passo de cada um dos cinco ciclos de execução da lógica do módulo
,
até alcançar a configuração final:
Introdução à Programação: Conceitos e Práticas.
Página 239
I:
N:
1
6
6
8
3
9
2
7
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
P:
I:
2
N:
6
9
8
3
6
2
7
4
N:
3
6
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
P:
6
I:
4
N:
6
9
8
7
6
2
3
5
6
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
V:
P:
6
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
P:
4
9
8
7
6
3
2
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
...
...
v.
2
...
...
I:
N:
9
8
7
6
2
3
P:
...
...
I:
9
8
3
6
2
7
V[1]
V[2]
V[3]
V[4]
V[5]
V[6]
Escrever um programa que forneça as seguintes operações sobre um vetor de números:
a. Copiar para
os elementos de que se encontram entre as posições e ;
b. Retornar a posição da primeira ocorrência dos elementos do vetor
em um
vetor ;
c. Eliminar os elementos do vetor que estejam entre as posições e , inclusive;
A
de parte dos elementos de um vetor para um segundo vetor deve considerar os
movimentos de memória ilustrados na seguinte figura:
Introdução à Programação: Conceitos e Práticas.
Página 240
p
q
Va: 1
2
3
4
Vb: 2
3
4
5
5
6
7
8
Figura 68: Cópia de Sub-Vetor.
A quantidade de elementos copiada é dada por
, e os índices das células do
vetor de origem são diferentes dos índices das células do vetor de destino. Se a
repetição for de a , então os índices envolvidos serão [
]
[ ].
A busca pela
de uma sequência de
elementos dentro de outra sequência
de elementos pode ser estruturada pela comparação dos primeiros
elementos de
e . Não havendo coincidência, então se compara os
elementos a partir do segundo
elemento de
com os
elementos de . Esta comparação será feita
vezes, ou até que uma igualdade seja verificada e a posição armazenada. A seguinte
figura ilustra esta lógica:
V: 1
2
3
4
5
6
7
8
1° Ciclo: Falha
1° Ciclo
Vt: 2
3
4
5
V: 1
2
3
4
5
6
7
8
2° Ciclo: Sucesso
2° Ciclo
Vt:
2
3
4
5
Figura 69: Posição de Sub-Vetor.
No exemplo deste diagrama, a quantidade máxima de repetições que seria feita a
comparação entre parte de com
seria vezes, pois
irá escorregando até que o
último elemento de
e de
fiquem emparelhados. Logo, serão feitas
comparações de vetores.
Para fazer a comparação dos
elementos de cada vetor, a lógica inicia o resultado
com a posição do primeiro elemento do sub-vetor de a ser comparado, e testa
elemento a elemento em busca de alguma diferença. Caso sejam encontrados
elementos distintos então a repetição interna é interrompida, e uma próxima comparação
de sub-vetor será feita em novo ciclo. Caso não haja diferença, então é constatado que
Introdução à Programação: Conceitos e Práticas.
Página 241
foi encontrado um sub-vetor idêntico ao vetor pesquisado, e o ciclo principal é
encerrado.
A terceira lógica trata de
os elementos entre as posições e de um vetor .
A seguinte figura ilustra os movimentos necessários. Os elementos que estão a partir da
posição
deverão ser copiados para as posições a partir de .
p
q
V: 1
2
3
4
V: 1
6
7
8
5
6
7
8
N=8
N=4
Figura 70: Eliminação de um Sub-Vetor.
Segue a implementação destas lógicas:
Program ExVETOR;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
Begin
{igual ao exemplo anterior}
End;
Procedure MostrarVet (V : TVReal; N : Integer);
Begin
{igual ao exemplo anterior}
End;
Procedure EliminarVet (Var V : TVReal; Var N : Integer;
p, q : integer);
Var I, D : Integer;
Begin
D := Q-P+1;
For I := Q+1 To N Do
V[I-D] := V[I];
N := N-D;
End;
Procedure CopiarToVet (Va : TVReal; Na : Integer;
p, q : Integer;
Introdução à Programação: Conceitos e Práticas.
Página 242
Var Vb : TVReal; Var Nb : Integer);
Var I : Integer;
Begin
For I := p To q Do
Vb[I-p+1] := Va[I];
Nb := q-p+1;
End;
Function PosVet (Vt : TVReal; Nt : Integer;
V : TVReal; N : Integer) : Integer;
Var P, I, J : Integer;
Begin
P := 0;
For I := 1 To N - Nt + 1 Do
Begin
P := I;
For J := 1 To Nt Do
If V[I+J-1] <> Vt[J] Then
Begin
P := 0;
Break;
End;
If P <> 0
Then Break;
End;
PosVet := P;
End;
Var Vx
Vy
V
: TVReal;
: TVReal;
: TVReal;
Nx
Ny
N
: Integer;
: Integer;
: Integer;
Begin
LerDados (V, N);
CopiarToVet (V, N, 2, 5, Vx, Nx);
MostrarVet (Vx, Nx);
Writeln ('POS = ', PosVet (Vx, Nx, V, N));
EliminarVet (V, N, 2, 5);
MostrarVet (V, N);
End.
A rotina
altera o próprio vetor passado como argumento, o que demanda a
passagem de parâmetro por referência.
A rotina
copia um vetor origem para um vetor destino, o que determina que
a passagem do vetor destino deva ser necessariamente por referência, pois as
alterações no parâmetro deverá ser refletida no argumento.
Introdução à Programação: Conceitos e Práticas.
Página 243
O programa principal ordena as chamadas na sequência lógica estabelecida para este
problema, e proporciona a seguinte interface:
Entre
1
2
3
4
5
6
7
8
-1
V[ 1]
V[ 2]
V[ 3]
V[ 4]
POS =
V[ 1]
V[ 2]
V[ 3]
V[ 4]
vi.
com os dados
Vetor V
=
=
=
=
2
=
=
=
=
2.000
3.000
4.000
5.000
1.000
6.000
7.000
8.000
Vetor Vx
Posição de Vx em V
Novo Vetor V
Escrever um programa que conta a quantidade de vezes que cada letra do alfabeto se
repete em uma
.
A solução deverá receber uma
e produzir como resultado um vetor com as
quantidades de vezes que cada letra aparece repetida nesta
. Segue a proposta
de uma solução:
Program ExCONTALETRA;
Type TVInt = Array['A'..'Z'] Of Integer;
Procedure ContarLetra (S : String; Var V : TVInt);
Var I : Integer; C : Char;
Begin
For C := 'A' To 'Z' Do
V[C] := 0;
For I := 1 To Length(S) Do
Begin
C := UpCase(S[I]);
If (C >= 'A') AND (C <= 'Z')
Then Inc (V[C]);
End;
End;
Procedure MostrarVet (V : TVInt);
Var C : Char;
Introdução à Programação: Conceitos e Práticas.
Página 244
Begin
For C := 'A' To 'Z' Do
If V[C] <> 0
Then Writeln ('V[''', C,'''] = ', V[C]:4);
End;
Var S
: String;
Vc : TVInt;
Begin
Readln (S);
ContarLetra (S, Vc);
MostrarVet (Vc);
End.
A rotina
implementa a lógica principal. Observar que ao contrário do que foi
dito anteriormente, este caso não demanda a presença de uma variável com a
quantidade de elementos em uso no vetor, uma vez que o vetor utilizado foi definido
com o mesmo tamanho que a quantidade de letras do alfabeto. A seguinte definição de
tipo é a base para o vetor com as contagens:
Type TVInt = Array['A'..'Z'] Of Integer;
O índice do vetor é do tipo char, sendo uma célula associada a cada letra de
a .
Recordamos que o Pascal permite que o índice de
seja qualquer faixa do tipo
ordinal.
A seguinte lógica foi implementada na rotina
:
For C := 'A' To 'Z' Do
V[C] := 0;
For I := 1 To Length(S) Do
Begin
C := UpCase(S[I]);
If (C >= 'A') AND (C <= 'Z')
Then Inc (V[C]);
End;
O primeiro
serve para zerar cada uma das células que irão conter as quantidades
de cada letra na
.
O segundo
, percorre cada caractere da string , perguntando se o seu equivalente
maiúsculo é uma letra de
a
. Em caso positivo, a célula correspondente àquela
letra é incrementada de .
Introdução à Programação: Conceitos e Práticas.
Página 245
Segue a seguinte interface de entrada e saída para um caso:
ola mundo belo, bom dia
V['A'] =
2
V['B'] =
2
V['D'] =
2
V['E'] =
1
V['I'] =
1
V['L'] =
2
V['M'] =
2
V['N'] =
1
V['O'] =
4
V['U'] =
1
22.4. Matriz
O tipo
utilizado para definir vetores também pode ser utilizado para definir
matrizes. Muitos problemas do mundo real podem ser modelados sob a forma de
matrizes tanto pela conveniência da representação quanto pela necessidade de fazer
uso da álgebra matricial. As linguagens imperativas clássicas não trazem operadores
embutidos para processar matrizes, ficando ao programador a incumbência de codificar
as rotinas com os recursos escalares da linguagem. Algumas linguagens do paradigma
funcional, tal como
, disponibilizam uma grande quantidade de operadores
matriciais. A seguinte figura compara tipos
,
e
:
1
X:
V:
X
V[I]
[1]
[2]
[3]
[4]
[5]
2
...
J
M:
...
?
1
2
3
4
...
I
...
?
[I]
M[I,J]
[?]
Figura 71: Comparação Escalar, Vetor e Matriz
Introdução à Programação: Conceitos e Práticas.
Página 246
A variável
pode ter seu conteúdo acessado diretamente através do nome da
variável, enquanto que um
necessita do nome mais um índice, e a matriz requer
além do nome mais dois índices, um para linha e outro para coluna. Este último caso,
para matrizes de duas dimensões. De forma geral, uma matriz de dimensão demanda
índices para identificar uma célula.
22.5. Sintaxe e Semântica
A sintaxe simplificada para a definição de um array com
[
dimensões é:
{
}]
A diferença em relação a definição de um vetor está na inclusão de uma lista de
. A notação {
} significa zero ou mais repetições do
conteúdo entre chaves. Assim, caso não tenha nenhuma repetição desta parte, o array
fica reduzido a um vetor. Ficam valendo as observações feitas no tópico sobre vetores,
onde a natureza do
é necessariamente escalar, ou seja, o índice
21
22
de um
deve ser do tipo
,
,
ou
. Variáveis
podem ser criadas a partir desta definição.
O seguinte exemplo ilustra as várias possibilidades de declaração de uma variável do
tipo
. À direita são apresentadas algumas atribuições às células de cada
,
permitindo também compreender o processo de indexação.
Var
Ma
Mb
Mc
Mx
Mt
Mq
Mr
Ms
Mn
Vs
:
:
:
:
:
:
:
:
:
:
Array[1..100, 1..30]
Array[0..499, 1..50]
Array[-10..10, -5..5]
Array[1..1000,'a'..'z']
Array[0..10000, 1..100]
Array['a'..'z', 1..50]
Array['0'..'9', 1..80]
Array[False..True, 'a'..'z']
Array[Boolean, 0..99]
Array[1..100]
Begin
Ma[3
,
Ma[3][10]
Mb[35
,
Mc[-5
,
Mx[300 ,
21
22
10 ]
20 ]
3 ]
'd']
:=
:=
:=
:=
:=
Of
Of
Of
Of
Of
Of
Of
Of
Of
Of
Integer;
LongInt;
Word;
Real;
Char;
Real;
Real;
Integer;
Integer;
String;
-1;
0;
80;
$ffff;
1.28;
Inclui as variações dos inteiros.
O tipo enumerado será apresentado mais adiante.
Introdução à Programação: Conceitos e Práticas.
Página 247
Mt[0
,
Mq['d' ,
Mr['4' ,
Ms[False,
Mn[True ,
Vs[1]
Vs[1,3]
Vs[1][3]
End
50 ]
30 ]
40 ]
'v']
60 ]
:=
:=
:=
:=
:=
:=
:=
:=
'x';
3.26;
-1.32e10;
-43;
43;
'ola mundo belo';
'A';
'E';
Os exemplos acima são exclusivamente de matrizes bidimensionais, porém sintaxe
semelhante se aplica a arrays multidimensionais. Observar a definição da variável
como vetor de
, o que lhe confere também a característica de matriz, uma vez
que cada célula de
faz referência a uma
, que é um vetor de char. Alguns
compiladores estenderam a sintaxe do Pascal padrão permitindo a indexação tanto na
forma [ ] ou [ ][ ], sendo esta última notação o estilo utilizado pela linguagem .
Para não gerar problemas de migração de código, é recomendado manter o primeiro
estilo. A exceção se dá no caso de vetor de
, onde a segunda forma é a mais
adequada.
Todas as considerações feitas para vetor em relação às expressões válidas para o
índice, também se aplicam para
multidimensionais, o que vale dizer, que o
índice de uma dimensão pode ser qualquer expressão compatível com o tipo adotado
na definição da variável.
Fica para o leitor analisar as variáveis declaradas e extrair a quantidade de memória
alocada a cada uma delas.
Observar que as dimensões dos
foram definidas através de constantes
numéricas. Em determinadas situações podem surgir lógicas que com frequência fazem
uso do tamanho máximo de uma determinada dimensão. Assim, ao longo do código
surgirão referências a este valor. Por exemplo, um determinado programa define a
dimensão de uma matriz para
linhas. Adicionalmente, em vários locais do programa
existem expressões aritméticas e lógicas fixando este valor nos seus cálculos. Porém,
quando por alguma necessidade a quantidade de linhas for redefinida para
, o
programador deverá percorrer todo o código em busca deste número para as devidas
readequações.
Nestas circunstâncias, é recomendado o uso da cláusula
, onde constantes
podem estar associadas a
. A sintaxe da cláusula
é:
{
}
Os exemplos que seguem ilustram o uso deste recurso:
Introdução à Programação: Conceitos e Práticas.
Página 248
CONST
ENTER
ESCAPE
SPACE
MAXCOL
MAXLIN
MAXLEN
MSG
=
=
=
=
=
=
=
#13;
#27;
#32;
100;
200;
MAXCOL * MAXLIN;
'OLA MUNDO';
Begin
{programa principal}
end.
O símbolo utilizado para relacionar o identificador com a constante é
e não
.
22.6. Exemplos
i.
Escrever um programa que preencha uma matriz bidimensional com dados lidos via
teclado e apresente estes dados na tela.
Uma matriz bidimensional é um array definido com dois índices. Assim, para percorrer
cada uma das células da matriz, quer seja para armazenar um dado ou obter o dado
armazenado, será demandado do programa, no caso de uma lógica simples, a utilização
de duas repetições aninhadas. A repetição mais interna processa mais rapidamente que
a repetição que a engloba, uma vez que o controle só retorna para a repetição externa
quando a interna é encerrada. Um segundo ciclo da repetição mais externa certamente
determinará um novo ciclo completo para a repetição interna. A seguinte figura ilustra
este estilo de construção:
Segue a proposta de uma solução:
Program ExMATRIZ;
Introdução à Programação: Conceitos e Práticas.
Página 249
Const MAXL = 100;
MAXC = 100;
Type TMReal = Array[1..MAXL, 1..MAXC] Of Real;
Procedure LerDados (Var M : TMReal; Var L, C : Integer);
Function GetX (Lin, Col : Integer) : Real;
Var X : Real;
Begin
Write ('M[',Lin,', ', Col,'] = ');
Readln (x);
GEtX := X;
End;
Var X : Real;
Begin
Writeln ('Entre com os dados:');
Writeln ('{-1} encerra LINHA');
Writeln ('{-2} encerra MATRIZ');
L := 0; C := 0;
X := GetX (L+1, C+1);
While X <> -2 Do
Begin
Inc (L);
C := 0;
If X = -1
Then X := GetX (L, C+1);
While (X <> -1) AND (X <> -2) Do
Begin
Inc (C);
M[L, C] := X;
X := GetX (L, C+1);
End;
End;
End;
Procedure MostrarMat (M : TMReal; L, C : Integer);
Var I, J : Integer;
Begin
For I := 1 To L Do
Begin
For J := 1 To C Do
Write (M[I,J]:8:3);
Writeln;
End;
End;
Introdução à Programação: Conceitos e Práticas.
Página 250
Var Mx : TMReal;
Lx, Cx : Integer;
Begin
LerDados
(Mx, Lx, Cx);
MostrarMat (Mx, Lx, Cx);
End.
A convenção adotada para as leituras dos dados é:


O valor
O valor
indica final de entrada de uma linha da matriz;
indica final de entrada da matriz;
Assim, na rotina
foram implementados dois loops, sendo que o loop externo é
encerrado quando uma entrada igual a
é identificada, e o loop intermo é encerrado
quando uma entrada
ou
é detectada. As variáveis e
controlam em que
posição da matriz o dado fornecido será armazenado. A variável é zerada antes de
iniciar o loop externo e incrementada a cada ciclo de execução deste loop. A variável é
zerada dentro do loop externo antes de iniciar o loop interno, e incrementado a cada
ciclo deste loop interno. Assim, quando
, o valor de será {
},
quando
, o valor de assumirá novamente cada valor deste conjunto. Ao encerrar
a entrada de dados, as variáveis e
conterão a dimensão real da matriz, parte
efetivamente preenchida com dados válidos.
A entrada de dados foi encapsulada na função
, que recebe como parâmetros as
posições
e
da matriz onde deverá ser armazenado o dado fornecido,
permitindo que seja apresentada na tela uma mensagem explicativa. Cabe destacar que
a função
foi implementada dentro do escopo da procedure
. Assim, ela é
acessível somente no corpo desta procedure. Com este exemplo, pretende-se mostrar
ao programador principiante que é possível, em
, limitar a visibilidade de variáveis
e rotinas ao escopo de outra rotina.
A procedure
escreve na tela os valores armazenados na matriz. São
necessárias novamente duas repetições, porém neste caso como as dimensões da
matriz já são conhecidas, então foi possível codificar a solução utilizando a instrução
. Na rotina
as dimensões só seriam conhecidas quando fosse encerrada a
digitação dos dados.
O tipo
foi definido no seguinte contexto:
Const MAXL = 100;
MAXC = 100;
Type TMReal = Array[1..MAXL, 1..MAXC] Of Real;
As dimensões associadas ao tipo
são definidas pelas constantes
e
, e não mais em função de constantes fixas. Isto proporciona uma maior facilidade
no caso de redimensionamento de variáveis deste tipo. As modificações estarão
concentradas em um único ponto do código.
Introdução à Programação: Conceitos e Práticas.
Página 251
Segue a seguinte interface de entrada e saída para um caso:
Entre com os dados:
{-1} encerra LINHA
{-2} encerra MATRIZ
M[1, 1] = 11
M[1, 2] = 12
M[1, 3] = 13
M[1, 4] = 14
M[1, 5] = -1
M[2, 1] = 21
M[2, 2] = 22
M[2, 3] = 23
M[2, 4] = 24
M[2, 5] = -1
M[3, 1] = 31
M[3, 2] = 32
M[3, 3] = 33
M[3, 4] = 34
M[3, 5] = -2
11.000 12.000 13.000
21.000 22.000 23.000
31.000 32.000 33.000
ii.
14.000
24.000
34.000
Escrever um programa que preencha uma matriz conforme o padrão que segue e
apresente estes dados na tela.
a)
b)
|
|
⋯
⋯
⋯
⋯
|
|
c)
⋯
⋯
|
|
|
|
⋯
⋯
d)
|
|
⋯
⋯
⋯
⋯
|
|
|
|
⋯
⋯
⋯
⋯
|
|
O formato geral de uma matriz é:
Introdução à Programação: Conceitos e Práticas.
Página 252
|
|
⋯
⋯
⋯
⋯
⋯
|
|
Os casos apresentados possuem lógicas que conectam os índices de uma célula com o
seu conteúdo. Por exemplo, no
onde se pretende preencher uma matriz
de acordo com o padrão dado pela matriz identidade, a lógica que orienta a forma de
preenchimento é:
Esta lógica deve ser aplicada a cada célula da matriz. Assim, a lógica para percorrer
cada elemento da célula requer duas repetição do tipo
, sendo a mais externa
produzindo os índices para as linhas
{
} e a interna os índices para as
colunas
{
}. As combinações de
e
geradas serão:
{
}.
No
, fica evidente que cada célula é preenchida com o seu índice de linha.
O
, a diagonal secundária é preenchida com e as demais células com
zero. No caso de matriz quadrada (
), uma célula pertencerá a diagonal
secundária, quando a soma dos seus índices coincidir com o valor de
.
O
trata de identificar quando uma célula está acima da diagonal principal.
Uma rápida análise nos índices permite certificar que esta condição ocorre quando
.
Segue a proposta de uma solução:
Program ExFILL;
Const MAXL
= 100;
MAXC
= 100;
NEWLINE = #10;
Type TMInt = Array[1..MAXL, 1..MAXC] Of Integer;
Procedure Fill_A (Var M : TMInt; L, C : Integer);
Var I, J : Integer;
Begin
For I := 1 To L Do
For J := 1 To C Do
M[I,J] := Ord (I=J);
End;
Introdução à Programação: Conceitos e Práticas.
Página 253
Procedure Fill_B (Var M : TMInt; L, C : Integer);
Var I, J : Integer;
Begin
For I := 1 To L Do
For J := 1 To C Do
M[I,J] := I;
End;
Procedure Fill_C (Var M : TMInt; L, C : Integer);
Var I, J : Integer;
Begin
For I := 1 To L Do
For J := 1 To C Do
If I + J = L + 1
Then M[I,J] := 1
Else M[I,J] := 0;
End;
Procedure Fill_D (Var M : TMInt; L, C : Integer);
Var I, J : Integer;
Begin
For I := 1 To L Do
For J := 1 To C Do
If J >= I
Then M[I,J] := 1
Else M[I,J] := 0;
End;
Procedure MostrarMat (Msg : String; M : TMInt; L, C : Integer);
Var I, J : Integer;
Begin
Writeln (Msg);
For I := 1 To L Do
Begin
For J := 1 To C Do
Write (M[I,J]:3);
Writeln;
End;
End;
Var Mx : TMInt; Lx, Cx : Integer;
Begin
Lx := 5; Cx := 5;
Fill_A (Mx, Lx, Cx);
MostrarMat (NEWLINE+'Exemplo a) ', Mx, Lx, Cx);
Introdução à Programação: Conceitos e Práticas.
Página 254
Fill_B (Mx, Lx, Cx);
MostrarMat (NEWLINE+'Exemplo b) ', Mx, Lx, Cx);
Fill_C (Mx, Lx, Cx);
MostrarMat (NEWLINE+'Exemplo c) ', Mx, Lx, Cx);
Fill_D (Mx, Lx, Cx);
MostrarMat (NEWLINE+'Exemplo d) ', Mx, Lx, Cx);
End.
No preenchimento da matriz identidade optou-se pela forma a esquerda para a produção
do ou do :
For I := 1 To L Do
For J := 1 To C Do
M[I,J] := Ord (I = J);
For I := 1
For J :=
If I =
Then
Else
Foi utilizada a expressão lógica
convertida para
para produzir o valor desejado. No caso de resultado
será , o que é exatamente o desejado.
Na lógica da procedure
To L Do
1 To C Do
J
M[I,J] := 1
M[I,J] := 0;
ou
,o
através da função
será , e para
optou-se pela forma convencional, com o uso do
.
Segue a seguinte interface de entrada e saída para o programa:
Exemplo
1 0
0 1
0 0
0 0
0 0
a)
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
Exemplo
1 1
2 2
3 3
4 4
5 5
b)
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
Exemplo
0 0
0 0
0 0
0 1
1 0
c)
0
0
1
0
0
0
1
0
0
0
1
0
0
0
0
Exemplo
1 1
0 1
0 0
0 0
0 0
d)
1
1
1
0
0
1
1
1
1
0
1
1
1
1
1
Introdução à Programação: Conceitos e Práticas.
Página 255
iii.
Escrever um programa que forneça as seguintes informações a partir dos dados de uma
matriz:
a. As somas dos elementos de cada linha;
b. As somas dos elementos de cada coluna;
c. O valor a posição do maior elemento.
A soma dos elementos de cada linha deverá produzir um resultado por linha, que resulta
em um vetor com o comprimento igual a quantidade de colunas da matriz.
⋯
⋯
⋯
|
|
|
|
⋯
⋯
Esta matriz deverá ser processada para produzir a seguinte soma:
⋯
⋯
⋯
|
|
⋯
⋯
|
|
|
|
[ ]
[ ]
|
[ ]
|
[
]
[]
Lógica semelhante se aplica a soma orientada por coluna.
Segue a proposta de uma solução:
Program ExFILL;
Const MAXL
MAXC
MAX
NEWLINE
=
=
=
=
100;
100;
100;
#10;
Type TMInt = Array[1..MAXL, 1..MAXC] Of Integer;
TVInt = Array[1..MAX] Of Integer;
Procedure SomarLinha (Var M : TMInt; L, C : Integer;
Var V : TVInt; Var N : Integer);
Var I, J : Integer;
Begin
N := L;
For I := 1 To L Do
Introdução à Programação: Conceitos e Práticas.
Página 256
Begin
V[I] := 0;
For J := 1 To C Do
V[I] := V[I] + M[I,J];
End;
End;
Procedure SomarColuna (Var M : TMInt; L, C : Integer;
Var V : TVInt; Var N : Integer);
Var I, J : Integer;
Begin
N := L;
For J := 1 To C Do
Begin
V[J] := 0;
For I := 1 To L Do
V[J] := V[J] + M[I,J];
End;
End;
Procedure GetMaior (Var M : TMInt; L, C : Integer;
Var Lin, Col : Integer);
Var I, J : Integer;
Begin
Lin := 1;
Col := 1;
For I := 1 To L Do
For J := 1 To C Do
If M[I,J] > M[Lin, Col] Then
Begin
Lin := I;
Col := J;
End;
End;
Procedure MostrarMat (Msg : String; M : TMInt;
L, C : Integer);
{igual aos exemplos anteriores}
End;
Procedure MostrarVet (Msg : String; V : TVInt; N : Integer);
Var I : Integer;
Begin
Writeln (Msg);
For I := 1 To N Do
Writeln ('V[',I,'] = ', V[I]:3);
End;
Procedure Fill_D (Var M : TMInt; L, C : Integer);
{igual ao exemplo anterior}
Introdução à Programação: Conceitos e Práticas.
Página 257
End;
Var Mx : TMInt; Lx, Cx : Integer;
Vx : TVInt; Nx : Integer;
Lin, Col : Integer;
Begin
Lx := 5; Cx := 5;
Fill_D (Mx, Lx, Cx); Mx[2, Cx] := 8;
MostrarMat (NEWLINE+'Matriz ', Mx, Lx, Cx);
SomarLinha (Mx, Lx, Cx, Vx, Nx);
MostrarVet (NEWLINE+'Soma Linha ', Vx, Nx);
SomarColuna (Mx, Lx, Cx, Vx, Nx);
MostrarVet (NEWLINE+'Soma Coluna ', Vx, Nx);
GetMaior (Mx, Lx, Cx, Lin, Col);
Writeln (NEWLINE+'Posicao do Maior = (', Lin, ', ',Col, ')');
End.
A lógica da
utiliza duas repetições do tipo
, sendo a mais
externa associada às
e a mais interna às
. Desta forma, para cada valor
de , será produzido um valor de para cada
. Dizemos assim, que o índice da
percorre mais rapidamente.
N := L;
For I := 1 To L Do
Begin
V[I] := 0;
For J := 1 To C Do
V[I] := V[I] + M[I,J];
End;
De forma semelhante, a
também utiliza duas repetições do tipo
, sendo a mais externa associada às
e a mais interna às
. Desta
forma, para cada valor de , será produzido um valor de para cada
. Dizemos
assim, que o índice da
percorre mais rapidamente.
N := L;
For J := 1 To C Do
Begin
V[J] := 0;
For I := 1 To L Do
V[J] := V[J] + M[I,J];
End;
Se considerarmos associado a
e associado a
, vemos que para percorrer
as colunas mais rapidamente usamos o aninhamento
⋯
, e para o caso de
percorrer as linhas mais rapidamente usamos o aninhamento
⋯
.
Introdução à Programação: Conceitos e Práticas.
Página 258
A lógica para obter a posição
do maior elemento da matriz se assemelha à
aplicada a um vetor, e consiste em percorrer cada elemento da matriz
⋯
testando se valor da célula
é maior que o elemento da célula
com o atual
maior. Em caso positivo os valores de
passam a conter os índices desta célula
.
Segue a seguinte interface de entrada e saída para o programa:
Matriz
1 1
0 1
0 0
0 0
0 0
1
1
1
0
0
1
1
1
1
0
Soma
V[1]
V[2]
V[3]
V[4]
V[5]
Linha
=
5
= 11
=
3
=
2
=
1
Soma
V[1]
V[2]
V[3]
V[4]
V[5]
Coluna
=
1
=
2
=
3
=
4
= 12
1
8
1
1
1
Posicao do Maior = (2, 5)
A matriz utilizada como teste foi preenchida pela lógica do caso
acrescida da alteração de uma célula para o valor .
do exemplo anterior,
Fill_D (Mx, Lx, Cx);
Mx[2, Cx] := 8;
iv.
Escrever um programa que efetua o produto matricial.
Considerando o seguinte produto de duas matrizes:
O produto será possível quando o número de colunas de
seja igual ao número de
linhas de
(
). A matriz
resultante será de dimensão (
). Segue um
exemplo simplificado para o produto:
Introdução à Programação: Conceitos e Práticas.
Página 259
|
|
|
|
|
|
Um elemento
da matriz é obtido pela soma dos produtos dos elementos da linha
de pelos elementos da coluna de .
Neste exemplo, o elemento
|
|
é obtido da seguinte forma:
|
|
|
|
Ou seja:
Observe que todos os elementos de na expressão possuem a mesma linha de , e
todos os elementos de possuem a mesma coluna de . Segue a expressão adaptada
para esta expressão:
Generalizando esta expressão para qualquer dimensão, e sabendo que
, tem-se:
⋯
Sob a forma de somatória, um elemento de
é obtido por:
∑
Logo, para todos os elementos de , tem-se:
∑
⋯
⋯
Segue a proposta de uma solução:
Program ExMULT;
Const MAXL
= 100;
MAXC
= 100;
NEWLINE = #10;
Introdução à Programação: Conceitos e Práticas.
Página 260
Type TMInt = Array[1..MAXL, 1..MAXC] Of Integer;
Function StrToInt (S : String) : Integer;
Var X, Code : Integer;
Begin
Val (S, X, Code);
StrToInt := X;
End;
Procedure LerDados (Msg : String; Var M : TMInt ; Var L, C : Integer);
Function GetX (Lin, Col : Integer) : String;
Var SX : String;
Begin
Write ('M[',Lin,', ', Col,'] = ');
Readln (Sx);
GetX := Sx;
End;
Var Sx : String;
Begin
Writeln (Msg);
Writeln ('{next} encerra LINHA');
Writeln ('{end} encerra MATRIZ');
L := 0; C := 0;
SX := GetX (L+1, C+1);
While Sx <> 'end' Do
Begin
Inc (L);
C := 0;
If SX = 'next'
Then SX := GetX (L, C+1);
While (SX <> 'next') AND (SX <> 'end') Do
Begin
Inc (C);
M[L, C] := StrToInt(SX);
SX := GetX (L, C+1);
End;
End;
End;
Procedure MostrarMat (Msg : String; M : TMInt; L, C : Integer);
{igual aos exemplos anteriores}
End;
Procedure ProdMat (Ma : TMInt; La, Ca : Integer;
Mb : TMInt; Lb, Cb : Integer;
Var Mc : TMint; Var Lc, Cc : Integer);
Var I, J, K, S : Integer;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 261
Lc := 0;
If Ca = Lb Then
Begin
Lc := La;
Cc := Cb;
For I := 1 To Lc Do
For J := 1 To Cc Do
Begin
S := 0;
For K := 1 To Ca Do
S := S + Ma[I,K]*Mb[K,J];
Mc[I,J] := S;
End;
End;
End;
Var Mx, My, Mz : TMInt; Lx, Cx, Ly, Cy, Lz, Cz : Integer;
Begin
LerDados ('Entre com a Matriz X', Mx, Lx, Cx);
MostrarMat (NEWLINE+'Matriz X', Mx, Lx, Cx);
LerDados ('Entre com a Matriz Y', My, Ly, Cy);
MostrarMat (NEWLINE+'Matriz Y', Mx, Lx, Cx);
ProdMat (Mx, Lx, Cx, My, Ly, Cy, Mz, Lz, Cz);
If Lz <> 0
Then MostrarMat (NEWLINE+'Matriz Z', Mz, Lz, Cz)
Else Writeln ('Produto impossível');
End.
A
foi adaptada para permitir que o
e
possam fazer parte dos
elementos da matriz. Assim, o dado de entrada é tratado como
, sendo que o final
de linha é o texto
e o final de matriz é o texto
. Não sendo um destes valores,
a
é convertida para inteiro pela função
e o resultado armazenado na
matriz. A conversão é feita utilizando a
:
Function StrToInt (S : String) : Integer;
Var X, Code : Integer;
Begin
Val (S, X, Code);
StrToInt := X;
End;
A lógica do módulo
que realiza o produto matricial define inicialmente o
produto como impossível através da atribuição
. Na sequência testa pela
viabilidade da operação através da expressão
. Em caso positivo, a lógica do
produto é iniciada.
Introdução à Programação: Conceitos e Práticas.
Página 262
O produto matricial demanda três
elemento da matriz resultante , e o
acumulada do produto de
[ ]
sendo o
eo
para referenciar cada
para obter este elemento realizando a soma
[ ]
Procedure ProdMat (Ma : TMInt; La, Ca : Integer;
Mb : TMInt; Lb, Cb : Integer;
Var Mc : TMint; Var Lc, Cc : Integer);
Var I, J, K, S : Integer;
Begin
Lc := 0;
If Ca = Lb Then
Begin
Lc := La;
Cc := Cb;
For I := 1 To Lc Do
For J := 1 To Cc Do
Begin
S := 0;
For K := 1 To Ca Do
S := S + Ma[I,K]*Mb[K,J];
Mc[I,J] := S;
End;
End;
End;
A soma acumulada poderia ser feita diretamente em
[ ] mas optou-se por utilizar a
variável para melhorar a legigilidade. A eficiência também é melhorada, uma vez que
se utiliza uma
em vez de uma
dentro do loop mais
interno.
A seguinte interface ilustra uma entrada e saída do programa, sendo que segunda
coluna é a sequência da primeira:
Entre com a Matriz X
{-1} encerra LINHA
{-2} encerra MATRIZ
M[1, 1] = 1
M[1, 2] = 2
M[1, 3] = 1
M[1, 4] = next
M[2, 1] = 2
M[2, 2] = 3
M[2, 3] = 3
M[2, 4] = next
M[3, 1] = 1
M[3, 2] = 0
M[3, 3] = 2
M[3, 4] = end
Matriz X
1 2 1
2 3 3
1 0 2
Introdução à Programação: Conceitos e Práticas.
Entre com a Matriz Y
{-1} encerra LINHA
{-2} encerra MATRIZ
M[1, 1] = 0
M[1, 2] = 5
M[1, 3] = next
M[2, 1] = 6
M[2, 2] = 3
M[2, 3] = next
M[3, 1] = -3
M[3, 2] = -4
M[3, 3] = end
Matriz Y
0 5
6 3
-3 -4
Matriz Z
9 7
9 7
-6 -3
Página 263
v.
Escrever um programa que resolva um sistema de equações lineares do tipo.
Considerando que o sistema tenha a seguinte representação matricial:
, onde:
⋯
⋯
[
]
[
]
[
]
⋯
A matriz e o vetor são fornecidos, sendo a solução desejada. O seguinte sistema
de equações será utilizado como exemplo para detalhar os passos de um método
simples de solução.
Pelo método de
, as linhas são combinadas através de operações
matemáticas que eliminem as parcelas abaixo da diagonal principal, produzindo uma
matriz triangular.
O
consiste em efetuar transformações nas três linhas abaixo da linha
de tal forma a eliminar a parcela de
nas linhas
e .
A visualização no formato de expressões pode ser melhorada se passarmos para o
formato matricial, justapondo a matriz com o vetor
produzindo a
[
]:
⋯
⋯
⋯
[
]
Para o caso exemplo, tem-se:
[
Fixando o elemento
como referência, a
Introdução à Programação: Conceitos e Práticas.
]
, produz:
Página 264
[
A lógica utilizada no
Um
]
foi:
consiste em eliminar os termos abaixo do elemento
[
A lógica utilizada no
O
]
foi:
consiste em eliminar os termos abaixo do elemento
|
A lógica utilizada no
.
.
|
foi:
Podemos combinar os passos com a lógica do escalonamento, obtendo:
Introdução à Programação: Conceitos e Práticas.
Página 265
Para completar a lógica, basta detalhar as operações com as linhas, de tal modo a ser
estendida a cada elemento. Neste caso, surgiria mais um
para codificar a
operação
. O detalhe pode ser inspecionado no código mais adiante.
A próxima etapa, com a matriz já escalonada, é obter os valores de
efetuando as
devidas substituições de baixo para cima (
). A linha
fornece o valor
de , que levado a linha fornece o valor de , e assim sucessivamente:
(
)
(
)
Assim, o vetor solução é
, e a forma geral da solução é:
∑
⋯
O seguinte programa implementa as lógicas apresentadas acima:
Program ExGAUSS;
Const MAXL
MAXC
MAX
NEWLINE
=
=
=
=
100;
100;
100;
#10;
Type TMReal = Array[1..MAXL, 1..MAXC] Of Real;
TVReal = Array[1..MAX] Of Real;
Introdução à Programação: Conceitos e Práticas.
Página 266
Function StrToReal (S : String) : Real;
Var Code : Integer; X : Real;
Begin
Val (S, X, Code);
StrToReal := X;
End;
Procedure LerDados (Msg : String; Var M : TMReal; Var L, C : Integer);
Function GetX (Lin, Col : Integer) : String;
Var SX : String;
Begin
Write ('M[',Lin,', ', Col,'] = ');
Readln (Sx);
GEtX := Sx;
End;
Var Sx : String;
Begin
Writeln (Msg);
Writeln ('{next} encerra LINHA');
Writeln ('{end} encerra MATRIZ');
L := 0; C := 0;
SX := GetX (L+1, C+1);
While Sx <> 'end' Do
Begin
Inc (L);
C := 0;
If SX = 'next'
Then SX := GetX (L, C+1);
While (SX <> 'next') AND (SX <> 'end') Do
Begin
Inc (C);
M[L, C] := StrToReal(SX);
SX := GetX (L, C+1);
End;
End;
End;
Procedure MostrarMat (Msg : String; M : TMReal; L, C : Integer);
Var I, J : Integer;
Begin
Writeln (Msg);
For I := 1 To L Do
Begin
For J := 1 To C Do
Write (M[I,J]:9:4);
Writeln;
End;
End;
Introdução à Programação: Conceitos e Práticas.
Página 267
Procedure MostrarVet (Msg : String; V : TVReal; N : Integer);
Var I : Integer;
Begin
Writeln (Msg);
For I := 1 To N Do
Writeln ('V[',I,'] =', V[I]:10:5);
End;
Procedure Gauss (Var A : TMReal; L, C : Integer);
Var I, J, K : Integer;
T : Real;
Begin
For I := 1 To L-1 Do
For J := I+1 To L Do
Begin
T := -A[I,I]/A[J,I];
For K := 1 To C Do
A[J,K] := T*A[J,K] + A[I,K];
End;
End;
Procedure BackSubst (A : TMReal; L, C : Integer;
Var V : TVReal; Var N : Integer);
Var I, J, K : Integer;
S : Real;
Begin
N := L;
For I := N DownTo 1 Do
Begin
S := A[I,C];
For J := I+1 To N Do
S := S - A[I,J]*V[J];
V[I] := S/A[I,I];
End;
End;
Var Mx : TMReal; Lx, Cx, Nx: Integer;
Vx : TVReal;
Begin
LerDados ('Entre com a Matriz X', Mx, Lx, Cx);
MostrarMat (NEWLINE+'Matriz X', Mx, Lx, Cx);
Gauss (Mx, Lx, Cx);
MostrarMat (NEWLINE+'Matriz X Triangular', Mx, Lx, Cx);
BackSubst (Mx, Lx, Cx, Vx, Nx);
MostrarVet (NEWLINE+'Vetor X', Vx, Nx);
End.
Introdução à Programação: Conceitos e Práticas.
Página 268
A procedure
recebe a matriz aumentada, trabalha seu conteúdo pelo método da
e produz a matriz triangular. Observar que a lógica do código é
equivalente aos passos feitos para o exemplo dado. Uma alteração que reduz a
quantidade de cálculos é modificar o
para:
For I := 1 To L-1 Do
For J := I+1 To L Do
Begin
T := -A[I,I]/A[J,I];
For K := I+1 To C Do
A[J,K] := T*A[J,K] + A[I,K];
End;
Com isto, os cálculos que zeram os elementos abaixo da diagonal principal não são
realizados, pois de fato esta parte da matriz não será manipulada em nenhum momento.
Fica assumido que é zero. Para efeito de visualização, foi mantido o
que efetua os
cálculos para todos os elementos da matriz.
A procedure
recebe a matriz triangular e calcula as raízes, armazenando o
resultado no parâmetro .
A seguinte interface ilustra uma entrada e saída do programa:
Entre com a Matriz X
{next} encerra LINHA
{end} encerra MATRIZ
M[1, 1] = 1
M[1, 2] = 3
M[1, 3] = 2
M[1, 4] = -4
M[1, 5] = -3
M[1, 6] = next
M[2, 1] = 2
M[2, 2] = 1
M[2, 3] = -3
M[2, 4] = 1
M[2, 5] = -1
M[2, 6] = next
M[3, 1] = 1
M[3, 2] = 2
M[3, 3] = -5
M[3, 4] = 3
M[3, 5] = 2
M[3, 6] = next
M[4, 1] = -2
M[4, 2] = 2
M[4, 3] = 2
M[4, 4] = -1
M[4, 5] = 4
M[4, 6] = end
Matriz X
1.0000
2.0000
1.0000
-2.0000
2.0000
-3.0000
-5.0000
2.0000
-4.0000
1.0000
3.0000
-1.0000
-3.0000
-1.0000
2.0000
4.0000
Matriz X Triangular
1.0000
3.0000
2.0000
0.0000
2.5000
3.5000
0.0000
0.0000 -14.0000
0.0000
0.0000 -0.0000
-4.0000
-4.5000
13.0000
-1.5385
-3.0000
-2.5000
10.0000
-6.1538
Vetor X
V[1] =
V[2] =
V[3] =
V[4] =
3.0000
1.0000
2.0000
2.0000
1.00000
2.00000
3.00000
4.00000
O método apresentado e sua respectiva implementação tem efeito introdutório e não
exaure o tema de resolução de sistemas de equações lineares.
Introdução à Programação: Conceitos e Práticas.
Página 269
23.
Arquivos
O tópico anterior abordou o tipo de dado
e quase todos os exemplos
apresentaram a necessidade de entrada de dados via teclado. Esta situação é bastante
comum, pois de alguma forma o
deve ser populado com as informações que
serão processadas. Porém, ao codificar a lógica de um problema e iniciar os testes é
frequente o surgimento de erros. Então, inicia um ciclo de correção e teste que inclui a
repetição de toda a entrada dos dados. Este processo torna cansativo o trabalho de
depuração do programa. Este cenário se acentua quando a entrada de dados envolve
grande volume de informações. A seguinte figura ilustra esta situação:
Figura 72: Entrada/Saída de grande volume de dados sem o uso de arquivos
A figura traz em destaque um programa para
, composto pelas rotinas
,
e
dados. O módulo para
gerencia a entrada de
dados, fazendo a leitura do valor digitado e o seu armazenando na memória. O módulo
efetua alguma manipulação destas informações, enquanto que
escreve os resultados na tela.
Além da facilidade nos testes, problemas reais quase sempre lidam com situações que
determinam a necessidade de armazenar dados em meios permanentes. Neste
contexto, o ideal seria que os dados que servem de entrada para algum programa
fossem digitados apenas uma vez e guardados em algum meio persistente, ou seja,
com capacidade de reter estas informações. O recurso de
proporciona esta
facilidade, permitindo que dados sejam lidos e gravados em meios de armazenamento
permanentes. A seguinte figura ilustra a adaptação da lógica anterior para incluir o uso
de arquivos como origem de dados para o programa ou como destino dos dados
enviados pelo programa:
Introdução à Programação: Conceitos e Práticas.
Página 270
Figura 73: Entrada/Saída de grande volume de dados com o uso de arquivos
Dentre as várias possibilidades, esta ilustração apresenta uma configuração de
módulos, onde a
é feita através da leitura de informações prégravadas em
. Também destaca, que quando conveniente parte das
informações pode ser lida a partir de entrada via teclado (dispositivo de entrada
padrão). A
pode ser direcionada para ser gravada também em
, mantendo quando conveniente a apresentação de informações na tela do
computador (dispositivo de saída padrão).
Um arquivo é uma entidade associada a uma sequência de bytes cujo armazenamento
acontece em um meio com capacidade de retenção. A definição se assemelha a um
vetor na memória
, porém este sem a capacidade de retenção, pois na falta de
energia o conteúdo da memória
é perdido. A interpretação do conteúdo de um
arquivo é dada pela rotina que fará a manipulação das informações.
De forma geral, os arquivos são classificados em
e
. Em
um
a sequência de bytes que compõem seu conteúdo é interpretado
como sendo números que representam caracteres
que no conjunto formam um
texto cuja visualização faz sentido a uma pessoa. No
a sequência dos
bytes que integram seu conteúdo representam informações cujo significado só pode ser
interpretado por algum programa específico, ou representam códigos de máquina, que
apenas o
ou o
estão aptos a tratar.
O gerenciamento do
,
,
é um das funções mais importantes de um
, pois tem a responsabilidade de assegurar o adequado
, bem como efetuar as operações típicas sobre arquivo, tais como
,
,
,
,
e outras.
A seguinte figura ilustra a visualização no formato texto para um arquivo que contém
um programa fonte escrito em
:
Introdução à Programação: Conceitos e Práticas.
Página 271
Figura 74: Visualização de um arquivo texto como sequência de caracteres.
A visualização na tela do conteúdo deste arquivo sob a forma de texto faz sentido, e
pode ser observado que se trata de um trecho do código fonte de um programa escrito
em
. Ou seja, o conteúdo do arquivo quando representado pelo caractere
equivalente de cada
é compreensível a uma pessoa.
A próxima figura ilustra o mesmo processo, porém aplicado a um arquivo executável:
Figura 75: Visualização de um arquivo executável como sequência de caracteres.
A visualização na tela do conteúdo deste arquivo sob a forma de texto já não faz pleno
sentido, mesmo que parte da sequência de bytes tenha equivalente textual coerente. O
conteúdo de um arquivo executável representa as instruções e os códigos binários a
serem tratados pelo
e pelo
.
Analisando um novo caso, a seguinte figura ilustra um programa que percorre os
elementos de um
de
células, cujo conteúdo varia de
a
, e os grava em
arquivo no mesmo formato em que se encontram na memória (codificado em binário).
Introdução à Programação: Conceitos e Práticas.
Página 272
Em seguida, este arquivo é visualizado com um editor de textos, que simplesmente
apresenta os caracteres equivalentes aos bytes do arquivo. Destacamos que a única
informação processada pelo editor de textos são os bytes que indicam uma nova linha.
Figura 76: Dado em Memória gravado em arquivo como binário
A visualização pelo editor de textos expõe uma série de caracteres que em nada
lembram os números do
que deram origem ao arquivo. Porém, como sabemos
de onde surgiram os dados, vemos que há uma coerência, pois a conversão para
complemento de dos dados do array enquadrados em
dá origem aos bytes do
arquivo. Cabe destacar a sequência invertida dos bytes. Cada quatro bytes formam um
número, e a sequência que representa o
, dada por
, foi armazenada
como
. Esta característica faz parte do padrão de armazenamento de
números da arquitetura
, denominada
. Uma pequena variação desta
abordagem pode ser vista na seguinte figura:
Figura 77: Dado em Memória gravado em arquivo como texto
Introdução à Programação: Conceitos e Práticas.
Página 273
O dado que vem da memória em formato bruto é convertido para o padrão texto. Com
as devidas orientações o programa utiliza a conversão adequada, de inteiro para
, real para
, ou outra conversão aplicável. A informação que vai para o
arquivo é a sequência de bytes que representa os códigos
do texto a ser
gravado. Observar que o módulo de conversão recebe o dado binário
e
produz a string
para o primeiro número. Desta forma, serão gravados em arquivos
os bytes
em hexadecimal, que representam os caracteres
e . Também
cabe destacar que após cada número aparece a sequência de dois bytes em
hexadecimal
, que é fruto da procedure
, que adiciona ao final de cada
linha gravada o código que representa o fim de linha. A procedure
não adiciona
estes dois bytes. Esta codificação dá condições para que os editores de texto entendam
quando uma informação deve ser escrita em uma nova linha da tela.
23.1. Arquivo Texto: Funções e Procedimentos
A linguagem Pascal oferece recursos básicos para manipular arquivos. Inicialmente
serão abordados arquivos textos, a fim de substituir a entrada de dados feita via
teclado. Desta forma, os problemas que exigem o fornecimento de grande quantidade
de informações poderão ter a entrada de dados direcionada para arquivo em vez de
teclado. O arquivo é um recurso gerenciado pelo
e possui vários
atributos, tais como: nome, extensão, pasta onde está armazenado, data de criação,
permissões de uso, tipo dentre outros. Para que o programa possa trabalhar com um
arquivo, é necessário fazer a ligação entre uma variável própria para isto e o arquivo
identificado pelo seu nome completo. A seguinte figura ilustra este contexto:
Figura 78: Manipulação de Arquivo por um programa
Introdução à Programação: Conceitos e Práticas.
Página 274
O uso do arquivo texto será contextualizado através de um exemplo que permitirá a
comparação entre a leitura de dados via teclado e a partir de um arquivo texto.
Extraindo um trecho de programa implementado anteriormente e isolando apenas a
parte que faz entrada e saída de dados, tem-se:
Program ExTEXT;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (Var V : TVReal; Var N : Integer);
Var X : Real;
Begin
Writeln ('Entre com os dados');
N := 0;
Readln (X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (X);
End;
End;
Procedure MostrarVet (V : TVReal; N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
Writeln ('V[', I:2,'] = ', V[I]:8:3);
End;
Var Vx
Nx
: TVReal;
: Integer;
Begin
LerDados (Vx, Nx);
{...}
MostrarVet (Vx, Nx);
End.
A procedure
faz a leitura de dados do teclado até que o usuário digite o
número
. Vamos implementar uma versão semelhante, porém buscando os dados de
um arquivo texto, cujo nome é
e pode ser criado a partir de qualquer editor
de textos. Seguem as primeiras e as últimas linhas do arquivo:
Introdução à Programação: Conceitos e Práticas.
Página 275
A procedure
será reescrita para admitir leitura de dados de um arquivo texto.
O nome do arquivo será fornecido como parâmetro. Segue a solução para este
problema:
Program ExTEXT;
Type TVReal = Array[1..100] Of Real;
Procedure LerDados (FN : String; Var V : TVReal; Var N : Integer);
Var X : Real;
F : Text;
Begin
Assign (F, FN);
Reset (F);
N := 0;
Readln (F, X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (F, X);
End;
Close (F);
End;
Procedure MostrarVet (V : TVReal; N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
Writeln ('V[', I:2,'] = ', V[I]:8:3);
End;
Introdução à Programação: Conceitos e Práticas.
Página 276
Var Vx
Nx
: TVReal;
: Integer;
Begin
LerDados ('notas.txt', Vx, Nx);
MostrarVet (Vx, Nx);
End.
Comparando as duas versões para
, tem-se:
Leitura do Teclado
Leitura de Arquivo Texto
Procedure LerDados (Var V : TVReal;
Var N : Integer);
Procedure LerDados (FN : String;
Var V : TVReal;
Var N : Integer);
Var X : Real;
Var X : Real;
F : Text;
Begin
Begin
Writeln ('Entre com os dados');
Assign (F, FN);
Reset (F);
N := 0;
Readln (X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (X);
End;
N := 0;
Readln (F, X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (F, X);
End;
Close (F);
End;
End;
As adaptações para alterar a procedure
para leitura do arquivo foram:
i.
Criação de uma variável do tipo arquivo
arquivo texto;
ii.
Chamada da procedure
arquivo
designado
pelo
);
{}
{ }
{ }
{ }
{ }
{ }
para migrar de leitura do teclado
que será utilizada para se conectar ao
que liga uma variável do tipo arquivo
seu
nome
completo
(
Introdução à Programação: Conceitos e Práticas.
a um
Página 277
iii.
Chamada da procedure
que reserva o arquivo para leitura dos seus dados;
iv.
Adaptação das chamadas a
para indicar que a leitura deve ser redirecionada do
teclado para o arquivo texto associado a uma determinada variável;
⋯
No exemplo, a chamada
determina que seja lido do arquivo texto um
número Real e armazenado na variável . Um indicador marca o ponto de parada do
, de tal forma que o próximo
lerá o número após este indicador.
v.
Liberação do arquivo associado a variável
;
Para manter a coerência entre leituras consecutivas o programa possui um indicador
que registra o ponto de parada do último
ou
. Assim que o arquivo é aberto
para leitura (
), este indicador fica posicionado no início do arquivo. Quando é
executado um
de um dado, a informação é copiada do arquivo para a variável
informada, e o indicador é posicionado no ínicio da próxima linha. Neste caso, o uso de
é útil quando a partir desta leitura não há mais dados disponíveis na linha.
Porém, se a linha contém vários dados, então o correto é efetuar as leituras individuais
com
, e reservar o
apenas para o último dado da linha.
É possível ler apenas dados escalares (
)eo
a partir dos
arquivos textos. Não há como a partir de um único
ler todo o conteúdo de um
arquivo texto para um vetor, por exemplo. É necessário criar a lógica que faz a leitura
de um escalar por vez e o armazena na célula correta do vetor.
Podemos agora melhorar a lógica da procedure de leitura para que não seja necessário
o valor
como indicador de fim dos dados. A função
retorna um
que
informa se o indicador alcançou o final de arquivo (
). O valor
corresponde ao final de arquivo. Assim, o
de leitura pode ser executado enquanto
o final de arquivo não for alcançado. O valor – pode e deve ser retirado do arquivo
texto. Segue a mudança proposta:
Leitura de Arquivo Texto
Leitura de Arquivo Texto com EOF
Procedure LerDados (FN : String;
Var V : TVReal;
Var N : Integer);
Procedure LerDados (FN : String;
Var V : TVReal;
Var N : Integer);
Var X : Real;
F : Text;
Begin
Var X : Real;
F : Text;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 278
Assign (F, FN);
Reset (F);
Assign (F, FN);
Reset (F);
N := 0;
Readln (F, X);
While X <> -1 Do
Begin
Inc (N);
V[N] := X;
Readln (F, X);
End;
Close (F);
End;
N := 0;
While Not Eof (F) Do
Begin
Readln (F, X);
Inc (N);
V[N] := X;
End;
Close (F);
End;
Observar que houve uma simplificação da lógica, pois foi dispensada a leitura antes da
repetição. O
testa pelo final de arquivo, caso tenha valor a ser lido então libera a
entrada para o corpo do
. A primeira linha efetua a leitura do dado, em seguida vem
o seu tratamento, e retorna para o
testando novamente pelo final do arquivo
(
). A função
tem o seguinte cabeçalho:
A saída para este programa é:
V[ 1]
V[ 2]
V[ 3]
V[ 4]
V[ 5]
.
.
.
V[35]
V[36]
V[37]
V[38]
=
=
=
=
=
34.300
83.800
15.400
45.800
44.200
=
=
=
=
51.000
45.500
80.200
74.800
Vamos introduzir mais uma adaptação no programa que é redirecionar a saída para em
vez de enviar as informações para a tela tenhamos elas em arquivo texto. A
será reescrita para incluir esta modificação. Comparando as
duas versões para
, tem-se:

Escrita na Tela
Procedure MostrarVet (V : TVReal; N : Integer);
Var I : Integer;
Introdução à Programação: Conceitos e Práticas.
Página 279
Begin
For I := 1 To N Do
Writeln ('V[', I:2,'] = ', V[I]:8:3);
End;

Escrita no Arquivo Texto
Procedure MostrarVet (FN : String; V : TVReal; N : Integer);
Var I : Integer;
F : Text;
{}
Begin
Assign (F, FN);
{ }
Rewrite (F);
{ }
For I := 1 To N Do
Writeln (F, 'V[', I:2,'] = ', V[I]:8:3);
{ }
{ }
Close (F);
End;
As adaptações para alterar a procedure
escrita no arquivo estão em destaque e foram:
para migrar de escrita na tela para
i.
Criação de uma variável do tipo
texto;
que será utilizada para se conectar ao arquivo
ii.
Chamada da procedure
arquivo
designado
pelo
);
iii.
Chamada da procedure
que reserva o arquivo para gravar dados. Esta foi a
diferença mais importante em relação a rotina
;
iv.
Adaptação das chamadas a
para indicar que a gravação deve ser
redirecionada da tela para o arquivo texto associado a uma determinada variável;
que liga uma variável do tipo arquivo
seu
nome
completo
(
a um
⋯
Observe que o conjunto de elementos que estava sendo escrito na tela foi redirecionado
para o arquivo, bastando indicar a variável do arquivo como primeiro argumento do
.
v.
Liberação do arquivo associado a variável
Introdução à Programação: Conceitos e Práticas.
;
Página 280
O programa principal foi adaptado para:
Var Vx
: TVReal;
Nx
: Integer;
Begin
LerDados
('notas.txt', Vx, Nx);
MostrarVet ('relat.txt', Vx, Nx);
End.
Abrindo o arquivo
conteúdo:
com um editor de textos podemos certificar do seu
23.2. Exemplos
i.
Adaptar o programa de solução de um sistema de equações lineares para permitir
entrada de dados via arquivo texto.
Este exercício demonstra a facilidade proporcionada pela entrada de dados a partir de
um arquivo texto. Um sistema de dez equações e dez incógnitas será utilizado para
testar o programa. Segue o programa proposto:
Program ExGAUSS;
Const MAXL
MAXC
MAX
= 100;
= 100;
= 100;
Type TMReal = Array[1..MAXL, 1..MAXC] Of Real;
TVReal = Array[1..MAX] Of Real;
Introdução à Programação: Conceitos e Práticas.
Página 281
Function FileExists (FN : String) : Boolean;
Var F : File;
Begin
{$I-}
Assign (F,FN);
Reset (F);
{$I+}
FileExists := (IOResult = 0) and (FN <> '');
Close (f);
end;
Procedure LerDados (FN : String; Var M : TMReal; Var L, C : Integer);
Var F : Text;
Begin
If FileExists (FN) Then
Begin
L := 0; C := 0;
Assign (F, FN);
Reset (F);
While Not Eof (F) Do
Begin
Inc (L);
C := 0;
While (Not Eoln(F)) And (Not Eof(F)) Do
Begin
Inc (C);
Read (F, M[L, C]);
End;
Readln (F);
End;
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
Procedure MostrarMat (FN, Msg : String; M : TMReal; L, C : Integer);
Var I, J : Integer;
F : Text;
Begin
Assign (F, FN);
If FileExists (FN)
Then Append (F)
Else Rewrite (F);
Writeln (F, Msg);
For I := 1 To L Do
Begin
For J := 1 To C Do
Write (F, M[I,J]:9:4);
Introdução à Programação: Conceitos e Práticas.
Página 282
Writeln (F);
End;
Writeln (F);
Writeln (F);
Close (F);
End;
Procedure MostrarVet (FN, Msg : String; V : TVReal; N : Integer);
Var I : Integer;
F : Text;
Begin
Assign (F, FN);
If FileExists (FN)
Then Append (F)
Else Rewrite (F);
Writeln (F, Msg);
For I := 1 To N Do
Writeln (F, 'V[',I,'] =', V[I]:10:5);
Close (F);
End;
Procedure ApagarArq (FN : String);
Var F : Text;
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Erase (F);
End;
End;
Procedure Gauss (Var A : TMReal; L, C : Integer);
{igual ao implementado anteriormente}
End;
Procedure BackSubst (A : TMReal; L, C : Integer;
Var V : TVReal; Var N : Integer);
{igual ao implementado anteriormente}
End;
Var Mx : TMReal; Lx, Cx, Nx: Integer;
Vx : TVReal;
Begin
LerDados
('matriz10x10.txt', Mx, Lx, Cx);
ApagarArq ('relat10x10.txt');
MostrarMat ('relat10x10.txt', 'Matriz X', Mx, Lx, Cx);
Introdução à Programação: Conceitos e Práticas.
Página 283
Gauss
(Mx, Lx, Cx);
MostrarMat ('relat10x10.txt', 'Matriz X Triangular', Mx, Lx, Cx);
BackSubst (Mx, Lx, Cx, Vx, Nx);
MostrarVet ('relat10x10.txt', 'Vetor X', Vx, Nx);
End.
Este programa traz uma série de recursos úteis a manipulação de arquivos. O arquivo
utilizado como teste tem o seguinte conteúdo:
O conteúdo representa um sistema
, o que proporciona dez linhas, sendo cada
linha com onze números, que representam os dez coeficientes mais o termo
independente. O
organiza o processamento e consiste na seguinte
sequência lógica:
i.
Executar a procedure
que carrega o conteúdo do arquivo
para a matriz
atualizando também as variáveis
e
com a dimensão da matriz. Caso exista arquivo com o mesmo nome do arquivo a
ser utilizado para conter o relatório com a saída do programa, então apague tal
arquivo [
].
Begin
LerDados
ApagarArq
ii.
('matriz10x10.txt', Mx, Lx, Cx);
('relat10x10.txt');
Gravar o conteúdo da matriz
no arquivo
. A chamada
[
] informa o nome do
arquivo de saída, uma linha de cabeçalho e a matriz com os dados.
MostrarMat ('relat10x10.txt', 'Matriz X', Mx, Lx, Cx);
iii.
Triangularizar a matriz informada pelo método de Eliminação de Gauss
[
]. Gravar o conteúdo desta nova matriz no arquivo
Introdução à Programação: Conceitos e Práticas.
Página 284
destinado a conter o relatório de saída. Esta informação deve ser anexada ao
final do arquivo.
Gauss
(Mx, Lx, Cx);
MostrarMat('relat10x10.txt', 'Matriz X Triangular', Mx, Lx, Cx);
iv.
Obter a solução deste sistema realizando as substituições de baixo para cima e
armazenar a solução no vetor
[
]. Gravar o
conteúdo deste vetor solução no arquivo destinado a conter o relatório de saída.
Esta informação deve ser anexada ao final do arquivo.
BackSubst (Mx, Lx, Cx, Vx, Nx);
MostrarVet ('relat10x10.txt', 'Vetor X', Vx, Nx);
End.
A procedure
carrega o conteúdo do arquivo de dados para uma variável de
memória. Porém a lógica deve funcionar para outras dimensões. Assim a estrutura da
ficou:
i.
Verificar se o arquivo informado existe [
]. Em caso positivo,
iniciar o processamento. Zerar os parâmetros associados com a quantidade de
linhas e de colunas da matriz. A função
foi implementada.
If FileExists (FN) Then
Begin
L := 0; C := 0;
ii.
Vincular a variável com o nome do arquivo em
arquivo para leitura apenas [
].
[
]. Resevar o
Assign (F, FN);
Reset (F);
iii.
Iniciar uma repetição que encerra apenas quando for alcançado o fim do arquivo
vinculado a variável [
].
While Not Eof (F) Do
Begin
iv.
Ao entrar na primeira repetição é sinal de que há linhas a serem lidas, então
incrementar o contador de linhas e zerar o contador de colunas, antes de entrar
na segunda repetição que fará a leitura de cada um dos dados de uma linha.
Inc (L);
C := 0;
v.
Iniciar uma segunda repetição, dentro da anterior, que encerra apenas quando
for alcançado o
. Para não incorrer em falha na última linha, testar
Introdução à Programação: Conceitos e Práticas.
Página 285
também pelo
[
função
testa se foi alcançado o fim de linha em um arquivo texto.
]. A
While (Not Eoln(F)) And (Not Eof(F)) Do
Begin
vi.
Incrementar a quantidade de colunas e ler para a memória um dado do arquivo.
Manter o indicador de leitura posicionado para ler o próximo dado
[
[
] ]. Caso fosse utilizado o
o indicador avançaria para o
início da próxima linha, desprezando todos os dados restantes.
Inc (C);
Read (F, M[L, C]);
End;
vii.
Após encerrar a repetição interna reposicione o indicador para o início da
próxima linha. Sem esta instrução o indicador ficará estacionado no final da linha
anterior, e não permitiria encerrar a repetição [
].
Readln (F);
End;
viii.
Fim do loop principal. Liberar o Arquivo [
então
imprimir
mensagem
[
[
]
].
]. Caso o arquivo não exista
adequada
na
tela
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
A função
i.
testa pela existência de um arquivo com o nome informado:
Cabeçalho da função. Recebe uma string com um nome de arquivo. Retorna
se o referido arquivo existe na pasta indicada. Não havendo indicado o
caminho, a pasta onde o executável está sendo processado é usada como
referência.
Function FileExists (FN : String) : Boolean;
Var F : File;
Begin
ii.
Desabilita a diretiva de compilação que verifica erro de
[{
}]. Nesta
condição o programa não acusará
a partir deste ponto. Vincular
com
[
] e tentar abrir o arquivo [
].
{$I-}
Assign (F,FN);
Reset (F);
Introdução à Programação: Conceitos e Práticas.
Página 286
iii.
Habilita a diretiva de compilação para erro de I/O. Testar o retorno da função
que informa o código de erro da última operação de I/O. Um valor zero
indica que não houve erro. O nome do arquivo deve ser diferente de texto vazio.
Liberar o arquivo.
{$I+}
FileExists := (IOResult = 0) and (FN <> '');
Close (f);
end;
A procedure
i.
elimina o arquivo com o nome informado:
Cabeçalho da procedure. Recebe uma string com um nome de arquivo.
Procedure ApagarArq
Var F : Text;
Begin
ii.
(FN : String);
Testar pela existência do arquivo [
]. Caso exista, então
vincular
com
[
]. Eliminar o arquivo informado por
[
].
If FileExists (FN) Then
Begin
Assign (F, FN);
Erase (F);
End;
End;
A procedure
a) Vincular
[
grava no arquivo indicado o conteúdo de uma matriz:
[
com
]. Testar pela existência do arquivo
].
Begin
Assign (F, FN);
If FileExists (FN)
b) Caso exista, então reservar o arquivo exclusivamente para escrita de linhas ao
seu final [
]. Caso o arquivo não exista, então criar um arquivo com o
nome indicado e reservar para escrita de linhas [
].
Then Append (F)
Else Rewrite (F);
c) Escrever uma linha explicativa no arquivo. Percorrer as linhas [
] e as
colunas [
] da matriz. Escrever cada elemento de uma linha da matriz em
sequência no arquivo [
[ ]
] . Após percorrer a linha da matriz,
Introdução à Programação: Conceitos e Práticas.
Página 287
então grave no arquivo
uma nova linha
o código de fim de linha [
], dando início a
Writeln (F, Msg);
For I := 1 To L Do
Begin
For J := 1 To C Do
Write (F, M[I,J]:9:4);
Writeln (F);
End;
d) Para melhorar a a legibilidade do arquivo são inseridas duas linhas em branco
[
]. Liberar o arquivo [
].
Writeln (F);
Writeln (F);
Close (F);
End;
A procedure
grava no arquivo indicado o conteúdo do vetor solução. A lógica
desta rotina utiliza recursos já explicados.
ii.
Elaborar um programa que recebe informações sobre as notas anuais de uma disciplina
e gera um relatório com as médias ponderadas.
O formato do arquivo para este exercício é dado por:
o
o
o
Primeira linha contém os quatro pesos adotados para cada nota;
A segunda linha contém o nome da disciplina;
Da terceira linha em diante vem vários blocos de cinco linhas com o nome do
aluno e as quatro notas.
Segue um exemplo de arquivo cujo conteúdo está de acordo com esta especificação.
Introdução à Programação: Conceitos e Práticas.
Página 288
O relatório esperado para este problema é uma relação de nomes com suas
correspondentes notas e média ponderada. Os dados deverão ser carregados do
arquivo para a memória, processados, e em seguida os resultados formatados devem
ser gravados em arquivo. Assim, a primeira tarefa é escolher uma forma de organizar
estes dados na memória. Com os recursos atuais, a estrutura mais adequada para
acomodar o núcleo principal das informações é o tipo
. Os pesos, os nomes e as
notas serão acomodadas em variáveis do tipo
. O seguinte diagrama apresenta
uma proposta de organização:
ARQUIVO
MEMÓRIA
0.2 0.2 0.3 0.3
Calculo
Adair Pereira
49
34
74
67
Disciplina (Disc)
Calculo
Adalto Cardoso
Pesos (Mp, Lp, Cp)
0.2
0.2
0.3
0.3
97
69
66
74
Calcular
Médias
Afonso Vargas
49
74
58
100
Alexandre Teixeira
61
83
56
44
Andrea Conti
78
71
26
41
Nomes (Vn, N)
Adair Pereira
Adalto Cardoso
Afonso Vargas
Alexandre Teixeira
.
.
.
Notas (Mt, Lt, Ct)
49 34 74 67
97 69 66 74
49 74 58 100
61 83 56 44
.
.
.
.
.
.
.
.
.
.
.
.
Médias (Mm, Lm, Cm)
xx
xx
xx
xx
Figura 79: Organização dos dados da disciplina na memória
Introdução à Programação: Conceitos e Práticas.
Página 289
A proposta para acomodar os pesos das provas em uma matriz com uma coluna visa
facilitar o cálculo da média, pois desta forma a rotina que implementa o produto matricial
poderá ser utilizada. Observar que a média de um aluno é a soma do produto das suas
notas pelos respectivos pesos.
Segue o programa proposto:
Program ExMEDIAS;
Const MAXL
MAXC
MAX
= 100;
= 100;
= 100;
Type TMReal
= Array[1..MAXL, 1..MAXC] Of Real;
TVString = Array[1..MAX] Of String;
Function FileExists (FN : String) : boolean;
{igual ao implementado anteriormente}
End;
Function PadRight (S : String; N : Integer) : String;
Begin
While Length(S) < N Do
S := S + ' ';
PadRight := S;
End;
Procedure LerDados (FN : String;
Var Mp
:
Var Disc
:
Var Vnomes :
Var Mt
:
Var F : Text;
TMReal;
Var Lp, Cp : Integer;
String;
TVString; Var Nnomes : Integer;
TMReal;
Var Lt, Ct : Integer);
Procedure LerPesos;
Begin
Lp := 0; Cp := 1;
While Not Eoln(F) Do
Begin
Inc (Lp);
Read (F, Mp[Lp, Cp]);
End;
Readln (F);
End;
Introdução à Programação: Conceitos e Práticas.
Página 290
Procedure LerNomesNotas;
Var J : Integer;
Begin
Lt := 0; Ct := Lp;
While Not Eof (F) Do
Begin
Inc (Lt);
Readln (F, Vnomes[Lt]);
For J := 1 To Lp Do
Readln (F, Mt[Lt, J]);
End;
Nnomes := Lt;
End;
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Reset (F);
LerPesos;
Readln (F, Disc);
LerNomesNotas;
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
Procedure RelatNotas (FN
Mp
Disc
Vnomes
Mt
Mm
Var I, J : Integer;
F : Text;
:
:
:
:
:
:
String;
TMReal;
String;
TVString;
TMReal;
TMReal;
Procedure Cabecalho;
Var J : Integer;
Begin
Writeln (F, 'Disciplina: ', Disc);
Writeln (F);
Writeln (F, '
Aluno
Introdução à Programação: Conceitos e Práticas.
N1
Lp, Cp : Integer;
Nnomes : Integer;
Lt, Ct : Integer;
Lm, Cm : Integer);
N2
N3
N4
Media');
Página 291
Write
(F, PadRight(' ', 21));
For J := 1 To Ct Do
Write (F, '[',Mp[J,1]:4:1,']');
Writeln (F);
Writeln (F);
End;
Begin
Assign (F, FN);
Rewrite (F);
Cabecalho;
For I := 1 To Lt Do
Begin
Write (F, Padright(Vnomes[I],20));
For J := 1 To Ct Do
Write (F, Mt[I,J]:6:1);
Writeln (F, Mm[I,1]:6:1);
End;
Close (F);
End;
Procedure ProdMat (Ma : TMReal; La, Ca : Integer;
Mb : TMReal; Lb, Cb : Integer;
Var Mc : TMReal; Var Lc, Cc : Integer);
Var I, J, K : Integer; S : Real;
Begin
Lc := 0;
If Ca = Lb Then
Begin
Lc := La;
Cc := Cb;
For I := 1 To Lc Do
For J := 1 To Cc Do
Begin
S := 0;
For K := 1 To Ca Do
S := S + Ma[I,K]*Mb[K,J];
Mc[I,J] := S;
End;
End;
End;
Var Mt, Mp, Mm : TMReal;
Vn : TVString;
Lt, Ct, Lp, Cp, Lm, Cm, N : Integer;
Disc : String;
Introdução à Programação: Conceitos e Práticas.
Página 292
Begin
LerDados
ProdMat
('notas calculo.txt', Mp, Lp, Cp, Disc, Vn, N,
Mt, Lt, Ct);
(Mt, Lt, Ct, Mp, Lp, Cp, Mm, Lm, Cm);
RelatNotas ('relat notas.txt', Mp, Lp, Cp, Disc, Vn, N,
Mt, Lt, Ct, Mm, Lm, Cm);
End.
O programa principal explicita as três principais funcionalidades: Ler os dados do arquivo
para a memória; Calcular a média e elaborar o relatório.
A procedure
é responsável em pegar as informações que estão no arquivo e
trazê-las para a memória, acomodando cada informação na estrutura adequada. Os
pesos das notas são armazenados em uma matriz com uma coluna e tantas linhas
quantos forem os pesos. O título da disciplina será armazenado em uma variável string.
Os nomes serão organizados em um vetor de strings, onde cada posição deste vetor
conterá o nome do aluno. As notas serão estruturadas em uma matriz cuja quantidade
de linhas será igual a quantidade de alunos e a quantidade de colunas será igual a
quantidade de pesos. O corpo da procedure ficou com a seguinte lógica:
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Reset (F);
LerPesos;
Readln (F, Disc);
LerNomesNotas;
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
A sequência de passos da
consiste em:
a) Testar pela existência do arquivo [
]. Caso exista, então
vincular
com
[
] e reservar o arquivo
para leitura
[
].
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Reset (F);
Introdução à Programação: Conceitos e Práticas.
Página 293
b) Com o arquivo devidamente aberto, então proceda a leitura dos pesos:
LerPesos;
A leitura dos pesos é feita por uma rotina separada a fim de não prejudicar a
legibilidade da procedure
. Observe que a procedure
não está
no mesmo nível que
, mas dentro do contexto de
. Isto
permite que os parâmetros e variáveis de
sejam visíveis a
.
Como a lógica da procedure
tem baixa probabilidade de ser reutilizada,
então esta abordagem permite modularizar o código sem o formalismo da
. Esta estratégia deve ser utilizada com critério, a fim de
não negligenciar a prática de
, que é fundamental para
uma boa modularização do código.
Procedure LerPesos;
Begin
Lp := 0; Cp := 1;
While Not Eoln(F) Do
Begin
Inc (Lp);
Read (F, Mp[Lp, Cp]);
End;
Readln (F);
End;
O número de linhas da matriz é inicializado com
e quantidade de colunas
com , conforme comentado anteriormente. Em seguida é iniciado um
que
se encerra quando for encontrado o código de
. Para cada repetição
é lido um número (peso) e armazenado na posição adequada da matriz de
pesos. Ao encerrar o
o indicador de posição no arquivo fica posicionado
sobre os caracteres de
. Para evitar erros nas próximas leituras, este
indicador deve avançar para o início da próxima linha. Este avanço é feito pela
instrução
.
c) Efetuar a leitura das disciplina:
Readln (F, Disc);
Os caracteres entre o
e o
string indicada. Além disso, os caracteres de
indicador é posicionado no início da próxima linha.
são lidos para a
são saltados, e o
d) Efetuar a leitura dos nomes e notas:
LerNomesNotas;
Introdução à Programação: Conceitos e Práticas.
Página 294
A leitura dos nomes e notas também foram feitas em módulo separado em
benefício da legibilidade.
Procedure LerNomesNotas;
Var J : Integer;
Begin
Lt := 0; Ct := Lp;
While Not Eof (F) Do
Begin
Inc (Lt);
Readln (F, Vnomes[Lt]);
For J := 1 To Lp Do
Readln (F, Mt[Lt, J]);
End;
Nnomes := Lt;
End;
O
principal se repete até encontrar o fim de arquivo [
].
Em cada passo do loop é incrementado o contador de alunos [
] e lida
uma linha inteira com o nome do aluno e armazenado no vetor de strings
[
[ ] ]. Logo após a leitura do nome do aluno é executada
uma repetição para ler cada uma das notas e armazená-las na matriz de notas.
Após encerrar o
, a quantidade de elementos do vetor de nomes recebe o
mesmo valor que a quantidade de linhas da matriz de notas.
e) Liberar o arquivo. Se a abertura inicial não foi bem sucedida então é apresentada
uma mensagem.
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
Após ter os dados acomodados na memória, é processada a procedure
, cuja
tarefa é combinar as
e os
para produzir as
. A média de um aluno é
dada pela soma dos produtos das notas pelos pesos. Deve ser multiplicada a primeira
nota pelo primeiro peso, a segunda nota pelo segundo peso e assim por diante, e ao
final somar estas parcelas. No caso em questão a soma dos pesos sempre será , o que
dispensa a divisão pela somatória dos pesos. Assim, o cálculo da média é o produto
matricial entre notas e pesos.
ProdMat
(Mt, Lt, Ct, Mp, Lp, Cp, Mm, Lm, Cm);
Introdução à Programação: Conceitos e Práticas.
Página 295
Concluída a execução do produto matricial, o passo seguinte é elaborar um relatório
integrando as informações. A rotina
tem como parâmetros todas as
informações para compor o relatório. A seguinte chamada é responsável por produzir um
arquivo com os dados agregados:
RelatNotas ('relat notas.txt', Mp, Lp, Cp, Disc, Vn, N,
Mt, Lt, Ct, Mm, Lm, Cm);
A sequência de passos da procedure consiste em:
a) Vincular com
[
] e criar o arquivo e reservar para gravação
[
]. Caso exista arquivo com este nome ele será recriado e seu
conteúdo anterior perdido.
Begin
Assign (F, FN);
Rewrite (F);
b) Invocar a procedure que grava linhas de cabeçalho:
Cabecalho;
c) Para cada aluno [
caracteres [
] do vetor de nomes gravar o nome ajustado para
[ ]
]:
For I := 1 To Lt Do
Begin
Write (F, Padright(Vnomes[I],20));
d) A frente do nome gravar as notas [
notas gravar a média [
[
[
]
]
] e após as
]:
For J := 1 To Ct Do
Write (F, Mt[I,J]:6:1);
Writeln (F, Mm[I,1]:6:1);
End;
e) Liberar o arquivo:
Close (F);
End;
Introdução à Programação: Conceitos e Práticas.
Página 296
Segue um extrato do relatório produzido para uma entrada de dados típica é:
Disciplina: Calculo
Aluno
Adair Pereira
Adalto Cardoso
Afonso Vargas
Alexandre Teixeira
Andrea Conti
Antonio Bárbara
Carlos Galhardo
Carlos Pedreira
.
.
.
Josué Ribeiro
Justino Roman
Leona Mattos
Maria dos Santos
Mário Valdivino
Pedro Antunes
Roberto Diniz
Romana Peres
iii.
N1
N2
N3
N4
Media
[ 0.2][ 0.2][ 0.3][ 0.3]
49.0
97.0
49.0
61.0
78.0
99.0
65.0
26.0
34.0
69.0
74.0
83.0
71.0
96.0
26.0
53.0
74.0 67.0
66.0 74.0
58.0 100.0
56.0 44.0
26.0 41.0
88.0 38.0
23.0 75.0
66.0 34.0
58.9
75.2
72.0
58.8
49.9
76.8
47.6
45.8
90.0
47.0
24.0
84.0
100.0
61.0
85.0
34.0
44.0
30.0
26.0
28.0
33.0
31.0
74.0
65.0
96.0
87.0
71.0
90.0
62.0
54.0
25.0
30.0
62.5
62.5
45.4
63.8
53.3
42.1
67.5
51.6
23.0
70.0
47.0
48.0
27.0
25.0
94.0
76.0
Elaborar um programa que recebe informações sobre pesos e alturas e gera um
relatório com os índices de massa corpórea.
O seguinte diagrama ilustra o formato do arquivo de entrada, bem como a saída
desejada:
O arquivo de entrada contém uma sequência de informações agrupadas a cada
duas linhas. A primeira linha se refere ao nome de uma pessoa e a segunda
linha possui os dados de peso e altura. O arquivo de saída descreve o formato
do relatório e ilustra os processamentos requeridos, tais como: o cálculo do IMC
de cada pessoa, bem como a obtenção das médias do peso, altura e o IMC
destas médias.
Introdução à Programação: Conceitos e Práticas.
Página 297
Segue o programa proposto:
Program ExIMC;
Const MAX
= 100;
Type TvReal
= Array[1..MAX] Of Real;
TVString = Array[1..MAX] Of String;
Function FileExists (FN : String) : boolean;
Var F : File;
begin
{$I-}
Assign (F,FN);
Reset (F);
{$I+}
FileExists := (IoResult = 0) and (FN <> '');
Close (f);
end;
function getIMC (P : Real; H : Real) : Real;
Begin
getIMC := P/Sqr(H);
End;
Function PadRight (S : String; Ch : Char; N : Integer) : String;
Begin
While Length(S) < N Do
S := S + Ch;
PadRight := S;
End;
Function PadLeft (S : String; Ch : Char; N : Integer) : String;
Begin
While Length(S) < N Do
S := Ch + S;
PadLeft := S;
End;
Function Center (S : String; N : Integer) : String;
Begin
Center := PadLeft (S, ' ', Length(S) + (N - Length(S)) Div 2);
End;
Procedure LerDados (FN : String;
Var CN : TVString;
Var CP, CA : TVReal;
Var N : Integer);
Introdução à Programação: Conceitos e Práticas.
Página 298
Var F : Text;
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Reset (F);
N := 0;
While Not EOF (F) Do
Begin
Inc (N);
Readln (F, CN[N]);
Readln (F, CP[N], CA[N]);
End;
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
Procedure CalcIMC (CP, CA : TVReal;
Var CM : TVReal;
N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
CM[I] := GetImc (CP[I], CA[I]);
End;
Function GetMedia (V : TVReal; N : Integer) : Real;
Var I : Integer; S : Real;
Begin
S := 0;
For I := 1 To N Do
S := S + V[I];
GetMedia := S/N;
End;
Procedure Relat (FN : String;
CN : TVString;
CP, CA, CM : TVReal;
N : Integer;
PesoM, AltM, ImcM : Real);
Var I : Integer;
F : Text;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 299
Assign (F, FN);
Rewrite (F);
Writeln (F, Center ('Relatorio de IMC', 60));
Writeln (F);
Writeln (F, ' N
Nome
Peso
Alt
IMC') ;
For I := 1 To N Do
Writeln (F, I:3, ' ', Padright(CN[I],' ', 30),
CP[I]:8:2, CA[I]:8:2, CM[I]:8:2);
Writeln (F);
Writeln (F, PadRight(Center('Medias',34),' ', 34),
PesoM:8:2, AltM:8:2, ImcM:8:2);
Close (F);
End;
Var VN
VP, VA, VM
MedP, MedA, MedM
N
Begin
LerDados
CalcIMC
MedP :=
MedA :=
MedM :=
:
:
:
:
TVString;
TVReal;
Real;
Integer;
('peso-alt.txt', VN, VP, VA, N);
(VP, VA, VM, N);
GetMedia (VP, N);
GetMedia (VA, N);
GetIMC (MedP, MedA);
Relat ('rimc.txt', VN, VP, VA, VM, N, MedP, MedA, MedM);
End.
O programa principal explicita as três principais funcionalidades: Ler os dados do
arquivo para a memória; Processar os cálculos: Índice de Massa Corpórea e
Médias; e elaborar o relatório. As rotinas e as lógicas utilizadas se assemelham
ao exemplo anterior para o cálculo das médias aritméticas, ficando a cargo leitor
se aprofundar no entendimento.
Introdução à Programação: Conceitos e Práticas.
Página 300
Segue um extrato do relatório produzido:
Relatorio de IMC
N
1
2
3
4
5
6
7
.
.
.
23
24
25
26
27
28
29
30
Nome
Adair Pereira
Adalto Cardoso
Afonso Vargas
Alexandre Teixeira
Andrea Conti Santos
Antonio Barbara
Carlos Galhardo
Peso
66.90
73.10
85.00
70.90
82.30
55.20
50.50
Alt
1.72
1.54
1.66
1.78
1.53
1.64
1.77
IMC
22.61
30.82
30.85
22.38
35.16
20.52
16.12
Josue Ribeiro
Justino Roman
Leona Mattos
Maria dos Santos
Mario Valdivino
Pedro Antunes
Roberto Diniz
Romana Peres
93.90
64.80
62.00
92.00
85.30
56.20
78.40
97.00
1.95
1.68
1.60
1.85
1.78
1.51
1.87
1.94
24.69
22.96
24.22
26.88
26.92
24.65
22.42
25.77
Medias
75.69
1.75
24.70
Introdução à Programação: Conceitos e Práticas.
Página 301
24.
Conjuntos
Em algumas circunstâncias o uso de conjuntos melhora a legibilidade do programa,
pois proporciona um mecanismo mais natural para operar sobre coleção ordenada de
elementos não repetidos. O Pascal oferece este recurso, porém limitado a conjuntos
formados por ordinais (
). Além disso, são permitidos
apenas ordinais cujo tamanho seja de
byte e domínio de
a
. A solução
empregando conjuntos é geralmente mais eficiente do que uma lógica equivalente
utilizando array. O tipo conjunto tem a seguinte sintaxe:
24.1. Operadores
As soluções baseadas em conjunto tendem a ser bastante eficiente, pois a
representação na memória para conjuntos geralmente consiste em uma sequência de
bits onde o valor
significa elemento ausente e o valor
elemento presente. São
reservados
(
) para a variável
, que é a quantidade máxima de
elementos permitida. As operações de {
} são
eficientemente traduzidas para operações lógicas com bits. É importante consultar o
documento do compilador para certificar da abordagem utilizada na representação de
conjuntos.
Além das operações permitidas, a tabela23 também ilustra alguns exemplos.
Operador
Ação
Exemplos
Program ExCONJUNTO;
União
Type TSByte = Set Of Byte;
TSChar = Set Of Char;
Diferença
Var Vogais
Digitos
Unidades
Consoantes
Letras
M31
:
:
:
:
:
:
TSChar;
TSChar;
TSByte;
TSChar;
TSChar;
TSByte;
23
O Pascal padrão prevê as operação de União, Diferença, Interseccção e Pertinência. As demais operações fazem
parte da extensão provida pela implementação da linguagem.
Introdução à Programação: Conceitos e Práticas.
Página 302
M30
AlfaNum
Interseccção
Está Contido
Contém
Pertinência
Begin
Vogais
Vogais
Letras
Consoantes
M30
M31
Digitos
Unidades
AlfaNum
: TSByte;
: TSChar;
:=
:=
:=
:=
:=
:=
:=
:=
:=
['a', 'e', 'i', 'o'];
Vogais + ['u'];
['a'..'z'];
Letras
Vogais;
[4, 6, 9, 11];
[1, 3..12]
M30;
['0'..'9'];
[0..9];
Letras + Digitos;
If 'a' in Vogais
Then Writeln ('''a'' é vogal');
If Digitos <= AlfaNum
Then Writeln ('Digitos contido em AlfaNum');
If AlfaNum >= Digitos
Then Writeln ('AlfaNum contém Digitos');
Igual
If Digitos <= Digitos
Then Writeln ('Digitos contido em Digitos');
If Digitos = Digitos
Then Writeln ('Digitos é igual a Digitos');
Diferente
If Digitos <> TSChar(Unidades)
Then Writeln ('Digitos diferente de Unidades');
End.
Os elementos do conjunto são designados listando seus componentes de forma
individual ou por faixa de valores separados por vírgulas, e envolvidos pelos
símbolos [ ], como segue:






['a', 'e', 'i', 'o']
['a'..'z']
[4, 6, 9, 11]
[1, 3..12]
['0'..'9']
[0..9]
Introdução à Programação: Conceitos e Práticas.
Página 303
Além das atribuições que ilustram algumas operações sobre conjuntos, uma sequência
de
complementam este exemplo. Porém, a expressão do último
apresenta um
detalhe que o distingue dos demais:
If Digitos <> TSChar(Unidades)
Then Writeln ('Digitos diferente de Unidades');
O nome do tipo
envolve a variável
expressão fosse escrita da seguinte forma:
que é do tipo
. Caso a
If Digitos <> Unidades
Then Writeln ('Digitos diferente de Unidades');
A intenção é testar se os dois conjuntos são diferentes, porém ocorrerá erro de
compilação pois há incompatibilidade na comparação de dois conjuntos de elementos
de tipos distintos (
e
). Entretanto, a diferença é apenas no nível
abstrato, pois no nível concreto de representação de dados as duas variáveis são
semelhantes. Assim, para contornar o erro sintático e permitir a comparação se utiliza o
conceito de
(conversão de tipo), que de fato força que o valor da variável
seja interpretado como
, ficando assim compatível com a variável
.
Além dos exemplos que seguem, fica a sugestão de modificar a função
para utilizar conjuntos.
24.2. Exemplos
i.
Elaborar um programa que informa se um determinado caractere é uma consoante,
vogal, dígito, alfanumérico, maiúscula, minúscula, ....
A solução proposta adota exclusivamente operações com conjuntos.
Program ExLOGICA;
Function IsLetra (Ch : Char) : Boolean;
Begin
IsLetra := UpCase(Ch) in ['A'..'Z'];
End;
Function IsVogal (Ch : Char) : Boolean;
Begin
IsVogal := UpCase(Ch) in ['A', 'E', 'I', 'O', 'U'];
End;
Function IsConsoante (Ch : Char) : Boolean;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 304
IsConsoante := UpCase (Ch) in (['A'..'Z'] –
['A', 'E', 'I', 'O', 'U']);
End;
Function IsDigit (Ch : Char) : Boolean;
Begin
IsDigit := Ch in ['0'..'9'];
End;
Function IsLower (Ch : Char) : Boolean;
Begin
IsLower := Ch in ['a'..'z'];
End;
Function IsUpper (Ch : Char) : Boolean;
Begin
IsUpper := Ch in ['A'..'Z'];
End;
Begin
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
End.
(IsConsoante('a'));
(IsConsoante('B'));
(IsDigit('x'));
(IsDigit('3'));
(IsVogal('a'));
(IsVogal('b'));
As soluções codificadas ficaram simples e intuitivas utilizando o operador , que retorna
se o elemento representado pelo argumento da esquerda pertence ao conjunto
representado pelo argumento a direita. É importante destacar que conjunto se aplica
apenas a tipos ordinais, não sendo possível construções como: [
], ou
[
], pois
e
não são ordinais.
A interface de entrada e saída para o programa é:
FALSE
TRUE
FALSE
TRUE
TRUE
FALSE
ii.
Elaborar um programa que faça as seguintes operações:
a. Relacionar em um conjunto as letras de uma string;
b. Compor uma string com as letras de um conjunto;
c. Eliminar os caracteres de uma string que pertençam a um conjunto.
Introdução à Programação: Conceitos e Práticas.
Página 305
Segue uma proposta de solução:
Program ExSTRSET;
Type TSChar = Set Of Char;
Function DelChars (S : String; Chars : TSChar) : String;
Var R : String; I : Integer;
Begin
R := '';
For I := 1 To Length(S) Do
If Not (S[I] in Chars)
Then R := R + S[I];
DelChars := R;
End;
Function StrToSet (S : String) : TSChar;
Var R : TSChar; I : Integer;
Begin
R := [ ];
For I := 1 To Length(S) Do
R := R + [S[I]];
StrToSet := R;
End;
Function SetToStr (S : TSChar) : String;
Var R : String; C : Char;
Begin
R := '';
For C := #0 To #255 Do
If C in S
Then R := R + C;
SetToStr := R;
End;
Begin
Writeln (DelChars ('ola mundo belo', ['a', 'o']));
Writeln (SetToStr(StrToSet('ola mundo belo')));
End.
A lógica da função que recebe uma string e retorna um conjunto de caracteres está
estruturada como segue:
a. Inicializar a variável
com o conjunto vazio: {
Introdução à Programação: Conceitos e Práticas.
[] };
Página 306
Function StrToSet (S : String) : TSChar;
Var R : TSChar; I : Integer;
Begin
R := [ ];
b. Percorrer cada caractere da string [
] e adicionar o caractere ao conjunto
temporário {
[ [ ]] }. Retornar
como resultado da função
[
].
For I := 1 To Length(S) Do
R := R + [S[I]];
StrToSet := R;
End;
Observar que a expressão [ [ ]] equivale a um conjunto com o caractere [ ].
A função
monta uma
com os elementos de um conjunto de
. É
importante destacar que conjunto não é array, logo não é possível acessar um elemento
do conjunto utilizando indexação. Assim, a solução deve perguntar para cada um dos
valores possíveis para um char se ele se encontra na string. Em caso positivo este
elemento é adicionado à string resultado. Seguem os detalhes:
a. Inicializar a variável string com vazio: {
};
Function SetToStr (S : TSChar) : String;
Var R : String; C : Char;
Begin
R := '';
b. Percorrer cada caractere [
] possível de pertencer a um
conjunto de char e perguntar se pertence ao conjunto informado [
]. Em
caso afirmativo, concatenar o caractere à string temporária {
}.
Retornar como resultado da função [
].
For C := #0 To #255 Do
If C in S
Then R := R + C;
SetToStr := R;
End;
Introdução à Programação: Conceitos e Práticas.
Página 307
O programa principal, composto pelas seguintes linhas, gerou a saída indicada na
sequência:
Writeln (DelChars ('ola mundo belo', ['a', 'o']));
Writeln (SetToStr(StrToSet('ola mundo belo')));
<l mund bel>
< abdelmnou>
A eliminação das letras
e
da string
produziu a
. A formação de um conjunto com as letras da
produziu o conjunto [
]. Obsevar que o conjunto não
apresenta elementos repetidos e está ordenado.
Introdução à Programação: Conceitos e Práticas.
Página 308
25.
Registro
A qualidade de um software depende de vários fatores que combinados indicam o grau
de adequação do produto. Conforme a finalidade do sistema determinados fatores
apresentam maior ou menor relevância. Alguns fatores de qualidade de software são:
legibilidade, confiabilidade, usabilidade, eficiência, modularidade, dentre outros. A
engenharia de software se ocupa principalmente de estabelecer um conjunto de
técnicas, metodologias e ferramentas que contribuam com a gestão de todo o ciclo de
vida de um software. As linguagens de programação, como parte do ambiente de
desenvolvimento de software, são elementos fundamentais para transformar
especificações e projetos em programas de computador. Neste sentido, as linguagens
devem proporcionar mecanismos de abstração que permitam produzir programas
alinhados com um processo de engenharia de software.
Citamos
anteriormente
que
de
forma
simplificada
a
equação
ilustra os componentes principais de um projeto de
um programa, que deve ter suporte nas linguagens de programação. Também, é forte a
presença da componente abstração no ambiente computacional, onde desempenha
papel essencial no ciclo de refinamento do problema até a sua materialização em um
produto acabado. Desta forma, podemos expressar a seguinte relação:
, reforçando a importância não só apenas
em organizar o código e os algoritmos visando a qualidade, mas de forma idêntica
dedicar esforços para uma boa modelagem dos dados. O exercício que abordou o
problema de emitir um relatório de notas e médias de uma disciplina de uma turma de
um curso demandou algumas variáveis para acomodar as informações requeridas para
a solução. Se estendermos o problema para modelar todo um sistema acadêmico,
certamente chegaríamos a uma quantidade intratável de variáveis para acomodar todas
as informações que um contexto deste exige. Assim, é fundamental que a linguagem
ofereça recursos que proporcione mecanismos de organização de dados, onde seja
possível abstrair novos tipos através do agrupamento de informações de naturezas
distintas e que tenham relação mais natural com a entidade modelada. O primeiro
passo na direção desta melhor organização é o conceito de
, onde um conjunto
de dados correlacionados podem ser estruturados em um novo tipo.
A ampliação do conceito de
ou
dá origem ao
que agrupa dados e rotinas para formarem uma nova entidade mais ampla, cujo
agrupamento esconde informações e comportamentos.
A extensão do conceito de
a fim de permitir um ordenamento
hierárquico destes agrupamentos, bem como proporcionar maior reusabilidade de
código deu origem a visão
.
A seguinte figura esboça um diagrama com os recursos de uma linguagem tipo
organizados por elementos de abstração:
Introdução à Programação: Conceitos e Práticas.
Página 309
Figura 80: Abstrações típicas de uma linguagem procedural
Introdução à Programação: Conceitos e Práticas.
Página 310
Este diagrama destaca que a linguagem proporciona de forma similar recursos voltados
tanto para a codificação da lógica do problema quanto para a modelagem dos dados.
Assim, o programador deve dedicar atenção e tempo às duas vertentes da abstração.
25.1. Sintaxe
As seguintes regras simplificadas24 indicam a sintaxe para uso do tipo
{
Segue um programa que exemplifica o uso de
[ ]
:
}
:
Program ExRECORD;
Type
TPonto = Record
X,
Y,
Z
: Real;
End;
TComplex = Record
Re,
Im : Real;
End;
TData = Record
D,
M,
A : Integer;
End;
TNome = Record
First,
Middle,
Last : String;
End;
TPessoa = Record
Nome : TNome;
Nasc : TData;
End;
Var P, Q
Z
Pessoa
T
24
:
:
:
:
TPonto;
TComplex;
TPessoa;
Record
H, M, S : LongInt;
Não incluída a parte variante.
Introdução à Programação: Conceitos e Práticas.
Página 311
End;
Begin
Readln (P.X, P.Y, P.Z);
Z.Re := P.X + P.Y;
Z.Im := P.Y + P.Z;
Q.X := P.X + 1;
Q.Y := P.Y + 1;
Q.Z := P.Z + 1;
Readln (Pessoa.Nome.First);
Readln (Pessoa.Nome.Middle);
Readln (Pessoa.Nome.Last);
Pessoa.Nasc.D := 10;
Pessoa.Nasc.M := 8;
Pessoa.Nasc.A := 1998;
T.H := 17;
T.M := 34;
T.S := 23;
End.
Neste exemplo são apresentados diversos registros que agregam informações
correlacionadas por algum conceito. Por se caracterizar com um tipo de dado, o
programador pode definir uma variável diretamente como
ou criar um tipo
associado com a nova definição. Esta última abordagem é a preferida por facilitar o
reuso e contribuir com a legibilidade. A variável foi criada qualificando o
na
própria definição do tipo. As demais variáveis ( , , , e
) são de tipos definidos
no bloco
.
O programa principal mostra o uso de variáveis do tipo
bem como a forma de
acesso aos seus campos. A seguinte figura ilustra a definição do tipo
e a
criação das variáveis e .
TPonto
TIPO
VARIÁVEIS
X
Y
Z
P
X
Y
Z
Q
X
Y
Z
O Pascal utiliza a notação
(ponto) para acesso aos campos. Assim, a célula da
variável
é referenciada como
. Da mesma forma podem ser referenciadas as
células
,
,
,
e
.
O seguinte diagrama ilustra o tipo
são registros:
Introdução à Programação: Conceitos e Práticas.
e a variável
cujos campos também
Página 312
Nasc
Nome
TPessoa
TNome
TData
D
Pessoa
M
A
...
...
...
First
Nasc
VARIÁVEL
Nome
TIPO
10
8
1998
J O R
L U I
S I L
D
M
A
G E First
Z
Middle
V A Last
Middle
Last
D
M
A
J O R G E First
Middle
L U I Z
S I L V A Last
A variável
possui dois campos que também são registros, sendo que o seguinte
código tráz referência a estes campos:
Readln (Pessoa.Nome.First);
Readln (Pessoa.Nome.Middle);
Readln (Pessoa.Nome.Last);
Pessoa.Nasc.D := 10;
Pessoa.Nasc.M := 8;
Pessoa.Nasc.A := 1998;
É notória a vantagem do uso de registros para organizar e agrupar informações
correlacionadas entre si. É importante destacar que o conceito de variável se aplica
integralmente aos campos de um registro. A designação de um campo através da
descrição completa do caminho que referencia um endereço de memória constitui-se
uma variável, e pode ser utilizada da mesma forma, tal como compor expressões e
serem passadas como parâmetro. Assim, podemos generalizar o conceito de variável
para englobar as seguintes variações:
Introdução à Programação: Conceitos e Práticas.
Página 313
Tipo de Variáveis
Variável normal25
Variável indexada
Variável identificadora de campo
Exemplos
A, X, Soma
V[I], M[I,J]
Data.Dia, VE[I].Salario
Não há restrições para composição entre variáveis
possível modelar um
,
com campo
,
e
, sendo
, dentre outras.
25.2. Exemplos
i.
Refazer o programa que recebe informações sobre as notas anuais de uma disciplina e
gera um relatório com as médias ponderadas.
Segue o programa proposto:
Program ExMEDIAS;
Const MAXN
MAXNOTAS
Type
TVReal
= 100;
= 10;
= Array[1..MAXNOTAS] Of Real;
TAluno = Record
Nome : String;
End;
TVAluno = Array[1..MAXN] Of TAluno;
TNota = Record
N
: Integer;
NtBim : TVReal;
Media : Real;
End;
TVNota = Array[1..MAXN] Of TNota;
TDisc = Record
Nome
: String;
N
: Integer;
Pesos : TVReal;
End;
TDados =
Disc
Alunos
Notas
25
Record
: TDisc;
: TVAluno;
: TVNota;
“Entire Variable” – [WIRTH, 1973]
Introdução à Programação: Conceitos e Práticas.
Página 314
N
End;
: Integer;
Function FileExists (FN : String) : boolean;
{igual ao exemplo anterior}
End;
Function PadRight (S : String; N : Integer) : String;
{igual ao exemplo anterior}
End;
Procedure LerDados (FN : String; Var Dados : TDados);
Var F : Text;
Procedure LerPesos;
Begin
With Dados.Disc Do Begin
N := 0;
While Not Eoln(F) Do
Begin
Inc (N);
Read (F, Pesos[N]);
End;
Readln (F);
End;
End;
Procedure LerNomesNotas;
Var J : Integer;
Begin
Dados.N := 0;
While Not Eof (F) Do
Begin
Inc (Dados.N);
Readln (F, Dados.Alunos[Dados.N].Nome);
For J := 1 To Dados.Disc.N Do
Readln (F, Dados.Notas[Dados.N].NtBim[J]);
Dados.Notas[Dados.N].N := Dados.Disc.N;
End;
End;
Begin
If FileExists (FN) Then
Begin
Assign (F, FN);
Reset (F);
Introdução à Programação: Conceitos e Práticas.
Página 315
LerPesos;
Readln (F, Dados.Disc.Nome);
LerNomesNotas;
Close (F);
End
Else Writeln ('Arquivo [',FN,'] não existe');
End;
Procedure RelatNotas (FN : String; Dados : TDados);
Var I, J : Integer;
F : Text;
Procedure Cabecalho;
Var J : Integer;
Begin
Writeln (F, 'Disciplina: ', Dados.Disc.Nome);
Writeln (F);
Writeln (F,
'
Aluno
N1
N2
N3
Write
(F, PadRight(' ', 21));
For J := 1 To Dados.Disc.N Do
Write (F, '[',Dados.Disc.Pesos[J]:4:1,']');
Writeln (F);
Writeln (F);
End;
N4
Media');
Begin
Assign (F, FN);
Rewrite (F);
Cabecalho;
For I := 1 To Dados.N Do
Begin
Write (F, Padright(Dados.Alunos[I].Nome,20));
For J := 1 To Dados.Notas[I].N Do
Write (F, Dados.Notas[I].NtBim[J]:6:1);
Writeln (F, Dados.Notas[I].Media:6:1);
End;
Close (F);
End;
Procedure CalcMedia (Var Dados : TDados);
Introdução à Programação: Conceitos e Práticas.
Página 316
Var I, J : Integer; S : Real;
Begin
For I := 1 To Dados.N Do
Begin
S := 0;
For J := 1 To Dados.Disc.N Do
S := S + Dados.Notas[I].NtBim[J]*Dados.Disc.Pesos[J];
Dados.Notas[I].Media := S;
End;
End;
Var X : TDados;
Begin
LerDados
('notas calculo.txt', X);
CalcMedia (X);
RelatNotas ('relat notas rec.txt', X);
End.
Introdução à Programação: Conceitos e Práticas.
Página 317
NOTAÇÃO
Record
Campo 1
Campo 2
Campo 3
Vetor
Vetor[1]
Vetor[2]
TVNota
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
...
N
Alunos
TDisc
Nome
N
Pesos[1]
Pesos[2]
...
Pesos[N]
TDados
Nome
N
Pesos[1]
Pesos[2]
...
Pesos[N]
Nome
Nome
Nome
...
Nome
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
Notas
TVAluno
Nome
Nome
Nome
...
Nome
TNota
N
NtBim[1]
NtBim[2]
...
NtBim[N]
Media
N
TAluno
Nome
Disc
A seguinte figura ilustra a forma com que as informações foram agrupadas em novos
tipos:
Vetor[N]
Introdução à Programação: Conceitos e Práticas.
Página 318
26.
Tipos Ordinais Definidos pelo Usuário
O tipo ordinal definido pelo usuário é um recurso da linguagem que permite aprimorar a
representação de dados através da adição de significado bem como da restrição de
domínio para o elemento modelado. A linguagem Pascal oferece estes conceitos
através de enumerados e subdomínio.
26.1. Enumerados
O tipo
também é classificado como
e
, e é definido como
uma relação de valores representados por identificadores. Desta forma, o procedimento
normal é criar um tipo enumerado na cláusula
associando um nome a uma relação
de identificadores, sendo que cada identificador representa um valor que é a ordem do
identificador no conjunto de enumerados.
Segue um programa que exemplifica o uso de
:
Program ExENUM;
Type TDia = (dom, seg, ter, qua, qui, sex, sab);
Const Dias : Array[dom..sab] of string = ('dom', 'seg', 'ter', 'qua',
'qui', 'sex', 'sab');
Function DiaToStr (D : TDia) : String;
Begin
DiaToStr := Dias[D];
End;
Function StrToDia (S : String) : TDia;
Var d : TDia;
Begin
StrToDia := TDia (-1);
For d := dom To sab Do
If Dias[d] = S Then
Begin
StrToDia := d;
Break;
End;
End;
var Dia : TDia;
begin
Dia := qua;
Writeln (DiaToStr(Dia));
Writeln (Ord (StrToDia('ter')));
Introdução à Programação: Conceitos e Práticas.
Página 319
Dia := Succ(Dia);
Writeln (DiaToStr(Dia));
Dia := Pred(Dia);
Writeln (DiaToStr(Dia));
Dia := StrToDia ('qau');
Writeln (Ord(Dia));
end.
Neste exemplo são apresentados diversos aspectos associados a enumerados. O
problema em questão é a conversão de um valor enumerado representando dia da
semana em uma
e vice-versa. Os seguintes comentários explicam os principais
elementos do programa:
a. Criar o tipo que relaciona os dias da semana:
Type
TDia = (dom, seg, ter, qua, qui, sex, sab);
Foram enumerados os dias da semana e associados ao novo tipo
. É
fundamental compreender que os identificadores não são strings. Não foram
utilizadas apóstrofes para delimitar o identificador. Os elementos do enumerados
são representados na memória por meio do número vinculado à posição do
identificador no enumerado. Assim, o identificador
está vinculado ao valor ,
ao valor e assim por diante. Os valores equivalem ao que retornaria a
função
para estes componentes.
b. Criar a variável que serve de base para a conversão de
para
:
Const
Dias : Array[dom..sab] of string = ('dom', 'seg', 'ter', 'qua',
'qui', 'sex', 'sab');
A cláusula
serve tanto para vinclular constantes com identificadores,
quanto para criar e inicializar uma variável. Assim, foi criada a variável
como um array de strings com índice do tipo ordinal
, sendo
o índice do
primeiro elemento do vetor e
o índice do último elemento. Este
serve
para mapear um índice para uma
. O conteúdo da célula
[
] é a
o que materializa a conversão.
c. Criar a função que mapeia um valor
em uma
equivalente:
Function DiaToStr (D : TDia) : String;
Begin
DiaToStr := Dias[D];
End;
A função
apenas retorna o valor da célula do vetor
passado como parâmetro.
Introdução à Programação: Conceitos e Práticas.
cujo índice é
Página 320
d. Criar a função que mapeia um valor
em um ordinal
equivalente:
Function StrToDia (S : String) : TDia;
Var d : TDia;
Begin
StrToDia := TDia (-1);
For d := dom To sab Do
If Dias[d] = S Then
Begin
StrToDia := d;
Break;
End;
End;
A função
implementa o mapeamento de uma
contendo três
letras que designam o dia da semana para o valor equivalente em
. A lógica
inicia atribuindo ao resultado da função o valor
. Porém, como a atribuição
direta não é possível em virtude da incompatibilidade de tipo entre o
( )
e o resultado da função (
), foi necessário utilizar o
para alterar
o tipo do valor
e permitir que a atribuição [
] seja
aceita.
Em seguida é implementada uma repetição que busca no vetor
pela
informada em . Ao encontrar, o valor da variável de controle contém o índice do
elemento procurado, que por construção, é o resultado procurado pela função.
Cabe destacar que a variável de controle é do tipo
, reforçando a opção que
o programador possui de utilizar qualquer ordinal como variável do
.
e. Criar o programa principal para testar a implementação:
var Dia : TDia;
begin
Dia := qua;
Writeln (DiaToStr(Dia));
Writeln (Ord (StrToDia('ter')));
Dia := Succ(Dia);
Writeln (DiaToStr(Dia));
Dia := Pred(Dia);
Writeln (DiaToStr(Dia));
Dia := StrToDia ('qau');
Writeln (Ord(Dia));
end.
O programa principal serve para ilustrar o uso dos recursos disponíveis para o
tipo enumerado e para testar as funções codificadas. A linguagem não permite
escrever valores enumerados na tela ou em arquivo texto, o que demanda a
necessidade de uma função que converta (
) elementos desta natureza
para string, podendo este ser escrito na tela. A legibilidade é um dos efeitos
Introdução à Programação: Conceitos e Práticas.
Página 321
positivos do uso de enumerados, pois auxilia no entendimento do programa. A
atribuição
é mais facilmente compreendida do que uma do tipo
, e sem perda de eficiência, pois na compilação as duas formas são
equivalentes.
É muito comum no caso de inteiros expressões do tipo
, ou mesmo
, que não podem ser estendidos para qualquer ordinal. Neste caso foram
utilizadas as funções
e
que retornam o próximo elemento e o elemento
anterior de um valor ordinal, inclusive enumerados. Estas funções se aplicam
também para inteiros, como em
. O uso de
e
para o último
elemento e o primeiro elemento do enumerado leva a erro de domínio, e
dependendo das configurações ajustadas para a compilação a inclusão de
código para a detecção deste tipo de erro pode ser desabilitada26.
Na linha de código
é utilizado um argumento para
que não possui equivalente no tipo
e cujo resultado esperado é
. A linha seguinte
confirma esta expectativa.
O uso conveniente de enumerados melhora a confiabilidade do programa ao
inibir construções que tentem atribuir valores que não pertençam a relação
definida para o enumerado. Se na codificação deste problema fosse utilizado
inteiro para representar um dia da semana, então uma atribuição do tipo
não seria inibida pela compilação, e erros decorrentes desta linha só
seriam percebidos na execução do programa.
A execução deste programa principal produz a saída indicada na sequência:
qua
2
qui
qua
-1
26.2. Subdomínio
O tipo
consiste na especialização de um tipo
, limitando os
dados aceitos a uma faixa contínua de valores e permitindo as mesmas operações
válidas para este tipo base. Os seguintes exemplos ilustram a forma de uso:
Nestes exemplos, são definidos dois novos tipos, sendo o tipo
baseado no tipo
, porém limitando o domínio de valores a faixa de
, enquanto que o tipo
tem como base o tipo
e a faixa especificada para
. As vantagens
26
Compiladores Borland e Free Pascal permitem incluir {$R+} ou não {$R+} código para verificação de erro de
domínio (Range Check Error).
Introdução à Programação: Conceitos e Práticas.
Página 322
na utilização deste recurso são principalmente legibilidade e confiabilidade (erro de
domínio).
Segue um programa que exemplifica o uso de
:
Program ExSUBDOM;
Type TDiaMes = 1..31;
TMes
= 1..12;
{$R+}
Function IsLeap (A : Integer) : Boolean;
Begin
IsLeap := (A Mod 4 = 0) And
((A Mod 100 <> 0) Or (A Mod 400 = 0));
End;
Function NumberOfDays (M : TMes; A : Integer) : TDiaMes;
Begin
If M in [1, 3, 5, 7, 8, 10, 12] Then
NumberOfDays := 31
Else If M in [4, 6, 9, 11] Then
NumberOfDays := 30
Else If (M = 2) Then
NumberOfDays := 28 + Ord(IsLeap (A))
Else
NumberOfDays := 0;
End;
Begin
Writeln
Writeln
Writeln
Writeln
Writeln
Writeln
End.
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
(NumberOfDays
( 2,
( 1,
( 2,
(12,
( 2,
(15,
2000));
1996));
1996));
1600));
2013));
2000));
Este programa é uma adaptação da implementação anterior, onde foram incorporados
os recursos de
e
. As variáveis, parâmetros e retorno de função
deixaram de ser do tipo genérico
e foram redefinidos para os tipos
e
. A expressão lógica que testa meses de
ou
dias utiliza
operação com conjuntos, como em:
[
].
Introdução à Programação: Conceitos e Práticas.
Página 323
Ao compilar este programa com o
e com a diretiva de verificação de erro
de domínio habilitada {
}, são identificados dois erros nas linhas destacadas27. O
erro em
ocorre pela atribuição de ao resultado da função que
está definido como
(fora da faixa). Na expressão
que invoca a função
, o compilador identifica
o argumento
como sendo incompatível (fora da faixa) com o parâmetro
que está
definido como
. Caso a diretiva de compilação seja definida como {
} este
mesmo programa irá compilar normalmente.
27
Erros:
– subdominio.pas(23,22) Error: range check error while evaluating constants
– subdominio.pas(33,28) Error: range check error while evaluating constants
Introdução à Programação: Conceitos e Práticas.
Página 324
27.
Expressões Binárias
As expressões binárias são recursos da linguagem que permitem manipular os
da
representação de um número inteiro. Algumas aplicações que envolvem aquisição de
dados, programação em baixo nível para sistemas operacionais, drivers, protocolos de
comunicação, criptografia e computação gráfica exigem frequentemente lógicas que
operem diretamente sobre os bits de um número. Além disso, determinadas operações
matemáticas envolvendo multiplicação ou divisão são mais eficientemente
implementadas utilizando operações binárias (
).
Na sequência são apresentados os operadores binários e de deslocamento de bits.
27.1. Operadores Binários
Os operadores binários são equivalentes aos operadores lógicos, porém aplicáveis
aos
da representação de um inteiro. Os operadores e as tabelas verdade
são as mesmas apresentadas no
, que em resumo são:
AND
0
1
OR
0
1
XOR
0
1
0
0
0
0
0
1
0
0
1
1
0
1
1
1
1
1
1
0
A
0
0
1
1
AND
B
0
1
0
1
A
0
0
1
1
OR
B
0
1
0
1
A
0
0
1
1
XOR
B
0
1
0
1
X
0
0
0
1
X
0
1
1
1
NOT
0
1
1
0
NOT
A
X
0
1
1
0
X
0
1
1
0
Abaixo das tabelas estão indicadas as formas de uso dos operadores
,
,
. O seguinte quadro ilustra uma expressão com o operador
e o efeito nos
Binário
1 1 1 0 0 1 1 0
0 0 1 1 1 0 1 1
0 0 1 0 0 0 1 0
Introdução à Programação: Conceitos e Práticas.
Hexa
$E6
$3B
$22
e
:
Decimal
230
59
34
Página 325
A expressão
com
e
produz um resultado em
que é a
aplicação da operação
bit a bit na representação binária de
e . Neste caso,
considera-se que
e foram declarados como sendo do tipo
, que equivale a
inteiro sem sinal com
.
Este outro exemplo ilustra a operação
que equivale a inteiro com sinal com
envolvendo operandos do tipo
,
:
Binário
1 1 1 1 1 1 1 1
0 0 1 1 1 0 1 1
0 0 1 1 1 0 1 0
Hexa
$FF
$3B
$2A
Decimal
255
59
42
Os inteiros com sinal são codificados em binário utilizando a notação em
. Logo, ao atribuir o valor
para a variável a codificação binária
resultante é
.
Uma análise na tabela verdade destaca que o operador
é adequado para zerar
(
) determinados bits de uma palavra. O operador
é aplicado nos casos em que
se deseja ligar ( ) bits de uma palavra. O operador
é mais indicado quando é
necessário inverter (
) determinados
, enquanto que o operador
é útil
para inverter todos os bits de uma representação.
27.2. Operadores de Deslocamento de Bits
A manipulação de
se completa com os operadores que executam a movimentação
dos bits para a esquerda ou para a direita.
O operador
(
) desloca os bits de um inteiro para a esquerda,
acrescentando zeros a direita. O seguinte diagrama ilustra esta operação para o
deslocamento de
a esquerda em um inteiro de
.
Tabela 3: Operador Shift Left
0
Introdução à Programação: Conceitos e Práticas.
Página 326
O efeito numérico que a operação
produz em um inteiro sem sinal é equivalente a
operação matemática de multiplicação por , onde é o número de
deslocados.
Se
e
, teremos então:
0
O valor de é
que equivale ao decimal
, ou ao valor de
. Os compiladores procuram otimizar o código, e sempre que possível traduzem
expressões do tipo
por
.
Um segundo operador é o
(
), que desloca os bits de um inteiro para a
direita, acrescentando zeros à esquerda. O seguinte diagrama ilustra esta operação
para o deslocamento de
a direita em um inteiro de
.
0
O efeito numérico que a operação
produz em um inteiro sem sinal é equivalente a
operação matemática de divisão de inteiro por
, onde
é o número de bits
deslocados. Se
e
, teremos então:
0
O valor de
é
que equivale ao decimal , ou ao valor de
. Os compiladores procuram otimizar o código, e sempre que possível
Introdução à Programação: Conceitos e Práticas.
Página 327
traduzem expressões do tipo
por
perdidos equivalem matematicamente ao valor de
. Observar que os
.
Na sequência serão apresentados exemplos que ilustram as aplicações com operações
binárias.
27.3. Exemplos
i.
Elaborar um programa que efetue as seguintes lógicas28:
a. Ligar o
da posição de um inteiro .
⋯
b. Zerar o
⋯
⋯
da posição de um inteiro .
⋯
c. Substituir o
⋯
da posição de um inteiro
⋯
f.
Girar os
g. Girar os
⋯

⋯
e. Testar se o
⋯
⋯ ⋯

d. Inverter o valor do
⋯
⋯ ⋯

menos significativo de .
⋯
da posição de um inteiro .
⋯ ̅̅̅ ⋯

da posição de um inteiro
⋯
pelo

está ligado.
⋯ ⋯
de , posições para a esquerda.
de , posições para a direita.
Segue o programa proposto:
Program ExBITWISE;
function dectobin (x, n : longint) : string;
Var S : String;
begin
S := '';
while x <> 0 do
begin
28
http://bits.stephan-brumme.com/
Introdução à Programação: Conceitos e Práticas.
Página 328
S := chr (ord('0') + x and 1) + S;
x := x shr 1;
end;
while length(s) < n do
S := '0' + S;
dectobin := S;
end;
function
Var mask
begin
mask
SetBit
end;
SetBit (x, t : longint) : longint;
: longint;
:= 1 shl t;
:= x or mask;
function ClearBit (x, t : longint) : longint;
Var mask : longint;
begin
mask
:= 1 shl t;
ClearBit := x and (not mask);
end;
function ModifyBit (x, t, r : longint) : longint;
Var mask : longint;
begin
mask
:= 1 shl t;
ModifyBit := (x and (not mask)) Or
((r shl t) and mask);
end;
function FlipBit (x, t : longint) : longint;
Var mask : longint;
begin
mask
:= 1 shl t;
FlipBit := x xor mask;
end;
function isBitSet (x, t : longint) : boolean;
begin
x := x shr t;
isBitSet := (x and 1) = 0;
end;
function rol (x, t : longint) : longint;
var s : longint;
begin
s := (sizeof (x) shl 3) - t;
rol := (x shl t) or (x shr s);
Introdução à Programação: Conceitos e Práticas.
Página 329
end;
function ror (x, t : longint) : longint;
var s : longint;
begin
s := (sizeof (x) shl 3) - t;
ror := (x shl s) or (x shr t);
end;
Var XL : longint;
Begin
XL := 0;
Writeln (dectobin(XL, 32));
XL := SetBit (XL, 3);
XL := SetBit (XL, 5);
XL := SetBit (XL, 31);
Writeln (dectobin (XL, 32));
XL := ClearBit (XL, 5);
Writeln (dectobin (XL, 32));
XL := ModifyBit (XL, 5, 1);
XL := ModifyBit (XL, 6, 1);
Writeln (dectobin (XL, 32));
XL := FlipBit (XL, 31);
Writeln (dectobin (XL, 32));
XL := FlipBit (XL, 31);
Writeln (dectobin (XL, 32));
XL := rol (XL, 5);
Writeln (dectobin (XL, 32));
XL := ror (XL, 5);
Writeln (dectobin (XL, 32));
End.
A fim de visualizar os efeitos das operações sobre os
de um inteiro optou-se em
mostrar na tela o equivalente binário da variável utilizada como teste. A função que
converte um inteiro para binário foi adaptada em relação a versão já apresentada
anteriormente. A seguinte tabela compara as duas versões:
Function DecToBin (X : Integer) :
String;
Var S : String;
Begin
S := '';
While X <> 0 Do
Introdução à Programação: Conceitos e Práticas.
function DecToBin (x, n : longint) :
string;
Var S : String;
Begin
S := '';
While x <> 0 do
Página 330
Begin
If X Mod 2 = 0
Then S := '0' + S
Else S := '1' + S;
X := X Div 2;
End;
Begin
S := chr (ord('0') + x And 1) + S;
x := x shr 1;
End;
While Length(S) < N do
S := '0' + S;
DecToBin := S;
End;
DecToBin := S;
end;
A versão implementada para este exemplo necessita dois parâmetros, sendo o inteiro
a ser convertido e
a quantidade de dígitos na formatação da
resultado. Esta
formatação é recomendada, pois facilita a visualização e comparação dos
.
A primeira diferença que se observa é que esta versão não utiliza
e
para obter
os dígitos binários. A lógica empregada isola o
menos significativo através da
expressão
. A constante deve ser vista na forma representada em binário com
tamanho estendido para o mesmo tamanho de . Assim, o resultado desta expressão
será
⋯
ou
⋯ . Após o tratamento do
menos significativo, a linha
atualiza o valor de com o deslocamento de todos os
uma posição a
direita, cujo efeito é a eliminação do
menos significativo. Esta lógica é repetida
enquanto o valor de
é diferente de zero. A expressão
retorna o caractere que se encontra na posição dada por
somado ou , que
resulta no caractere
ou .
Em seguida vem a lógica que ajusta a
para ficar com comprimento ,
efetuando a concatenação de zeros à esquerda. Esta construção se assemelha à
utilizada na função
, e poderia ser codificada como rotina separada.
Na sequência são comentadas algumas das funções de manipulação de bits:
a. Ligar o
da posição de um inteiro .
⋯
⋯

⋯ ⋯
Para ligar um determinado bit de um inteiro faz-se uso de uma propriedade do
operador
em que
, para qualquer valor do bit e
. Assim,
deve ser montada uma máscara que tenha
na posição e
nas demais. A
operação
desta máscra com o número dado resulta no bit desejado com valor e
os demais inalterados. Segue o código da função:
function
Var mask
begin
mask
SetBit
SetBit (x, t : longint) : longint;
: longint;
:= 1 shl t;
:= x or mask;
Introdução à Programação: Conceitos e Práticas.
Página 331
end;
A máscara com o bit na posição é obtida efetuando um deslocamento à esquerda
de posições no inteiro
⋯ . Como sabemos que o decimal 1 é representado
em binário e estendido para equiparar ao tamanho da variável destino
, então a
operação
produzirá a máscara desejada. Em seguida, a expressão
resultará em um valor que é um inteiro com todos os bits iguais aos bits de com
exceção do bit da posição que será forçosamente .
As funções
e
c. Substituir o
⋯
⋯
seguem o mesmo princípio.
da posição de um inteiro

⋯
pelo bit menos significativo de .
⋯
Neste problema, tem-se um com seus bits
⋯ ⋯
, um com seus
bits
⋯
e um número . A combinação destes dados produzirá
⋯ ⋯
, onde o bit de deverá ser substituído pelo bit de .
A seguinte rotina codifica esta lógica:
function ModifyBit (x, t, r : longint) : longint;
Var mask : longint;
begin
mask
:= 1 shl t;
ModifyBit := (x and (not mask)) Or
((r shl t) and mask);
end;
O quadro que segue ilustra o passo a passo das principais transformações feitas
com os bits bem como as combinações necessárias para produzir o resultado
desejado. A leitura do quadro deve se dar de cima para o meio e de baixo para o
meio, onde então se posiciona a sequência de bits com o resultado da função.
t
Introdução à Programação: Conceitos e Práticas.
Página 332
f.
Girar os
de , posições para a esquerda.
Esta funcionalidade é muito comum na linguagem
da maioria das
arquiteturas. Neste problema, tem-se um com seus bits
⋯
e um número que indica quantos bits devem girados para a esquerda. Não há
perda de bits, pois os bits que saem pela direita servem de preenchimento pela
esquerda. Assim, supondo
, então a rotação de
posições produziria
⋯
.
Ao desmembrar a sequência
⋯
chega-se a duas
sequências abaixo indicadas que podem ser obtidas por deslocamento de bits e
unidas pela operação
para produzir o giro solicitado:
⋯
⋯
⋯
Generalizando para quaisquer bits tem-se
. Ainda é
possível parametrizar o número , uma vez que representa a quantidade de bits do
valor a ser rotacionado. A função
fornece a quantidade de bytes destinada
para , que multiplicado por fornece a quantidade de bits. Esta multiplicação por
foi substituída pela operação
que matematicamente equivale a
multiplicar por . Segue a codificação da função
:
function rol (x, t : longint) : longint;
var s : longint;
begin
s := (sizeof (x) shl 3) - t;
rol := (x shl t) or (x shr s);
end;
A rotação para a direita tem lógica equivalente.
O quadro abaixo apresenta tanto a saída resultante da execução do programa principal
quanto os comentários passo a passo sobre as alterações sofridas pelos bits:
00000000000000000000000000000000
10000000000000000000000000101000
10000000000000000000000000001000
10000000000000000000000001101000
00000000000000000000000001101000
10000000000000000000000001101000
00000000000000000000110100010000
10000000000000000000000001101000
Introdução à Programação: Conceitos e Práticas.
XL := 0;
set bits 3, 5 e 31
clear bit 5
modify bits 5 e 6 para 1
flip bit 31
flip bit 31
rotate left 5 bits
rotate right 5 bits
Página 333
28.
Ponteiros
O conceito de ponteiro é bastante simples e está associado a um tipo de dado que
permite criar variáveis destinadas a guardar um número cujo significado é um endereço
de memória, conforme ilustra a seguinte figura:
Variável
Endereço
X
-1
$00409000
Y
32
$00409004
Z
-250
$00409008
P
$00409004
$0040900C
Este diagrama ilustra três variáveis quaisquer ,
e
ocupando determinados
endereços de memória, e a variável
do tipo ponteiro ocupando o endereço
e cuja célula contém o valor
que é uma referência a uma
posição de memória.
Apesar da simplicidade do conceito, ponteiros são essenciais para a construção de
estruturas de dados dinâmicas, tais como lista encadeada, árvores e grafos. Variáveis
ponteiros são invariavelmente vinculadas a alocação dinâmica, que consiste na reserva
e liberação de memória conforme a necessidade do problema.
28.1. Sintaxe
A declaração de variáveis ponteiros tem a seguinte sintaxe:
O símbolo utilizado em Pascal para denotar ponteiros é
a declaração de variável ponteiro:
. O seguinte programa ilustra
Var X, Y, Z : LongInt;
P : ^LongInt;
Begin
X := -1;
Introdução à Programação: Conceitos e Práticas.
Página 334
Y := 32;
Z := -250;
P := @Y;
End.
Da mesma forma, uma variável de tipo ponteiro tem conteúdo incerto até que se atribua
um valor válido. A declaração
faz com que seja reservada memória para
acomodar única e exclusivamente a variável . Na arquitetura
um ponteiro
ocupa
ou
de memória.
28.2. Operação com Ponteiros
As operações típicas com variável ponteiro são: atribuição de um endereço de memória
e a referência à célula apontada. Variável ponteiro pode ser inicializada com um valor
especial, identificado como
, que equivale ao zero para inteiros. Assim, o comando
atribui um valor conhecido para
o que permite maior controle sobre as
operações com este ponteiro.
No exemplo anterior foi utilizada uma expressão para inicializar com o endereço da
variável . O endereço de memória associado com uma variável, procedure ou function
pode ser obtido com o operador
ou com a função
. Assim, a expressão
ou
retornam o endereço de memória da variável . Agora, a variável ,
declarada como ponteiro para
, contém um endereço válido de células
associadas a um
. A seguinte figura ilustra a notação comum para mostrar o
vínculo de uma variável ponteiro com um endereço de memória. A leitura que se faz é
que a variável ponteiro contém o endereço da célula indicada pela seta.
Y
32
P
Uma variável de tipo ponteiro com conteúdo
seguintes notações:
é normalmente ilustrada em uma das
P
P
Introdução à Programação: Conceitos e Práticas.
Página 335
A segunda operação com ponteiros é o acesso à área apontada cuja denominação é
. Esta referência é feita com a variável ponteiro seguida do símbolo ,
o que produz
. Assim, no exemplo anterior a célula associada ao endereço
pode ser acessada de duas formas distintas, sendo uma de modo
convencional através da variável e outra através de por meio do
.
P^
32
LongInt
Var P : ^LongInt;
P
Ponteiro
Esta figura reforça o conceito e diferencia a variável do tipo ponteiro ( ) e o conteúdo
da área por ela apontada
O deferenciamento
é do tipo
e pode ser
entendido como se fosse uma variável escalar normal, também denominada
. Assim, podemos completar a tabela apresentada anteriormente,
e acrescentar mais esta forma de designar uma célula de memória:
Tipo de Variáveis
Variável normal
Variável indexada
Variável identificadora de campo
Variável referenciada
Exemplos
A, X, Soma
V[I], M[I,J]
Data.Dia, VE[I].Salario
P^, Q^.Next^, T[1]^.pnome^
O Pascal padrão considera apenas estas duas operações com ponteiro, atribuição e
, porém os dialetos disponíveis, tal como
, estendem as
possibilidades e incorporam vários dos recursos típicos da
. Nos exemplos
que seguem serão construídos programas que ilustram várias operações com ponteiro.
28.3. Exemplos
i.
Adaptar, utilizando ponteiros, as lógicas que calcula a soma dos elementos de um vetor
e obtem o maior elemento:
Segue o programa proposto:
Program ExPTR;
Const MAX = 100;
Type TVReal = Array[1..MAX] Of Real;
TPReal = ^Real;
Introdução à Programação: Conceitos e Práticas.
Página 336
Procedure LerDados (FN : String; Var V : TVReal; Var N : Integer);
{igual aos exemplos anteriores}
End;
Procedure MostrarVet (V : TVReal; N : Integer);
{igual aos exemplos anteriores}
End;
Function GetMaior (V : TVReal; N : Integer) : Real;
Var I : Integer;
M,
P : TPReal;
Begin
M := @V[1];
P := @V[2];
While P <= @V[N] Do
Begin
If P^ > M^
Then M := P;
Inc(P);
End;
GetMaior := M^;
End;
Function GetSoma (V : TVReal; N : Integer) : Real;
Var S : Real;
P : TPReal;
Begin
S := 0;
P := @V[1];
While P <= @V[N] Do
Begin
S := S + P^;
Inc(P);
End;
GetSoma := S;
End;
Var VR
NR
Soma
Maior
:
:
:
:
TVReal;
Integer;
Real;
Real;
Begin
LerDados
('pesos.txt', VR, NR);
MostrarVet (VR, NR);
Soma := GetSoma (VR, NR);
Writeln
('Soma = ', Soma:8:3);
Maior := GetMaior (VR, NR);
Writeln
('Maior = ', Maior:8:3);
Introdução à Programação: Conceitos e Práticas.
Página 337
End.
A procedure
já foi explicada e serve para inicializar um vetor de números reais
com dados que estão gravados em arquivo, enquanto que
apresenta os
dados de um vetor na tela.
a) A função
de ponteiros.
teve sua lógica implementada para fazer o maior uso possível
A estrutura da lógica está baseada em uma variável ponteiro utilizada para
percorrer cada elemento do vetor. O seguinte diagrama ilustra o uso deste
ponteiro.
V
[1]
[2]
[3]
[4]
P
[N]
[MAX]
Inicialmente a variável é declarada como ponteiro para o tipo
que por conveniência foi definido um novo tipo
.
. Observe
Function GetSoma (V : TVReal; N : Integer) : Real;
Var S : Real;
P : TPReal;
Begin
A variável
é utilizada para acumular a soma dos valores de
e, portanto
inicializada com . A variável ponteiro
é inicializada com o endereço do
primeiro elemento de
[ ] . No momento em que foi executado este
programa,
é inicializado com o valor decimal
, que é o endereço de
[ ]
S := 0;
P := @V[1];
Na sequência a repetição para percorrer os elementos de utiliza o
em
vez do
, para explorar mais o conceito de ponteiro. Assim, a cada ciclo do
o conteúdo de é atualizado para receber o endereço do próximo elemento
Introdução à Programação: Conceitos e Práticas.
Página 338
do vetor. Isto é obtido fazendo um incremento em . Neste caso, o incremento no
conteúdo de uma variável ponteiro é entendido como adicionar um número que
expressa o tamanho da célula. Desta forma, como foi declarado como ponteiro
para
, o incremento de significa incremento de uma célula
, ou seja de
para esta arquitetura. Assim, a repetição é executada até que contenha
um endereço além do limite final do vetor .
While P <= @V[N] Do
Begin
S := S + P^;
Inc(P);
End;
GetSoma := S;
End;
Os valores que a variável
assume a cada ciclo são {
} A
diferença entre dois valores consecutivos é de oito unidades. Antes de fazer
avançar para o próximo elemento, o conteúdo da célula por apontada
é
acumulada em
b) A função
também teve sua lógica implementada para fazer o maior uso
possível de ponteiros.
A estrutura da lógica é semelhante a função
, onde uma variável
ponteiro é utilizada para percorrer cada elemento do vetor e a variável ,
também ponteiro, vai sendo atualizada com o endereço do maior elemento.
Inicialmente as variáveis e M são declaradas como ponteiro para o tipo
.
Function GetMaior (V : TVReal; N : Integer) : Real;
Var I : Integer;
M,
P : TPReal;
A variável ponteiro é utilizada para acomodar o endereço do maior elemento e
é inicializada com o endereço do primeiro elemento de V
[ ] A
variável ponteiro
é inicializada com o endereço do segundo elemento de
[ ] .
Begin
M := @V[1];
P := @V[2];
Na sequência a repetição para percorrer os elementos de
utiliza a mesma
estrutura da função
. O tratamento dado a cada elemento no interior do
é testar se o conteúdo apontado por é maior que o conteúdo apontado por
. Em caso positivo a variável recebe o conteúdo de , que é o
endereço do elemento do vetor naquele ciclo
.
Introdução à Programação: Conceitos e Práticas.
Página 339
While P <= @V[N] Do
Begin
If P^ > M^
Then M := P;
Inc(P);
End;
GetMaior := M^;
End;
O diagrama apresentado abaixo ilustra o comportamento de
ao longo da
repetição. Para melhorar a legibilidade foram omitidos os passos para a variável
, cujo comportamento é semelhante ao descrito anteriormente, porém iniciando
com o endereço do segundo elemento de . A variável vai assumindo, quando
necessário, o endereço do maior elemento até aquele momento da execução. Ao
encerrar a repetição, o conteúdo de
é o endereço do elemento de com o
maior valor. A função retorna ao final o valor da célula apontada por
.
V
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
75.60
67.20
87.60
56.90
54.30
99.80
101.60
77.40
69.75
...
M
[MAX]
O quadro abaixo apresenta a saída resultante da execução do programa:
V[ 1]
V[ 2]
V[ 3]
V[ 4]
V[ 5]
V[ 6]
V[ 7]
V[ 8]
V[ 9]
Soma
Maior
=
=
=
=
=
=
=
=
=
=
=
Introdução à Programação: Conceitos e Práticas.
75.600
67.200
87.600
56.900
54.300
99.800
101.600
77.400
69.750
690.150
101.600
Página 340
ii.
Elaborar um programa que procure pelas primeiras ocorrências de um texto em um vetor
de
e retorne os endereços das
que contém o texto procurado e o
endereço do primeiro caractere dentro da
.
O programa deverá ser alimentado a partir de um arquivo texto com uma relação de
nomes. O processamento deverá pesquisar por um texto e informar os nomes que o
contém e a posição inicial deste texto dentro do nome. As estruturas de dados de apoio
criadas para representar este problema são:
TPChar = ^Char;
l
TPString = ^String;
l
TRPos = Record
PS
: TPString;
l
PS
PC
: TPChar;
l
PC
End;
A relação de nomes será armazenada em um estrutura do tipo vetor de
[
]
, enquanto que o resultado da pesquisa de um
texto neste vetor será armazenado em um
com as informações de cada busca
bem sucedida
[
]
. O que se deseja armazenar para o
acerto é um record
com o endereço da string
) que contém a
palavra pesquisa e o endereço do primeiro caractere
que coincide. A
figura após o código fonte ilustra um caso exemplo.
Segue o programa proposto:
Program ExSEARCH;
Const MAX = 100;
Type TVString = Array[1..MAX] Of String;
TPChar
= ^Char;
TPString = ^String;
TRPos = Record
PS : TPString;
PC : TPChar;
End;
TVRPos = Array[1..MAX] Of TRPos;
Introdução à Programação: Conceitos e Práticas.
Página 341
Procedure LoadTXT (FN : String; Var V : TVString; Var N : LongInt);
Var F : TEXT;
P : TPString;
Begin
Assign (F, FN);
Reset (F);
P := @V[1];
N := LongInt(P);
While Not Eof(F) Do
Begin
Readln (F, P^);
Inc (P);
End;
N := (LongInt(P) - N) div sizeof(String);
Close (F);
End;
Procedure Buscar (S : String; V : TVString; N : LongInt;
Var VX : TVRPos; Var NX : LongInt);
Var I, T : LongInt;
Begin
NX := 0;
For I := 1 To N Do
Begin
T := Pos (S, V[I]);
If T <> 0 Then
Begin
Inc (NX);
VX[NX].PS := @V[I];
VX[NX].PC := @V[I] + T;
End;
End;
End;
Procedure Mostrar (VX : TVRPos; NX : LongInt);
Var I : LongInt;
Begin
For I := 1 To NX Do
Writeln (VX[I].PS^, ' [', LongInt(VX[I].PC) –
LongInt(VX[I].PS),']');
End;
Var VS : TVString;
VP : TVRPos;
NS, NP : LongInt;
Begin
LoadTXT ('nomes.txt', VS, NS);
Buscar ('Santos', VS, NS, VP, NP);
Mostrar (VP, NP);
Introdução à Programação: Conceitos e Práticas.
Página 342
End.
O seguinte diagrama ilustra a estrutura de memória para este problema:
VS
Adair Pereira
Adalto Cardoso
Afonso Vargas
Alexandre Teixeira
Andrea Conti Santos
Antonio Barbara
Carlos Galhardo
Carlos Pedreira
Cristian Mendes
VP
PS
Deodato Fonseca
PC
Dirceu Carrera
PS
Eduarda Valente
PC
Elisa Andreato
PS
Emerson Santos Muniz
PC
Everton Moreira
PS
Fernanda Madeira
PC
Fernando Videira
George Salgueiro
Giovani Carli
Inacio Castilho
Jose de Oliveira
Jose Simoes dos Santos
Josue Ribeiro
Justino Roman
Leona Mattos
Maria dos Santos
Mario Valdivino
Pedro Antunes
Roberto Diniz
Romana Peres
Introdução à Programação: Conceitos e Práticas.
Página 343
A variável
armazena as linhas contidas no arquivo texto e o vetor
é um
de
, onde cada
contém dois campos, sendo um deles ponteiro para uma
e o outro campo um ponteiro para o primeiro caractere da palavra pesquisada. A
variável
é populada pela rotina
e a variável
junto com as conexões
indicadas são tratadas pela rotina
.
a) A procedure
realiza a leitura das informações contidas em um arquivo
texto para um vetor de
. A lógica clássica foi adaptada para ilustrar o
conceito de ponteiros.
Inicialmente a variável
é declarada como ponteiro para
por conveniência foi definido um novo tipo
é aberto para leitura.
. Observe que
. O arquivo texto
Procedure LoadTXT (FN : String; Var V : TVString;
Var N : LongInt);
Var F : TEXT;
P : TPString;
Begin
Assign (F, FN);
Reset (F);
A variável é iniciada com o endereço da célula [ ] (
[ ]), ou seja,
aponta para [ ]. O parâmetro , que conterá a quantidade de linhas lidas, é
obtido através de operações com endereços. Inicialmente
recebe o endereço
contido em , porém convertido para inteiro. Observe o
para
permitir a atribuição
.
P := @V[1];
N := LongInt(P);
A lógica de leitura dos dados do arquivo para a memória inclui uma repetição
enquanto o fim de arquivo não for detectado. É lida uma linha inteira do arquivo
para a célula
. Em seguida é atualizado para conter o endereço da próxima
célula
).
While Not Eof(F) Do
Begin
Readln (F, P^);
Inc (P);
End;
Ao final da leitura de todo o arquivo, a variável conterá o endereço da célula
após a última. Neste momento ainda contém o endereço da primeira célula. A
quantidade de elementos do array pode ser calculadoa pela diferença entre estes
endereços, divido pelo tamanho de cada célula. Em seguida o arquivo é
liberado.
Introdução à Programação: Conceitos e Práticas.
Página 344
N := (LongInt(P) - N) div sizeof(String);
Close (F);
End;
b) A
realiza a pesquisa no vetor de nomes pelas ocorrências de
um determinado texto e vai preenchendo o vetor de resultados com os endereços
relacionados com as linhas que contém o texto pesquisado.
O parâmetro
sucedida por
é iniciado com zero e será incrementado a cada busca bem
em [ ].
Procedure Buscar (S : String; V : TVString; N : LongInt;
Var VX : TVRPos; Var NX : LongInt);
Var I, T : LongInt;
Begin
NX := 0;
É realizada uma repetição para cada linha do vetor de nomes. Em cada ciclo é
testado se o texto de referência está contido no nome. Em caso positivo,
é
incrementado, e os campos de
[ ] são preenchidos com o resultado da
pesquisa. A atribuição
[ ]
[ ] armazena no campo
o valor do
endereço da
em [ ], enquanto que
[ ]
[ ]
armazena
em
o endereço do primeiro caractere com a palavra pesquisada. Este
endereço é dado pela soma do endereço do início da
acrescido da
posição do primeiro caractere do texto coincidente.
For I := 1 To N Do
Begin
T := Pos (S, V[I]);
If T <> 0 Then
Begin
Inc (NX);
VX[NX].PS := @V[I];
VX[NX].PC := @V[I] + T;
End;
End;
End;
O quadro abaixo apresenta a saída resultante da execução do programa, onde é feita a
seguinte pesquisa:
:
Andrea Conti Santos [14]
Emerson Santos Muniz [9]
Jose Simoes dos Santos [17]
Maria dos Santos [11]
Introdução à Programação: Conceitos e Práticas.
Página 345
29.
Estrutura de dados dinâmica
A seção anterior abordou o conceito e algumas aplicações de ponteiros, porém sempre
referenciando memória alocada pela linguagem. É importante compreender a estrutura
de memória de um programa em execução a fim de entender adequadamente a
manipulação de endereços e ponteiros, e consequentemente visualizar o suporte
computacional para as estruturas de dados dinâmicas.
29.1. Organização da memória de um programa em execução
A compilação de um programa fonte (ver Figura 43: Processo de Tradução) produz um
módulo objeto com o seu conteúdo refletindo em forma binária as instruções
codificadas em linguagem de alto nível. O módulo objeto e demais módulos da
biblioteca são ligados para produzir o módulo executável final. Enfim, é possível
processar este arquivo executável no ambiente computacional gerenciado pelo
. Neste momento o arquivo executável é interpretado pelo
e carregado para a memória onde adquire uma nova estrutura, a saber:
a) As variáveis globais são agrupadas em uma área de memória denominada
. De forma geral neste segmento residem as variáveis estáticas,
aquelas que têm o seu espaço de memória reservado no momento da carga do
executável e ficam ligadas a esta memória até o fim do programa.
b) Os bytes que representam as instruções codificadas ficam residentes em uma área
designada como
. São estes
que fluem para a
para serem interpretados e processados formando assim o ciclo de execução das
instruções.
c) Uma terceira região de memória, denominada
, é destinada à
suportar as chamadas de sub-programas (funções e procedures) acomodando de forma
temporária os dados necessários a execução destas rotinas, tais como: parâmetros,
endereço de retorno, variáveis locais (semi-dinâmicas), resultado da função, link estático
e link dinâmico. Este agrupamento de dados é denominado de
, e cada chamada de rotina demanda o empilhamento de um
. Assim, uma
variável local fica ligada a um espaço de memória apenas enquanto a rotina na qual ela
foi declarada estiver ativa.
d) O programa dispõe ainda, de uma área extra de memória, chamada
, destinada a
alocação dinâmica de dados, onde o momento de reserva de espaço de memória e o
momento de liberação deste espaço são definidos pelo programador através de
comandos explícitos para tais fins.
O quadro a seguir ilustra um programa exemplo bem como suas partes distribuídas
pelos diversos segmentos de memória. A primeira coluna apresenta os endereços de
memória de uma compilação em
. Pelos endereços iniciais e finais é
Introdução à Programação: Conceitos e Práticas.
Página 346
possível obter a quantidade de bytes ocupada pelo código binário:
, o que equivale a
.
Program ExSEG;
Type TVInt
= Array[1..1000] Of Integer;
$004013e0 Procedure LerDados
(V : TVInt; N : Integer);
Var I, J : Integer;
Begin
{
Segmento de Dados
TPVInt = ^TVInt;
}
$00401416 End;
$00401417
$00401420 Procedure MostrarDados
(S : String;
PV : TPVInt; N : Integer);
Var T : String;
Segmento de Código
...
Segmento de Pilha
I, J : Integer;
Begin
{
...
}
$00401440 End;
$00401441
Var PX : TPVInt;
Heap
NX : Integer;
$00401450 Begin
{...}
New
(PX);
$00401479
LerDados
(
PX^
, NX);
$00401488
MostrarDados
('teste', PX, NX);
$0040148f
Dispose
(PX);
{...}
$004014a0 End.
$004014a1
As cores indicam onde cada parte do programa irá residir na memória durante a
execução. A parte não código das
residirão no
Introdução à Programação: Conceitos e Práticas.
Página 347
pelo tempo que durar a execução do módulo. Neste exemplo, há
apenas duas chamadas de procedimentos no programa principal, a ativação de
e
, e foram destacados os
para onde
deve retornar o fluxo do programa quando encerrar a execução dos módulos. Estes
endereços são armazenados no
no momento de cada chamada.
As variáveis globais
e
são de natureza estática e irão residir no segmento de
dados. A variável
é do tipo ponteiro
e ocupará
de memória na
arquitetura
, o que é suficiente para armazenar um endereço de memória. A
definição de
, quando devidamente inicializado deverá apontar para o início de um
vetor de inteiros.
[
]
29.2. Alocação dinâmica
A
consiste na requisição de memória em tempo de execução de
forma explícita pelo programador através da inclusão de uma linha de código com a
instrução própria para este fim. De forma semelhante, a liberação desta memória
alocada deverá se dar por ordem explícita do programador.
A alocação de memória em
é feita pela seguinte procedure:
O parâmetro é do tipo ponteiro e a forma de passagem é por referência, o que significa
que no momento da chamada o argumento indica o local onde deverá ser armazenado
o endereço da memória alocada. No exemplo anterior a linha de código
faz
com que o
reserve uma área de memória para um
, suficiente para acomodar
células do tipo
, sendo que o endereço do ínicio deste bloco é armazenado
em
. Inicialmente, antes da alocação o conteúdo da variável
é algo incerto e sem
vinculação com área de memória válida. Nesta situação o correto é atribuir o valor
á
, oferecendo assim uma possibilidade para que o código adiante possa testar o
conteúdo da variável ponteiro antes de efetivar o uso da área apontada
.
O seguinte diagrama ilustra um mapa de memória em dois momentos distintos, sendo o
primeiro logo após a criação de
, porém sem inicialização, e o segundo após a
atribuição do valor
à
:
Introdução à Programação: Conceitos e Práticas.
Página 348
VARIÁVEL NÃO
INICIALIZADA
PX
VARIÁVEL
INICIALIZADA COM NIL
???
PX
O valor inicial de
é indefinido e o local apontado é incerto, e consequentemente o
uso de
deve acarretar em erro de execução. O segundo cenário indica que
foi
inicializado com
. Esta próxima ilustração apresenta o cenário após a alocação de
memória com
, onde o processamento da rotina
efetiva a reserva de
tantos bytes quantos forem necessários para acomodar
células do tipo
eo
endereço inicial deste bloco é atribuído ao argumento
. Assim, podemos afirmar que
contém o endereço do vetor e
tem todas as prerrogativas de um vetor de
inteiros.
HEAP
PX^
PX
Assim, caso o programador queira inicializar as células alocadas em zero, poderá fazêlo da seguinte forma:
[ ]
A liberação da área alocada é feita chamando a seguinte procedure:
O parâmetro é do tipo ponteiro e a forma de passagem é por cópia-valor. Geralmente o
argumento passado é o mesmo utilizado para a procedure
. De fato é necessário
Introdução à Programação: Conceitos e Práticas.
Página 349
fornecer o endereço alocado e com esta informação o gerenciador da
executará a
liberação. Neste exemplo, a liberação poderá ser feita com
. A partir deste
momento a utilização da área apontada por
é inválida podendo acarretar erro de
execução. É recomendado que após a liberação a variável ponteiro seja reinicializada
com
.
29.3. Exemplos
i.
Elaborar um programa para manipular uma lista encadeada:
A
é uma estrutura de dados que pode ser utilizada para organização de
dados. O problema de referência será carregar de um arquivo texto para a memória uma
relação de nomes de pessoas e executar algum tipo de processamento. Até o momento
o mecanismo mais adequado para receber estes dados seria uma variável do tipo
de
.
Supondo que o seguinte arquivo terá seu conteúdo carregado para uma lista encadeada
do tipo invertida:
ARQUIVO
Adair Pereira
Adalto Cardoso
.
.
.
Roberto Diniz
Romana Peres
O seguinte diagrama ilustra como a lista encadeada invertida será estruturada na
memória:
MEMÓRIA
MEMÓRIA - HEAP
Romana...
Roberto...
Adalto...
Adair...
Head
Introdução à Programação: Conceitos e Práticas.
Página 350
Os principais elementos da lista são a
(
) e os
. A cabeça da lista é
uma variável do tipo ponteiro que deverá conter o endereço do primeiro nodo. No caso
de uma lista sem nodo o conteúdo de
será
. Os nodos são todos do mesmo tipo
e consistem de um registro com pelo menos dois campos, sendo um reservado para o
dado que se deseja armazenar e o outro nodo um ponteiro para uma estrutura do
mesmo tipo do nodo. As seguintes definições de tipo e de variáveis proporcionam o
suporte inicial necessário para estruturar uma lista encadeada invertida:
Program ExLISTA;
Type
TPNodo
TNodo
Dado
Next
End;
=
=
:
:
^TNodo;
Record
String;
TPNodo;
Var
Head : TPNodo;
Begin
Head := Nil;
End.
O registro
representa o modelo de cada nodo e é composto pelo campo
do
tipo
e pelo campo
do tipo
. O tipo
representa um ponteiro
para o tipo
. O campo dado foi definido para conter o nome da pessoa e o campo
next apontará para o próximo elemento da lista.
Neste exemplo será adotada a
onde o dado mais
recentemente adicionado é inserido na primeira posição. De outra forma teríamos uma
. A variável
é inicializada com
indicando lista vazia. Na
sequência são descritos os passos para criar e inserir um nodo na lista.
Inicialmente a lista está vazia:
PASSO 0
H
Introdução à Programação: Conceitos e Práticas.
Página 351
O próximo passo é inserir o primeiro nodo na lista. Será utilizada uma variável ponteiro
, do tipo
para auxiliar no processo de montagem da lista:
i.
É criado um nodo na
receber a informação desejada (
e vinculado a
. O campo
.
PASSO 1.1
T
já pode
1
New (T);
2
T^.Next := H;
3
H := T;
1
Adair...
H
ii.
A inserção deste nodo na lista se dá fazendo com que o próximo de
seja o atual primeiro (onde aponta).
PASSO 1.2
T
1
New (T);
2
T^.Next := H;
3
H := T;
1
Adair...
H
iii.
2
Em seguida o nodo criado torna-se cabeça da lista (
PASSO 1.3
T
).
1
New (T);
2
T^.Next := H;
3
H := T;
1
Adair...
H
3
Introdução à Programação: Conceitos e Práticas.
2
Página 352
Para fixar o conceito, seguem os passos para inserir o segundo nodo na lista:
i.
É criado um nodo na
receber a informação desejada (
PASSO 2.1
e vinculado a
. O campo
já pode
.
1
Adalto...
1
New (T);
2
T^.Next := H;
3
H := T;
T
Adair...
H
ii.
A inserção deste nodo na lista se dá fazendo com que o próximo de
seja o atual primeiro (onde aponta).
PASSO 2.2
1
Adalto...
T
1
New (T);
2
T^.Next := H;
3
H := T;
2
Adair...
H
iii.
Em seguida o nodo criado torna-se cabeça da lista (
PASSO 2.3
1
Adalto...
T
).
1
New (T);
2
T^.Next := H;
3
H := T;
2
3
Adair...
H
Introdução à Programação: Conceitos e Práticas.
Página 353
De modo semelhante os demais nodos são criados e inseridos na lista. As informações
atribuídas ao campo
são oriundas de um arquivo texto contendo a relação de
nomes.
Procedure Load (FN : String; Var H : TPNodo);
Var F : Text;
T : TPNodo;
Begin
Assign (F, FN);
Reset (F);
While Not Eof(F) Do
Begin
New (T);
Readln (F, T^.Dado);
T^.Next := H;
H := T;
End;
Close (F);
End;
Para percorrer uma lista encadeada e utilizar o dado armazenado no nodo também é
utilizada uma variável ponteiro auxiliar . Inicialmente faz apontar para onde aponta o
cabeça da lista
(
). Em seguida é iniciada uma repetição que a cada ciclo faz
com que
avance e aponte para o próximo elemento (
). A repetição é
executada enquanto o valor for diferente de
, indicando assim que alcançou o
final da lista. A seguinte figura ilustra uma lista encadeada e destaca a variável
se
deslocando pelos nodos a cada ciclo do
.
T
Romana...
Roberto...
Adalto...
Adair...
H
A seguinte função conta a quantidade de nodos de uma lista encadeada:
Function ContaNodos (H : TPNodo) : Integer;
Var C : Integer;
T : TPNodo;
Begin
C := 0;
Introdução à Programação: Conceitos e Práticas.
Página 354
T := H;
While T <> Nil Do
Begin
Inc (C);
T := T^.Next;
End;
ContaNodos := C;
End;
Segue o programa proposto com várias operações com uma lista encadeada:
Program ExLISTA;
Type
TPNodo
TNodo
Dado
Next
End;
=
=
:
:
^TNodo;
Record
String;
TPNodo;
Procedure Load (FN : String; Var H : TPNodo);
Var F : Text;
T : TPNodo;
Begin
Assign (F, FN);
Reset (F);
While Not Eof(F) Do
Begin
New (T);
Readln (F, T^.Dado);
T^.Next := H;
H := T;
End;
Close (F);
End;
Procedure Relat (FN : String; H : TPNodo);
Var F : Text;
T : TPNodo;
Begin
Assign (F, FN);
Rewrite (F);
T := H;
While T <> Nil Do
Begin
Writeln (F, T^.Dado);
T := T^.Next;
Introdução à Programação: Conceitos e Práticas.
Página 355
End;
Close (F);
End;
Function ContaNodos (H : TPNodo) : Integer;
Var C : Integer;
T : TPNodo;
Begin
C := 0;
T := H;
While T <> Nil Do
Begin
Inc (C);
T := T^.Next;
End;
ContaNodos := C;
End;
Procedure Liberar (Var H : TPNodo);
Var T : TPNodo;
Begin
While H <> Nil Do
Begin
T := H;
H := H^.Next;
Dispose (T);
End;
End;
Procedure LiberarFirst (Var H : TPNodo);
Var T : TPNodo;
Begin
If H <> Nil Then
Begin
T := H;
H := H^.Next;
Dispose (T);
End;
End;
Procedure EliminarNodos (var H : TPNodo; Nome : String);
Var T, Q : TPNodo;
Begin
While (H <> Nil) And (Pos(Nome, H^.Dado) <> 0) Do
LiberarFirst (H);
Introdução à Programação: Conceitos e Práticas.
Página 356
Q := H;
T := H;
While T <> Nil Do
Begin
If Pos(Nome, T^.Dado) <> 0 Then
Begin
Q^.Next := T^.Next;
Dispose (T);
T := Q^.Next;
End;
Q := T;
T := T^.Next;
End;
End;
Procedure Add (var H : TPNodo; Nome : String);
Var Novo, T, Q : TPNodo;
Begin
New (Novo);
Novo^.Dado := Nome;
Q := H;
T := H;
While (T <> Nil) And (T^.Dado > Nome) Do
Begin
Q := T;
T := T^.Next;
End;
If Q = T Then
Begin
Novo^.Next := H^.Next;
H := Novo;
End Else
Begin
Novo^.Next := Q^.Next;
Q^.Next := Novo;
End;
End;
Var
Head : TPNodo;
Begin
Head := Nil;
Load ('nomes.txt', Head);
Introdução à Programação: Conceitos e Práticas.
Página 357
Relat ('nomes-lista.txt', Head);
Writeln (ContaNodos (Head));
EliminarNodos (Head, 'Romana');
Writeln (ContaNodos (Head));
EliminarNodos (Head, 'Santos');
Writeln (ContaNodos (Head));
Relat ('nomes-lista2.txt', Head);
Add (Head, 'Aabrao da Silva');
Writeln (ContaNodos (Head));
Relat ('nomes-lista3.txt', Head);
Liberar (Head);
Writeln (ContaNodos (Head));
End.
A procedure
já foi explicada e serve para criar a lista encadeada invertida a partir
dos dados contidos em um arquivo texto. A procedure
gera um relatório a partir
dos dados contidos nos nodos, permitindo que seja verificada a correção da lógica de
montagem. O módulo
retira da lista e libera a memória alocada dos
nodos cujos dados contenham um determinado texto. A rotina
insere um novo nodo
na posição que mantenha a ordem alfabética. Neste caso supõe-se que a lista foi
montada em ordem alfabética descendente. A procedure
desaloca todos os
nodos da lista.
Introdução à Programação: Conceitos e Práticas.
Página 358
30.
Interpretador da Linha Comando
O interpretador de comando ou
de um sistema operacional é um programa que
proporciona interação entre o usuário e o ambiente computacional. Antes do surgimento
das interfaces mais elaboradas, notadamente as interfaces gráficas, a
era o único
meio de execução de comandos. Os comandos típicos incluem:
i.
ii.
iii.
iv.
gerenciamento de pastas ou diretórios (consultar, criar, renomear, apagar,
copiar);
gerenciamento de arquivos;
controle de processos (consultar, executar e
);
manipulação de data e hora (consultar e alterar), dentre outros.
Além do comando é necessário conhecer os parâmetros de execução, o que na maioria
dos casos dificulta o uso dos recursos disponíveis no sistema operacional.
O conhecimento das funcionalidades proporcionadas por um interpretador de
comandos é fundamental para profissionais responsáveis pela administração de
serviços e recursos computacionais. Principalmente nos sistemas
ou
as
são verdadeiros ambientes de programação que disponibilizam poderosas
linguagens interpretadas que permitem o desenvolvimento de programas (
) com
as mais variadas lógicas para execução de comandos.
O surgimento e a disseminação de interfaces gráficas reduziu drasticamente a
necessidade do uso do interpretador de comandos para tarefas básicas. O seguinte
comando lista o conteúdo de uma pasta ou diretório no ambiente
:
$ pwd
/home/arquivos
$ ls –l *.txt
drwxr--r-1 arquivos
-rw-r--r-1 arquivos
-r-xr-xr-x
1 arquivos
O
editors
editors
fred
4096
30405
8460
dados.txt
pessoas.txt
notas.txt
comando
admite vários parâmetros via linha de comando, como
– – – – – – – - , que orientam a forma de apresentar o conteúdo da pasta. Ao
utilizar uma interface gráfica, o usuário navega facilmente pelas pastas a um simples
toque no mouse ou na tela, e muitas vezes não tem noção que as informações
apresentadas foram obtidas através de chamadas ás funções do sistema operacional.
Assim, é importante conhecer o mecanismo da linguagem que permite capturar os
argumentos passados através da linha de comando. O
original não fornece este
recurso, porém descendentes do
incoporaram as funções
e
que permitem acessar os argumentos passados via linha de comando no
momento que o programa foi executado.
Introdução à Programação: Conceitos e Práticas.
Página 359
A função
retorna a quantidade de argumentos da linha de commando.
Caso só tenha sido executado o programa em si, sem argumentos, o resultado é zero.
A função
retorna o
argumento da linha de comando. O valor de
deve estar ser
. O valor de
retorna a identificação
completa do arquivo executado incluindo o caminho e o nome.
O seguinte exemplo ilustra a utilização deste recurso:
Var I : Integer;
Begin
Writeln ('Linha de Comando processada: [', ParamStr(0),']');
Writeln ('Quantidade de argumentos
: [', ParamCount,']');
For I := 1 To ParamCount Do
Writeln (ParamStr(I));
End.
Na sequência o resultado para a execução indicada.
C:\dados\programa>linhadecomando -a -d 100 *.txt ola mundo belo
Linha de Comando processada: [C:\dados\programa\linhadecomando.exe]
Quantidade de argumentos
: [7]
-a
-d
100
*.txt
ola
mundo
belo
O espaço em branco é interpretado como separador de argumentos. O arquivo
executado
foi
o
com
os
argumentos
.
Introdução à Programação: Conceitos e Práticas.
Página 360
31.
Recursividade
O estilo de programação determina a aparência de um programa. A linguagem
pertence a família das linguagens imperativas e provê bons mecanismos para a
programação estruturada. A solução de um problema conduz geralmente a uma
organização do programa que combina as construções de controle clássicas,
agrupadas em procedures e functions, executando operações sobre estruturas de
dados. Porém, há uma forma diferenciada de representação de problemas que resulta
em programas com estilo bem específico, denominada
.
31.1. Conceito
A programação recursiva é um estilo de resolução de problemas que consiste na
descrição da lógica em dois passos, sendo um passo elementar e direto e um segundo
passo mais abrangente que generaliza a lógica invocando a si mesmo até reduzir o
problema à chamada do passo elementar.
O poder desta técnica influenciou fortemente os paradigmas funcional (
e
)e
lógico (
) onde a forma principal de resolução de problemas é pelo uso da lógica
recursiva.
Um exemplo clássico de recursividade é o cálculo do fatorial de
do problema pode ser feita da seguinte forma:
{
, onde a declaração
}
Reescrevendo esta definição tem-se:


Observamos que
aparece no lado esquerdo e direito do segundo passo, o que
caracteriza a recursão. O programa que implementa esta lógica é:
Program ExFATORIAL;
Function
Begin
If N =
Then
Else
End;
Fatorial (N : Integer) : Real;
0
Fatorial := 1
Fatorial := N * Fatorial (N-1);
Var K : Integer;
Begin
Introdução à Programação: Conceitos e Práticas.
Página 361
For K := 0 To 30 Do
Writeln (K:3, ' ', Fatorial(K):1:0);
End.
A seguinte figura ilustra a sequência das chamadas recursivas para o cálculo do fatorial
de :
Fatorial (5)
5*Fatorial (4)
5*4*3*2*1*1
4*3*2*1*1
4*Fatorial (3)
3*2*1*1
3*Fatorial (2)
2*1*1
2*Fatorial (1)
1*Fatorial (0)
1*1
1
As chamadas recursivas acumulam uma sequência de contextos abertos que começam
a ser resolvidos e fechados quando encontram uma definição básica não recursiva. A
figura anterior ilustra a execução de forma descendente e o fechamento dos contextos
de forma ascendente, iniciando com
. A partir deste ponto, os
resultados vão retornando às chamadas abertas, resolvendo o fatorial, e assim
sucessivamente até chegar à chamada inicial com
Na sequência o resultado para a execução indicada.
0
1
2
3
4
5
.
.
.
25
26
27
28
29
30
1
1
2
6
24
120
15511210043331000000000000
403291461126606000000000000
10888869450418400000000000000
304888344611714000000000000000
8841761993739700000000000000000
265252859812191000000000000000000
Introdução à Programação: Conceitos e Práticas.
Página 362
31.2. Exemplos
i.
Elaborar um programa que:
a. retorna a posição da primeira ocorrência de
b. busca pela última ocorrência de em .
A busca recursiva por um
em um vetor
em um vetor ;
não ordenado pode ser definido como:
[ ]
[ ]
{
}
Em síntese a declaração deste problema estabelece que a busca será feita em um
determinado intervalo de elementos ( a ), comparando o valor de
com o primeiro
elemento deste invervalo. Caso este primeiro elemento não seja igual a , então é feita
uma nova busca em um intervalo que exclua o antigo primeiro elemento (
a ). O
elemento não pertencerá ao vetor quando após uma sucessão de estreitamentos do
intervalo de busca chega-se ao ponto que o índice do primeiro elemento do intervalo
supera o índice do último elemento.
A busca pela última ocorrência de
em
é feita de modo semelhante, porém
comparando-se ao o último elemento do intervalo e o estreitamento ocorre no índice
do último elemento ( a
).
{
[ ]
[ ]
}
O programa que implementa está lógica é:
Program ExBUSCAR;
Const MAX = 100;
Type TVInt = Array[1..MAX] Of Integer;
Procedure FillVetSeq (Var V : TVInt; N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
V[I] := I;
End;
Function BuscarDir (V : TVInt; I, N, X : Integer) : Integer;
Begin
If I > N Then
Introdução à Programação: Conceitos e Práticas.
Página 363
BuscarDir
If V[I] = X
BuscarDir
Else
BuscarDir
End;
:= 0 Else
Then
:= I
:= BuscarDir (V, I+1, N, X);
Function BuscarRev (V : TVInt; I, N, X : Integer) : Integer;
Begin
If I > N Then
BuscarRev := 0 Else
If V[N] = X Then
BuscarRev := N
Else
BuscarRev := BuscarRev (V, I, N-1, X);
End;
Var VX : TVInt;
P : Integer;
Begin
FillVetSeq (VX, 30);
P := BuscarDir (VX, 1, 30, 5);
Writeln (P);
P := BuscarRev (VX, 1, 30, 25);
Writeln (P);
End.
É notório o poder da técnica de recursividade tanto na descrição do problema quanto na
implementação do programa. Notadamente, a solução é compacta, porém com relevante
conteúdo computacional. Além disso, pode ser constatado que o código produzido é
bastante semelhante à descrição do problema. O programa principal ilustra duas
chamadas. Antes porém, o vetor é preenchido com
valores de a
através da
procedure
. Em seguida são chamadas as funções recursivas para a busca
direta e a busca reversa. Neste caso, os resultados apresentados serão
para
e
para
.
ii.
Elaborar um programa que forneça os termos de uma série de
.
A série ou sequência de
é uma sucessão de números, onde os dois primeiros
elementos são e 1 e os demais são obtidos pela soma dos dois valores anteriores.
Assim, podemos enumerar os seguintes termos:
⋯
Vários eventos da natureza podem ser modelados através da série de
, tais
como o crescimento das pétalas de determinadas flores, espiral de conchas, população
de coelhos, dentre outros. A definição recursiva para os termos desta série é dada por:
Introdução à Programação: Conceitos e Práticas.
Página 364
{
}
O programa que implementa esta lógica é:
Program ExFIBO;
Function Fib (N : LongInt) : LongInt;
begin
if N = 0 Then
Fib := 0 Else
if N = 1 Then
Fib := 1 Else
Fib := Fib(N-1) + Fib(N-2);
End;
Var I : LongInt;
Begin
For I := 0 To 30 Do
Writeln (Fib (I));
End.
Esta solução não é a mais adequada devido a sua pouca eficiência, pois os cálculos
feitos para
não são aproveitados para
. Segue uma versão mais
eficiente:
Program ExFIBO;
function
Begin
If N =
Then
Else
Fib2(N, P0, P1 : LongInt) : LongInt;
1
Fib2 := p1
Fib2 := Fib2(N-1, P1, P0 + p1);
End;
Function
Begin
If N =
Then
Else
End;
Fib (N : LongInt) : LongInt;
0
Fib := 0
Fib := Fib2 (N, 0, 1);
Var I : LongInt;
Begin
For I := 0 To 30 Do
Writeln (Fib (I));
End.
Introdução à Programação: Conceitos e Práticas.
Página 365
Na sequência o resultado para a execução indicada.
0
1
1
2
3
5
8
13
21
34
55
.
.
.
75025
121393
196418
317811
514229
832040
iii.
Elaborar um programa para:
a. calcular a soma dos elementos de um vetor;
b. contar a quantidade de vezes que um determinado valor aparece em um vetor.
A soma dos elementos de um vetor pode ser descrita de forma recursiva. O passo
primitivo é para o caso do vetor não possuir elemento algum, resultando em soma igual
a zero. O passo geral estabelece que a soma dos elementos do vetor é igual à adição
do primeiro elemento com a soma dos demais
elementos.
{
}
[ ]
A quantidade de vezes que um elemento aparece em um vetor
descrita na forma recursiva, conforme segue:
{
Introdução à Programação: Conceitos e Práticas.
[ ]
[ ]
também pode ser
}
Página 366
O programa que implementa esta lógica é:
Program ExSOMAR;
Const MAX = 100;
Type TVInt = Array[1..MAX] Of Integer;
Procedure FillVetSeq (Var V : TVInt; N : Integer);
Var I : Integer;
Begin
For I := 1 To N Do
V[I] := I mod 10;
End;
Function
Begin
If N =
Then
Else
End;
Somar (V : TVInt; N : Integer) : Integer;
0
Somar := 0
Somar := V[N] + Somar (V,N-1);
Function Contar (V : TVInt; N, X : Integer) : Integer;
Begin
If N = 0 Then
Contar := 0
Else If V[N] = X Then
Contar := 1 + Contar (V, N-1, X)
Else Contar := Contar (V, N-1, X);
End;
Var VX : TVInt;
C, S : Integer;
Begin
FillVetSeq (VX, 30);
S := Somar (VX, 30);
C := Contar (VX, 30, 5);
Writeln (S);
Writeln (C);
End.
Introdução à Programação: Conceitos e Práticas.
Página 367
32.
Referências Bibliográficas
I. Wirth, Niklaus. The Programming Language Pascal: Revised Report.
Eidgenössische Technische Hochschule. 1973. Modo de acesso: World Wide
Web:
.
II. GHEMAWAT, Pankaj (Adaptado do Livro de). A estratégia e o cenário de
negócios – Caso 1: Intel Corporation 1968-1997, Editora Bookman, 1999.
III. Programa Educar: Curso para professores de 1ª a 4ª série do Ensino
Fundamental. Sistemas de Numeração. ICMC/USP. Modo de acesso: World
Wide Web:
.
IV. Fonseca Filho, Cléuzio. História da computação [recurso eletrônico]: O
Caminho do Pensamento e da Tecnologia. Porto Alegre. EDIPUCRS, 2007.
205 p. Modo de acesso: World Wide Web:
V. "The ENIAC Story". Modo de acesso: World Wide Web:
. Acessado em 03-02-2014.
VI. "History of Computer Printers". Modo de acesso: World Wide Web:
Acessado
em 03-02-2014.
VII. Intel Corporation. Intel® 64 and IA-32 Architectures Software Developer’s
Manual. Volume 1: Basic Architecture. Order Number: 253665-043US. May
2012.
VIII. Lancharro, Eduardo Alcalde. Informatica Basica. MAKRON BOOKS ISBN:
0074605100.
IX. Meirelles,
Fernando
S.
Informática:
microcomputadores. Makron Books.
Novas
aplicações
com
X. Barroso, L. C. et al., Cálculo Numérico com Aplicações, 2 ed. Ed. HARBRA,
São Paulo, 1987. ISBN:8529400895.
XI. Wirth, Niklaus. Algoritmos e estruturas de dados. Rio de Janeiro: LTC - Livros
Técnicos e Científicos, 1989. 255p. ISBN 8521611900.
XII. Wirth, Niklaus. Programação Sistemática. Editora Campus. 1978.
XIII. Ralston, Anthony; Neill, Hugh. Algorithms (Teach Yourself). Editora McGrawHill. 1997. 194p.
Introdução à Programação: Conceitos e Práticas.
Página 368
ÍNDICE REMISSIVO
A
ábaco, 10, 12, 28
ábaco chinês, 10
Ada, 14
Álgebra de Boole, 15
Anticítera, 10, 11
Assembly, 20, 21, 23
B
Blaise Pascal, 12
Ch
Charles Babbage, 14
C
Colossus, 15
Comando de Atribuição, 92
D
decimal, 27, 29, 31, 32, 35, 36, 43, 63, 64, 139, 169, 171,
194, 195, 196, 312, 317, 323
Decimal Codificado em Binário, 15
E
ENIAC, 16
Enigma, 15
Entrada de Dados
Read, 110
Readln, 110
Expressões Numéricas, 93
Introdução à Programação: Conceitos e Práticas.
F
FORTRAN, 20, 21, 83
Função
Argumentos, 115
Cabeçalho, 115
Chamada, 115
Forma Geral, 113
Passagem de Parâmetros, 115
Principais Elementos, 113
Funções Matemáticas
Abs, 103
ArcTan, 104
Cos, 104
, 105
, 106
Int, 106
Ln, 106
PI, 105
Round, 107
Sin, 105
Sqr, 106
Sqrt, 107
, 108
Funções Textuais
Chr, 141
Copy, 143
Length, 140
Ord, 142
Pos, 142
Str, 144
UpCase, 141
Val, 144
G
George Boole, 15
Página 369
, 32
Precedência de Operadores, 103
Progressão Geométrica, 36
H
Hollerith, 15
R
I
relés, 17
Representação de Dados, 55
Números Inteiros, 56
Inteiro com Sinal
Módulo Sinal, 56
J
S
Jacquard, 13
John Napier, 11
Saída de Dados
Write, 111
Writeln, 111
, 105, 120, 122
sistema de numeração, 27, 28, 29, 31, 32, 33, 34
Sistema de Numeração
binário, 20, 31, 33, 35, 36, 37, 39, 43, 46, 56, 57, 58,
59, 61, 62, 63, 65, 67, 68, 75, 99, 101, 195, 196,
257, 258, 259, 311, 315, 316, 317, 332
decimal, 32
hexadecimal, 32, 46, 97, 137, 138, 169, 196, 259
L
Leibniz, 13
N
Napier, 11, 12
Números Inteiros
Inteiro Com Sinal, 56
T
O
tear, 13
Tipos Inteiros
Byte, 93
Int64, 93
Integer, 93
LongInt, 93
LongWord, 93
QWord, 93
ShortInt, 93
SmallInt, 93
Word, 93
Tipos Reais
Comp, 94
Double, 94
Extended, 94
Real, 94
Single, 94
Turing, 15
Operadores Lógicos
AND, 148
NOT, 149
OR, 149
XOR, 149
Operadores Matematicos
*, 102
/, 102
+, 102
Div, 102
Mod, 102
Operadores Relacionais
<, 151
<=, 151
<>, 151
=, 150
>, 150
>=, 150
V
P
válvulas, 17
Passagem de Parâmetros
Referência, 123
Valor, 123
, 34, 35
posicional, 27, 31, 34
Introdução à Programação: Conceitos e Práticas.
W
Wilhelm Schickard, 11
Página 370

Documentos relacionados

solução

solução write('Da 5 volores inteiros:'); while b<>5 do (* ≠ nao e permittido *) begin read(e); if (e mod 3) = 0 then begin c := c + 1 ; if d Leia mais

[java] Sequencia de escape,[ras.] A experiência da ALMG com o uso

[java] Sequencia de escape,[ras.] A experiência da ALMG com o uso Chegando com a Palestra já iniciada, apresento em seguida um breve resumo das estratégias adotadas pela direção de informática da ALMG, que reduziu em 35% os gastos com atualização de softwares. A ...

Leia mais