Tipos de dados predefinidos standard (simples)
1
1. Identificadores
Um identificador é uma sequência de letras, dígitos e “underscore” (_), por qualquer ordem e
até um máximo de 255 caracteres, desde que o 1º carácter seja uma letra ou um “underscore”.
Um identificador é um nome que é dado a um elemento do programa, tais como constantes,
tipos, variáveis, procedimentos, funções, unidades, programas e campos de registos.
2. Tipos de dados predefinidos standard (simples)
Os tipos de dados predefinidos standard dividem-se em duas categorias : fundamentais e
genéricos. Nos tipos fundamentais, a cadeia e o formato são independentes do CPU e do Sistema
Operativo, mantendo-se inalteradas com as diferentes implementações (versões) do Delphi. Ao
contrário, nos tipos genéricos, a cadeia e o formato dependem do CPU e do Sistema Operativo.
Existem 3 classes de tipos predefinidos que distinguem os seus elementos em tipos
fundamentais e genéricos, que são : inteiros, caracteres e strings. Todas as restantes classes, apenas
consideram os tipos como fundamentais.
2.1. Inteiros (Integer)
Um número inteiro é uma sequência de dígitos, precedida por um sinal +/− (opcional o +).
Os tipos inteiros fundamentais são os que constam na tabela seguinte :
Nome
Gama de valores
Formato
Shortint
-128 . . 127
8-bit com sinal
Smallint
-32768 . . 32767
16-bit com sinal
Longint
-2147483648 . . 2147483647
32-bit com sinal
Byte
0 . . 255
8-bit sem sinal
Word
0 . . 65535
16-bit sem sinal
Os tipos inteiros genéricos são os que constam na tabela seguinte :
Nome
Gama de valores
Formato
Integer
-32768 . . 32767
16-bit com sinal
Cardinal
0 . . 65535
16-bit sem sinal
Integer
-2147483648 . . 2147483647
32-bit com sinal
Cardinal
0 . . 2147483647
32-bit sem sinal
As aplicações devem utilizar o formato inteiro genérico sempre que possível, uma vez que,
geralmente, tiram o máximo rendimento do CPU e do Sistema Operativo.
2.2. Reais (Real)
Um número real é representado usando a notação em Ponto Flutuante ("Floating-Point") com
ou sem expoente. A notação sem expoente denomina-se por simples (por ex., −34.78) e a sua forma
geral é a seguinte :
[+/−] (Inteiro sem sinal) . (Inteiro sem sinal)
Apontamentos de Delphi Pascal
2
Tipos de dados predefinidos standard (simples)
A forma geral de um número real com expoente é a seguinte :
[+/−] Mantissa E Expoente
{ [+/−] Mantissa × 10Expoente }
em que
Mantissa é um inteiro ou real em notação simples sem sinal,
Expoente é um inteiro que varia entre dois valores, de acordo com a sua precisão (tabela seguinte).
Tipo
Gama de valores
Dígitos
significativos
Tamanho
(em bytes)
Real
2.9 x 10-39 . . 1.7 x 1038
11 − 12
6
7−8
4
15 − 16
8
Single
Double
1.5 x 10-45 . . 3.4 x 1038
5.0 x 10-324 . . 1.7 x 10308
Extended
3.4 x 10-4932 . . 1.1 x 104932
19 − 20
10
Comp
−263+1 . . 263−1
19-20
8
Currency
−922337203685477.5808 . . 922337203685477.5807
19-20
8
2.3. Lógicos (Boolean)
Os valores lógicos são denominados pelos identificadores predefinidos True e False. Existem
predefinidos 4 tipos lógicos : Boolean, ByteBool, WordBool e LongBool. Como qualquer destes tipos
são enumerados, isto é, constituem um conjunto ordenado, existem as seguintes relações :
Boolean
ByteBool, WordBool, LongBool
False < True
False <> True
Ord (False) = 0
Ord (False) = 0
Ord (True) = 1
Ord (True) = N (N ≠ 0)
Succ (False) = True
Succ (False) = True
Pred (False) = True
Pred (False) = True
Um elemento do tipo Boolean ou ByteBool ocupa 1 byte, do tipo WordBool ocupa 2 bytes (1
palavra) e do tipo LongBool ocupa 4 bytes (2 palavras). O tipo Boolean é o mais utilizado e usa menos
memória; os restantes tipos existem essencialmente para estabelecer compatibilidade com outras
linguagens e com o ambiente Windows.
Um elemento do tipo Boolean apenas pode assumir o valor 0 ou 1, mas se for de um dos
restantes tipos, pode assumir qualquer outro valor ordinal. Uma expressão do tipo ByteBool,
WordBool ou LongBool é considerada False quando o seu valor ordinal é 0 (zero) e True quando o
seu valor ordinal é diferente de zero (0).
2.4. Caracteres (Char)
Um carácter representa-se entre plicas (‘) para se distinguirem de números e identificadores.
Também aqui existem tipos fundamentais e genéricos. Os tipos caracteres fundamentais são o
AnsiChar e WideChar.
Os valores do tipo AnsiChar são representados por 1 byte, ordenados de acordo com o conjunto
de caracteres ANSI/ASCII. Os valores do tipo WideChar representam-se por 2 bytes (1 palavra),
ordenados de acordo com o conjunto de caracteres Unicode sistema que utiliza 2 bytes para
Apontamentos de Delphi Pascal
Tipos de dados predefinidos não standard
3
guardar a informação de um carácter (mais de 65000 caracteres). Os primeiros 256 caracteres Unicode
correspondem aos caracteres ANSI.
O tipo carácter genérico é o Char. Nesta versão do Delphi Pascal, o tipo Char corresponde ao
tipo AnsiChar, mas noutras versões para outros CPU’s e Sistemas Operativos, pode corresponder ao
WideChar.
No tipo Char existem vários subconjuntos ordenados importantes de referir, como :
{ ‘A’, ..., ‘Z’ }
→
Letras maiúsculas
{ ‘a’, ..., ‘z’ }
→
Letras minúsculas
2.5. String
Uma string é uma sequência de caracteres ASCII entre plicas. Por exemplo, ‘Delphi Pascal’.
Existem 2 tipos fundamentais de strings, que são : ShortString e AnsiString. O tipo ShortString
representa as strings com, no máximo, 255 caracteres ASCII. O tipo AnsiString representa as strings,
cujo comprimento apenas é limitado pela memória disponível (1 GB).
O único tipo genérico é o tipo String, que, por defeito, corresponde ao tipo ShortString no
Delphi 16, e ao tipo AnsiString no Delphi 32 (versão 3 ou mais).
3. Tipos de dados predefinidos não standard
Um tipo de dados não standard é definido a partir de tipos de dados predefinidos standard.
3.1. TDateTime
O Delphi guarda os valores da data e hora num elemento do tipo TDateTime. O tipo
TDateTime pertence à unidade System e está definido como real (Double) da seguinte forma :
type TDateTime = type Double ;
A parte inteira de um valor do tipo TDateTime corresponde ao número de dias que passaram
desde 30-12-1899; a parte fraccionária é uma fracção de um dia com 24 horas que já passou. A tabela
seguinte ilustra alguns exemplos :
Data em real
Data em TDateTime
0.0
30-12-1899 00:00
2.75
01-01-1900 18:00
−1.25
29-12-1899 06:00
35065.0
01-01-1996 00:00
3.2. TTimeStamp
O tipo TTimeStamp é utilizado para representar datas e horas com muita precisão. Este tipo é
definido como um registo da seguinte forma :
type TTimeStamp = record
Time : Integer ;
Date : Integer ;
end ;
em que,
Time corresponde ao número de milésimos de segundo desde as 00:00 horas
Date corresponde ao número de dias passados desde 01-01-0001
Apontamentos de Delphi Pascal
4
Operadores
4. Operadores
4.1. Aritméticos
Neste tipo de operadores, os operandos e os resultados são apenas dos tipos inteiro e real. A
tabela seguinte descreve os operadores aritméticos existentes :
Operador
Descrição
Operandos
Resultado
+
Adição
(Inteiro, Inteiro)
Inteiro
−
Subtracção
(Inteiro/Real, Real)
Real
*
Produto
(Real, Inteiro/Real)
Real
/
Divisão Real
(Inteiro/Real, Inteiro/Real)
Real
Div
Divisão Inteira
Mod
Resto da Divisão Inteira
(Inteiro, Inteiro)
Inteiro
4.2. Lógicos
Neste tipo de operadores, os operandos e os resultados são apenas do tipo lógico. A tabela
seguinte descreve os operadores lógicos existentes :
Operador
Operação
Descrição
=
Igualdade
Verifica se 2 expressões lógicas são iguais
Not
Negação
Troca o valor da expressão lógica
And
Conjunção (e)
Devolve True apenas se as duas expressões são True
Or
Disjunção (ou)
Devolve True se uma das 2 expressões é True
Xor
Ou exclusivo
Devolve True apenas se as expressões são diferentes
4.3. Relacionais
Neste tipo de operadores, os operandos são ambos do mesmo tipo simples (inteiro, real, lógico,
carácter ou string) e o resultado do tipo lógico. A tabela seguinte descreve os operadores relacionais :
Operador
Descrição
=
Igualdade
<>
Desigualdade
<
Menor
<=
Menor ou Igual
>
Maior
>=
Maior ou Igual
Apontamentos de Delphi Pascal
Constantes tipificadas (“typed constants”)
5
5. Constantes
Muitas vezes é conveniente associar um dado de qualquer tipo com um identificador,
proporcionando, assim, um nome ao elemento de informação. O identificador é designado por
constante se o elemento de informação lhe é afecto permanentemente (isto é, se o valor do elemento
de informação de mantém inalterado ao longo do programa).
Uma constante deve ser sempre definida antes de poder aparecer numa instrução do Delphi
Pascal. Esta definição tem 2 funções : estabelece que o identificador é uma constante e associa um
valor à constante. O tipo da constante será implicitamente determinado pelo elemento de informação.
A forma geral de definição de uma constante é a seguinte :
const
Exemplos :
const
Nome = Valor (expressão) ;
pi = 3.14159265 ;
termo = 2 * pi ;
cadeira = 'Informatica' ;
Existem 3 identificadores predefinidos que representam constantes : maxint, true e false. O
primeiro, maxint, especifica o maior valor que pode ser atribuído a uma quantidade de tipo Integer.
As outras, true e false, representam os 2 valores que podem ser atribuídos a uma variável lógica.
6. Variáveis
O identificador cujo valor pode variar durante a execução do programa é designado por
variável. Todas as variáveis devem ser individualmente declaradas (i.e., definidas) antes de poderem
aparecer numa instrução. A declaração de variáveis estabelece o facto de que o identificador é uma
variável e especifica o seu tipo.
A forma geral da declaração de uma variável é a seguinte :
var
Nome : Tipo ;
Para se declarar N variáveis do mesmo tipo, a forma geral é a seguinte :
var
Nome_1, Nome_2, . . . , Nome_N : Tipo ;
Exemplos :
var Linha, Coluna : Integer ;
X, Y : Double ;
Achou : Boolean ;
Bandeira : Char ;
Notas :
A declaração de variáveis implica a reserva de espaço de memória.
Por exemplo, a 2ª declaração define 2 registos de memória de tipo Double, identificados por X e Y.
X
Y
Estes espaços permanecem vazios até que uma instrução adequada os mande preencher.
7. Constantes tipificadas (“typed constants”)
São identificadores que não são constantes, mas que são declaradas na secção das constantes.
Estes identificadores funcionam como variáveis, às quais são atribuídos valores iniciais, apenas
Apontamentos de Delphi Pascal
6
Expressões
quando se inicia a execução do programa. Estas variáveis podem ser alteradas através de instruções
adequadas, sempre que se desejar.
A síntaxe é a seguinte :
const
Exemplo :
const
Nome : Tipo = Valor (expressão) ;
Cont : Integer = 0 ;
Apelido : String = ‘Almeida’ ;
8. Expressões
Uma expressão é um conjunto de operandos (números, constantes, variáveis, etc.) agrupados
por certos operadores, constituindo uma forma algébrica que representa um valor (um elemento
simples). Existem 2 tipos de expressões : numéricas e lógicas. Uma expressão numérica representa um
valor numérico e uma expressão lógica representa um valor lógico (true ou false).
Uma expressão pode, por vezes, tornar-se bastante complexa, devido à presença de múltiplos
operadores. Nestes casos torna-se necessário especificar a ordem pela qual as operações são
efectuadas.
8.1. Prioridades dos operadores
A ordem pela qual as operações são efectuadas, pode ser determinada pelas prioridades
naturais dos operadores. A tabela a seguir indica essas prioridades.
OPERADORES
PRIORIDADES
NOT
1ª
* / DIV MOD AND
2ª
+ − OR XOR
3ª
= <> >
>= < <=
4ª
Exemplos :
1. 3 + 6 * 2 = 3 + 12 = 15
2. true and false or not true = true and false or false = false or false = false
8.2. Operadores com a mesma prioridade
Dentro de um dado grupo de prioridades, as operações são efectuadas à medida que aparecem,
isto é, o cálculo efectua-se da esquerda para a direita.
Exemplo :
193 mod 19 div 3 * 127 = 3 div 3 * 127 = 1 * 127 = 127
8.3. Uso de parêntesis
As duas regras anteriores podem ser alteradas pelo uso de parêntesis. Neste caso, em primeiro
calcula-se o que se encontra entre parêntesis.
Apontamentos de Delphi Pascal
Dados definidos pelo utilizador
7
Exemplos :
1. 12 / (3 * 2) = 12 / 6 = 2.0
(12 / 3 * 2 = 4.0 * 2 = 8.0 )
2. ( (3 > 7) or (3 <= 7) ) and ( 7 <> 10 ) = (false or (3 <= 7) ) and (7 <> 10) = (false or true) and
(7 <> 10) = true and (7 <> 10) = true and true = True
8.4. Conclusão
Para se determinar o valor de uma expressão, deve-se proceder da seguinte forma :
1º Reduzir a expressão, eliminando todos os parêntesis que existam, começando pelos que se
encontram mais à esquerda;
2º Verificar quais as operações mais prioritárias e efectuar as que aparecem em primeiro.
9. Dados definidos pelo utilizador
Existem 2 tipos de dados simples definidos pelo utilizador : por enumeração e por subdomínio.
9.1. Dados definidos por enumeração
Este tipo de dados consiste numa sequência ordenada de identificadores, em que cada um
destes é interpretado como um elemento individual. Estes elementos estão colectivamente associados
a um nome particular que serve para identificar o tipo de informação.
A forma geral desta definição é a seguinte :
type NomeTipo = ( Elemento_1, Elemento_2, . . . , Elemento_N ) ;
onde as reticências (...) serão substituídas pelas restantes alternativas.
Exemplos :
type
var
Dia_Semana = (segunda, terça, quarta, quinta, sexta, sabado, domingo) ;
Cor = (amarelo, verde, vermelho, azul) ;
Naipe = (ouros, copas, paus, espadas) ;
feriado : Dia_Semana ;
tinta : Cor ;
trunfo : Naipe ;
9.2. Dados definidos por subdomínio (gama de valores)
Um subdomínio refere-se a uma parte do intervalo original de um tipo de dados simples e
ordenado. Dados deste tipo são elementos que caem nesse intervalo de valores, formando um
subconjunto de dados contíguos e ordenados.
O conceito de subdomínio pode ser aplicado a qualquer conjunto de dados ordenados e
simples. Isto inclui dados enumerados previamente definidos, assim como do tipo inteiro, carácter e
lógico. A forma geral desta definição é a seguinte :
type
NomeTipo = PrimeiroElemento . . UltimoElemento ;
em que,
PrimeiroElemento ≤ UltimoElemento e { PrimeiroElemento, ... , UltimoElemento } é um conjunto
simples ordenado.
Exemplo :
type
var
Digito = 0 . . 9 ;
Dia_Util = Segunda . . Sexta ;
i, j : Digito ;
dia : Dia_Util ;
Apontamentos de Delphi Pascal
8
Instruções
9.3. Observações
•
Para os elementos de um qualquer tipo definido pelo utilizador, são válidos os operadores
relacionais (<, >, =, <>, >=, <= ) e as funções de ordem.
•
Refira-se também que o tipo pode ser definido na declaração das variáveis.
Exemplo :
var i, j : 1 . . 10 ;
tinta : (amarelo, verde, vermelho, azul) ;
10. Instruções
Uma instrução do Delphi Pascal é uma ordem, ou conjunto de ordens, que obriga o computador
a efectuar certas acções. Existem 2 conjuntos de instruções : simples e estruturadas.
As instruções simples, que são essencialmente únicas e incondicionais, são de 3 tipos :
• de atribuição;
• que acedem a procedimentos;
• GOTO.
As instruções estruturadas são de 3 tipos :
• compostas;
• condicionais;
• repetitivas.
10.1. De atribuição
A instrução de atribuição é uma instrução simples, que é usada para atribuir um valor a uma
variável. Esta instrução tem a seguinte forma :
Variável := Valor (expressão) ;
( := significa “ toma o valor de” )
em que,
Valor é uma expressão, que pode ser um elemento simples (número, carácter ou lógico).
No entanto, a informação deve ser do mesmo tipo que a variável a que está afecta, exceptuando
o caso em que um valor inteiro pode ser atribuído a uma variável real.
Exemplos :
1. w : = x + y − 300 ;
2. L := ( j > 0 ) or ( i > 0 ) ;
3. letra := chr (k) ;
10.2. Composta
Antes do mais, refira-se que as instruções são obedecidas sequencialmente, como mostra o
seguinte esquema :
...
Instrução_1 ;
Instrução_2 ;
...
Apontamentos de Delphi Pascal
Instruções
9
Uma instrução composta consiste numa sequência de 2 ou mais instruções consecutivas,
envolvidas pelas palavras-chave BEGIN e END. A sua forma geral é a seguinte :
begin
Instrução_1 ;
Instrução_2 ;
...
Instrução_N
end
Refira-se que todas as instruções terminam necessariamente com ponto e vírgula, excepto a
última (Instrução_N), pois esta está imediatamente antes da palavra END. No entanto, se o ponto e
vírgula for colocado naquela instrução, isso não significa erro, apenas é desnecessário.
Uma instrução composta deve ter a seguinte indentação :
...
begin
Instrução_1 ;
Instrução_2 ;
begin
Instrução_3 ;
Instrução_4 ;
Instrução_5
end ;
Instrução_6
end
...
Exemplo :
begin
IntroduzirDados (raio) ;
area := 3.14159 * sqr (raio) ;
MostrarResultados (raio, area)
end ;
10.3. Condicionais
Este tipo de instruções são importantes, já que, normalmente, é necessário efectuar testes
lógicos e então tomar uma determinada atitude que depende do resultado do teste selecção
alternativa . Ou então, escolher entre um grupo de instruções de entre os grupos disponíveis
selecção múltipla.
10.3.1. Selecção alternativa (estrutura IF)
Esta estrutura permite que uma acção se realize, unicamente, se uma condição lógica tem um
determinado valor lógico (true/false). Esta estrutura tem duas formas : if...then... e if...then...else... .
A forma geral da estrutura if ... then ... é a seguinte :
if ExpressãoLógica
then Instrução ;
em que
Instrução será executada se e só se a ExpressãoLógica for verdadeira (se for falsa é ignorada
nenhuma acção é executada) e pode ser de qualquer tipo.
Apontamentos de Delphi Pascal
10
Instruções
A forma geral da estrutura if ...then ...else ... é a seguinte :
if ExpressãoLógica
then Instrução_1
else Instrução_2 ;
em que,
Instrução_1 será executada se a ExpressãoLógica for verdadeira; caso contrário, será executada a
Instrução_2.
Note-se que apenas uma das instruções é executada, mas nunca ambas. As instruções podem
ser de qualquer tipo. Refira-se ainda que, no fim da Instrução_1 não pode aparecer o ponto e vírgula
(sinalética de fim de instrução); no final da Instrução_2, o critério é o aplicado para o caso geral.
Exemplos :
1. if (saldo < 1000.0) or (estado = 'R')
then MostrarResultados (saldo) ;
O valor da variável real saldo é mostrado se ela for menor que 1000 ou se a variável do tipo carácter
estado representar o carácter 'R'.
2. if circulo
then begin
IntroduzirDados (raio) ;
area := 3.14159 * sqr (raio) ;
MostrarResultados ('Area do circulo = ', area)
end
else begin
IntroduzirDados (comprimento, largura) ;
area := comprimento * largura ;
MostrarResultados ('Área do rectângulo = ', area)
end ;
Este exemplo permite determinar a área de 2 figuras geométricas diferentes. Se a variável lógica circulo é
verdadeira (pretende-se determinar a área dum círculo), então é executada a seguinte instrução composta :
introduzir o valor do raio, cálcular o valor da área e mostrar como resultado o valor da area; caso
contrário (pretende-se determinar a área dum rectângulo), é executada a seguinte instrução composta :
introduzir os valores do comprimento e largura do rectângulo, cálcular o valor da área e mostrar como
resultado o valor da área.
10.3.2. Selecção múltipla (estrutura CASE)
Esta estrutura permite que grupos particulares de instruções sejam escolhidos de entre os vários
disponíveis. A selecção é baseada no valor corrente de uma expressão referida como selector.
A forma geral desta estrutura é a seguinte :
case Expressão of
ListaOpções_1 : Instrução_1 ;
...
ListaOpções_N : Instrução_N
end ;
em que,
Expressão pode ser de qualquer tipo predefinido standard ordenado (não real),
ListasOpções_k correspondem a conjuntos de constantes de um certo tipo (1 ≤ k ≤ N)
Instrução_k podem ser de qualquer tipo (1 ≤ k ≤ N)
Cada opção representa um dos valores permitidos da expressão. Assim, se a expressão é dum
tipo T, as opções são valores deste tipo que caiam dentro de uma gama permitida. As opções não têm
que aparecer por uma ordem específica, embora cada opções deva ser única.
Apontamentos de Delphi Pascal
Instruções
11
Exemplo :
case mes of
1, 3, 5, 7, 8, 10, 12 :
2 :
quantidade_dias := 31 ;
if ano_bissexto
then quantidade_dias := 29
else quantidade_dias := 28 ;
quantidade_dias := 30
11, 6, 4, 9 :
end ;
mes ∈ { 1, 3, 5, 7, 8, 10, 12 }
mes ∈ { 2 }
mes ∈ { 11, 6, 4, 9 }
⇒
⇒
⇒
quantidade_dias = 31
quantidade_dias = 29/28
quantidade_dias = 30
Observação :
Se a expressão (selector) não tomar nenhum dos valores das listas de opções (cláusulas), então tal
facto pode provocar um erro de algoritmo.
Outra forma da estrutura CASE :
No Delphi Pascal existe uma forma alternativa da estrutura CASE, mais desenvolvida que a
normal, cuja sintaxe é a seguinte :
case Expressão of
ListaOpções_1 : Instrução_1 ;
...
ListaOpções_N : Instrução_N
else
Instrução
end ;
10.4. Repetitivas (ciclos)
Com estas instruções, é possível que um grupo de instruções consecutivas quaisquer seja
executado repetidas vezes. Existem 2 tipos de instruções repetitivas : condicional e incondicional.
10.4.1. Repetição "Enquanto" (estrutura While ... Do)
Neste tipo de estrutura, um grupo de instruções consecutivas é executado repetidamente,
"enquanto" uma condição lógica é satisfeita (tem o valor true). Logo, esta instrução é uma repetição
condicional, sendo a condição lógica testada no inicio do ciclo.
A forma geral da estrutura WHILE é a seguinte :
while ExpressãoLógica do
Instrução ;
em que,
Instrução é de qualquer tipo e inclui uma característica que deve influenciar o valor da
ExpressãoLógica.
Generalidades :
• A instrução do ciclo é executada enquanto a expressão lógica for verdadeira. Ou seja, para cada
iteração do ciclo, se a expressão lógica for verdadeira, a instrução é executada; caso contrário, a
próxima instrução a ser executada é aquela a seguir ao referido ciclo.
• Refira-se ainda que devido ao facto da expressão lógica ser avaliada antes do ciclo ser executado
pela 1ª vez, ela pode nunca ser executada se a ExpressãoLógica é falsa logo no início.
Apontamentos de Delphi Pascal
12
Instruções
Exemplos :
1. Elaborar um bloco que escreva numa tabela as potências de 2, inferiores a 1000.
i := 1 ;
potencia := 2 ;
while potencia <= 1000 do
begin
MostrarResultados (potencia) ;
i := i + 1 ;
potencia := potencia * 2
end ;
2. Elaborar um bloco que escreva numa tabela os primeiros 20 números inteiros e o seu dobro.
i := 1 ;
while i <= 20 do
begin
MostrarResultados (2 * i) ;
i := i + 1
end ;
10.4.2. Repetição "Até Que" (estrutura Repeat ... Until)
Neste tipo de estrutura, um grupo de instruções consecutivas é executado repetidamente, "até
que" uma condição lógica seja satisfeita. Logo, esta instrução é uma repetição condicional, sendo a
condição lógica testada no fim do ciclo.
A forma geral da estrutura REPEAT, é a seguinte :
repeat
Instrução_1 ;
...
Instrução_N
until ExpressãoLógica ;
em que
as instruções são de qualquer tipo e incluem características que devem influenciar o valor da
ExpressãoLógica.
Generalidades :
• O conjunto de instruções deste ciclo (Instrução_1, ... , Instrução_N) são executadas até que a
expressão lógica seja verdadeira (condição de paragem). Portanto, aquele conjunto de
instruções são executadas enquanto a expressão lógica for falsa.
• Como o teste à condição de paragem é efectuado no fim do ciclo, este é efectuado pelo menos
uma vez no ciclo 'While ... Do', este pode nunca ser efectuado.
Exemplos :
1. Elaborar um bloco que escreva numa tabela as potências de 2, inferiores a 1000.
i := 1 ;
potencia := 2 ;
repeat
MostrarResultados ( potencia ) ;
i := i + 1 ;
potencia := potencia * 2
until potencia > 1000 ;
Apontamentos de Delphi Pascal
Instruções
13
2. Elaborar um bloco que escreva numa tabela os primeiros 20 números inteiros e o seu dobro.
i := 1 ;
repeat
MostrarResultados ( 2 * i ) ;
i := i + 1
until i > 20 ;
10.4.3. Repetição com controlador (estrutura For)
Neste tipo de estrutura, um grupo de instruções consecutivas é executado repetidamente, um
certo número de vezes. Logo, esta instrução é uma repetição incondicional.
A forma geral da estrutura FOR é a seguinte :
for VarControlo := ExpInicial { to | downto } ExpFinal do
Instrução ;
em que,
VarControlo é uma variável pré-declarada de qualquer tipo ordenado (não reais);
ExpInicial e ExpFinal são expressões do mesmo tipo de VarControlo e constituem os limites do
domínio daquela variável, durante a execução do ciclo;
to e downto determinam se as iterações são para ser incrementadas ou decrementadas,
respectivamente, em 1 unidade. O incremento ou decremento é efectuado automaticamente;
Instrução é uma instrução de qualquer tipo, mesmo outras estruturas de controlo.
Generalidades :
• O ciclo é executado um número fixo de vezes, assumindo a variável de controlo (VarControlo)
valores de ExpInicial até ExpFinal. Portanto, este ciclo apenas pode ser utilizado quando se sabe,
à priori, o número de vezes que vai ser efectuado.
• Com a directiva to (downto) é necessário que o valor de ExpInicial seja menor (maior) ou igual
ao valor de ExpFinal. O ciclo cessa quando a variável de controlo, VarControlo, assume o valor
dado por ExpFinal.
• A VarControlo e as expressões ExpInicial e ExpFinal, não podem ser alteradas dentro do ciclo.
Exemplos :
1. Elaborar um bloco que escreva numa tabela os primeiros 20 números inteiros e o seu dobro.
for i := 1 to 20 do
MostrarResultados ( 2 * i ) ;
2. Elaborar um bloco que calcule o factorial de um número inteiro N N! = N.(N-1).... .2.1 .
fact := 1 ;
for i := N downto 1 do
factorial := factorial * i ;
10.4.4. Rotinas de controlo dos ciclos
Existem duas rotinas que permitem alterar o normal funcionamento dos ciclos, que são os
procedimentos Continue e Break.
O procedimento CONTINUE permite saltar para a próxima iteração do ciclo ou deixar o ciclo
permaturamente em resposta a uma condição específica. No entanto, as condições necessárias para
que a próxima iteração tenha sentido têm de ser garantidas.
A forma geral deste procedimento é a seguinte :
procedure Continue ;
Apontamentos de Delphi Pascal
14
Instruções
Exemplo : determinar o produto de, no máximo, 100 valores positivos (os outros são ignorados).
prod := 1 ;
for i := 1 to 100 do
begin
IntroduzirDados ( X ) ;
if X < 0 then
Continue ;
prod := prod * X ;
end ;
O procedimento BREAK permite terminar com o ciclo, saltando imediatamente para a primeira
instrução que se encontra depois do referido ciclo.
A forma geral deste procedimento é a seguinte :
procedure Break ;
Exemplo : somar valores positivos (para terminar, introduzir um valor negativo).
soma := 0 ;
while True do
begin
IntroduzirDados ( X ) ;
If X < 0 then
Break ;
soma := soma + X
end ;
10.5. Goto
A instrução GOTO é uma instrução simples, que é usada para alterar a sequência de execução
de um programa, transferindo o controlo (saltando) para uma parte diferente do mesmo programa.
A forma geral da instrução GOTO é a seguinte :
Goto Etiqueta ;
onde Etiqueta representa um inteiro positivo inferior a 9999.
Cada etiqueta deve ser declarada antes de poder ser utilizada no programa (deve preceder as
declarações de constantes e variáveis).
As declarações das etiquetas é feito da seguinte forma :
Label
Etiqueta_1, Etiqueta_2, ... , Etiqueta_N ;
onde Etiqueta_1, Etiqueta_2, ..., Etiqueta_N representam as etiquetas de instruções individuais.
As etiquetas de instrução são escritas sob a seguinte forma :
Etiqueta : Instrução ;
em que as instruções podem preceder ou suceder as instruções GOTO.
Nota :
Podem ser efectuados saltos (GOTO) dentro do mesmo nível de estrutura ou para fora de
estruturas (ciclos, subprogramas, ...) mas nunca para dentro de estruturas.
Generalidades :
• A execução de uma instrução GOTO obriga a uma transferência de controlo para a
correspondente instrução etiquetada. Portanto, essa instrução é a próxima a ser executada.
Apontamentos de Delphi Pascal
Tabelas (“Arrays”)
•
•
•
•
•
•
•
15
Um programa pode conter várias instruções GOTO diferentes que transferem o controlo para o
mesmo lugar do programa. No entanto, cada instrução etiquetada deve ter a sua própria
etiqueta específica (não podem existir 2 instruções "objectivo" com a mesma etiqueta).
O controlo pode ser transferido para fora, para dentro e para o princípio de uma instrução
composta. No entanto, o controlo não pode ser transferido para o meio de uma dessas
instruções.
Além disso, se o controlo é transferido internamente para o fim (END) de uma instrução
composta (END etiquetado), então a etiqueta deve ser precedida por uma instrução vazia (;).
Isto é, colocar ponto e vírgula a seguir à instrução que precede END.
É sempre possível não utilizar GOTO's.
Um programa que utiliza GOTO's perde toda a clareza, pois a estrutura do algoritmo deixou de
ser facilmente detectada pela leitura do programa. Ou seja, este tipo de instrução é típica de
linguagens de programação não-estruturada (o que não é o caso do Pascal).
A instrução GOTO deve ser encarada como uma instrução demasiado poderosa e usada apenas
como último recurso.
A instrução GOTO é utilizada positivamente como saída directa de um processo recursivo.
11. Tabelas (“Arrays”)
Até aqui, os tipos de dados estudados têm a característica comum de, aquando da declaração de
variáveis destes tipos, cada uma representar um único elemento. No tipo de dados estruturados
("arrays"), um único identificador pode representar múltiplos elementos (variáveis), os quais, podem
ser acedidos individualmente e separadamente. No entanto, os "arrays" têm um número fixo de
componentes e todas do mesmo tipo.
11.1. Tabela de uma dimensão
11.1.1. Definição
Os "arrays" de uma dimensão podem ser imaginados como uma lista de elementos, todos do
mesmo tipo; ou seja, um vector.
A maneira mais útil e usual de definir (construir) um "array" de uma dimensão, é inseri-la como
parte da declaração de tipo, da seguinte forma :
type
Nome = array [ TipoIndice ] of Tipo ;
em que,
Nome é o identificador do tipo estruturado que se pretende criar;
TipoIndice é o tipo dos índices das componentes (tem de ser simples ordenado e definido por
subdomínio por ex., TipoIndice = Indice_1 . . Indice_N);
Tipo corresponde ao tipo das componentes e pode ser qualquer (incluindo estruturados).
11.1.2. Declaração de variáveis
Existem duas formas de declarar variáveis deste tipo : declarando variáveis de um tipo já
definido ou introduzindo a definição do tipo na declaração das variáveis.
A síntaxe para a primeira forma é a seguinte :
var
Nome_1, ... , Nome_N : NomeTipo ;
A síntaxe da segunda forma é a seguinte :
var
Nome_1, ... , Nome_N : array [ TipoIndice ] of Tipo ;
Apontamentos de Delphi Pascal
16
Tabelas (“Arrays”)
11.1.3. Declaração de constantes
A síntaxe da declaração de constantes de um tipo destes é a seguinte :
const Nome : NomeTipo = ( Valor_1, Valor_2, … , Valor_N ) ;
em que N corresponde ao número de elementos do conjunto TipoIndice (número de elementos do
“array” ou tabela).
11.1.4. Identificação dos elementos
Os elementos do "array" são identificados escrevendo a variável declarada como do tipo
NomeTipo, seguido pelo seu índice entre parêntesis recto :
NomeVariável [índice]
11.1.5. Representação gráfica
Considere-se uma tabela unidimensional com 8 elementos do tipo carácter.
0
1
2
3
4
5
6
7
M [ 0 ] = ‘F’
M [ 2 ] = ‘G’
‘F’
‘A’
‘G’
‘C’
‘B’
‘E’
‘H’
‘D’
M [ 3 ] = ‘C’
M : array [ 0 . . 7 ] of Char ;
M [ 6 ] = ‘H’
M [ 7 ] = ‘D’
11.1.6. Generalidades
O tipo dos índices das componentes pode ser um qualquer simples ordenado (excepto reais),
mas considerando apenas subdomínios. Ou seja, o índice é do tipo escalar não real, mas
também não pode tomar todo o domínio dos inteiros, nem todo o domínio dos caracteres, mas
apenas subdomínios daqueles conjuntos.
Os elementos individuais de um vector podem ser usados em expressões, instruções de
atribuição, etc., como se fossem variáveis.
O valor do índice pode ser expresso como uma constante, uma variável ou uma expressão.
Contudo o índice deve ser do tipo correcto e estar dentro do intervalo correcto.
11.1.7. Exemplos
1. Declaração de um tipo de nome vector, com 100 elementos do tipo real, e de uma variável.
type vector = array [1 . . 100] of Real;
var
x : vector;
Para se aceder ao elemento k (1 ≤ k ≤ 100), basta escrever x [k]. Por ex., para k=34, x [34].
No entanto, a declaração
var
x : array [ 1 . . 100 ] of Real;
é equivalente às duas anteriores, se se pretende apenas declarar uma variável daquele tipo.
2. Declaração de uma variável indexada de nome vencimentos, com 6 elementos do tipo real.
var Vencimentos : array [ 'A' . . 'F' ] of Real ;
Para se aceder ao elemento de índice 'C', basta escrever vencimentos ['C'].
3. Definir 2 tipos e declarar constantes evariáveis desses tipo.
type
Dia_Semana = ( Segunda, Terça, Quarta, Quinta, Sexta, Sábado, Domingo ) ;
Gastos = array [ Dia_Semana ] of Real ;
const GastosIniciais : Gastos = ( 15.5, 25.8, 23.9, 14.75, 18.0, 20.5, 22.3 ) ;
var
A, B, C : Gastos ;
Apontamentos de Delphi Pascal
Tabelas (“Arrays”)
17
11.2. Tabela de duas dimensões
11.2.1. Definição
Pode-se pensar em "arrays" de 2 dimensões como uma tabela de elementos, formada por linhas
e colunas. O primeiro índice corresponde ao nº da linha e o segundo ao nº da coluna; ou seja, uma
matriz. Independentemente da sua dimensão, um "array" bidimensional (matriz) consiste sempre
numa colecção de elementos do mesmo tipo.
A maneira mais útil e usual de definir (construir) um "array" de duas dimensão, é inseri-la
como parte da declaração de tipo, da seguinte forma :
type
Nome = array [ TipoIndice1, TipoIndice2 ] of Tipo ;
em que,
Nome é o identificador do tipo estruturado que se pretende criar;
TipoIndice1 e TipoIndice2 são os tipos dos índices das componentes e podem ser diferentes;
Tipo corresponde ao tipo das componentes.
11.2.2. Declaração de variáveis
Existem duas formas de declarar variáveis deste tipo : declarando variáveis de um tipo já
definido ou introduzindo a definição do tipo na declaração das variáveis.
A síntaxe para a primeira forma é a seguinte :
var
Nome_1, ... , Nome_N : NomeTipo ;
A síntaxe da segunda forma é a seguinte :
var
Nome_1, ... , Nome_N : array [ TipoIndice1, TipoIndice2 ] of Tipo ;
11.2.3. Declaração de constantes
A síntaxe da declaração de constantes de um tipo destes, é a seguinte :
const
Nome : NomeTipo = ( (Val_11, …, Val_1N ), … , (Val_M1, …, Val_MN ) ) ;
em que M e N são o número de elementos dos conjuntos TipoIndice1 e TipoIndice2, respectivamente
(ou seja, as quantidades de linhas e colunas, respectivamente).
11.2.4. Identificação dos elementos
Os elementos do "array" são identificados escrevendo a variável declarada como do tipo
NomeTipo, seguido pelos índices da linha e coluna, entre parêntesis recto :
NomeVariável [indice1, indice2].
11.2.5. Representação gráfica
Considere-se uma tabela bidimensional com 28 elementos do tipo carácter (4 linhas e 7 colunas).
j=1 j=2 j=3 j=4 j=5 j=6 j=7
M [ 0, 1 ] = −9.0
i = 0 −9.0
i=1
i=2
i=3
12.7
3.45
5.78
M [ 0, 7 ] = 12.7
M [ 1, 3 ] = 3.45
65.7
M [ 1, 5 ] = 5.78
1.5
M : array [ 0 . . 3, 1 . . 7 ] of Real ;
Apontamentos de Delphi Pascal
M [ 2, 4 ] = 65.7
M [ 3, 6 ] = 1.5
18
Registos
11.2.6. Exemplos
1. Definir um "array" de 2 dimensões de nome quadro com 66 elementos (6 × 11) reais, indexados
por [i, j] (i = -10, ... , -5 e j = -5, ... , 5) e declaração de uma variável q daquele tipo.
type quadro = array [ -10 . . -5, -5 . . 5 ] of Real ;
var q : quadro ;
2. Definição de um "array" de 2 dimensões de nome tabuleiro, constituído por 8 × 8 = 64
elementos do tipo cor (definido antes), indexados por [i, j] ( i, j = 1, ... , 8) e declaração de uma
variável de nome tab daquele tipo.
type cor = ( branco, preto ) ;
tabuleiro = array [1 . . 8, 1 . . 8] of cor ;
var
tab : tabuleiro ;
A definição do tipo de nome tabuleiro é equivalente à seguinte definição :
type tabuleiro = array [1 . . 8] of array [1 . . 8] of cor ;
3. Sabendo que
var
M : array [1 . . 10, 1 . . 10] of integer ;
uma secção de programa para determinar o número de elementos nulos é a seguinte :
nulos := 0 ;
for i := 1 to 10 do
for j := 1 to 10 do
if M [i, j] = 0 then
nulos := nulos + 1 ;
11.3. "Arrays" de várias dimensões
Independentemente da sua dimensão, um "array" consiste sempre numa colecção de elementos
do mesmo tipo. Todos os elementos podem ser colectivamente referidos por um único identificador
(o nome comum do "array").
A forma geral da definição de um "array" de dimensão N é a seguinte :
type
Nome = array [ TipoIndice1, . . . , TipoIndiceN ] of Tipo ;
em que,
Nome é o identificador do tipo estruturado que se pretende criar;
TipoIndice1, ..., TipoIndiceN são os tipos dos índices das componentes e podem ser diferentes;
Tipo corresponde ao tipo das componentes.
Observação :
Tudo o que se disse para os "arrays" de 1 e 2 dimensões, aplica-se aos de várias dimensões.
12. Registos
12.1. Definição
Os registos são um tipo de dados estruturados, com um número fixo de componentes (campos
do registo), os quais podem ser de diferentes tipos.
Pode-se definir um registo incluindo-o como parte de uma declaração de tipo ou de variável.
No entanto, a forma mais útil e usual é quando se declara como tipo.
Apontamentos de Delphi Pascal
Registos
19
A forma geral da definição do tipo registo é a seguinte :
type
Nome = record
ListaCampos_1 : Tipo_1 ;
...
ListaCampos_N : Tipo_N
end ;
em que
Tipo_k (1 ≤ k ≤ N) pode ser de qualquer tipo definido pelo utilizador ou padrão;
ListaCampos_k representa o grupo de campos do Tipo_k (1 ≤ k ≤ N), em que a sua declaração é
feita numa maneira semelhante a um conjunto de variáveis.
12.2. Declaração de variáveis
Existem duas formas de declarar variáveis deste tipo : declarando variáveis de um tipo já
definido ou introduzindo a definição do tipo na declaração das variáveis.
A síntaxe para a primeira forma é a seguinte :
var
Var_1, Var_2, . . ., Var_M : Nome_Registo ;
A síntaxe para a segunda forma é a seguinte :
var
Var_1, Var_2, . . ., Var_M : record
ListaCampos_1 : Tipo_1 ;
...
ListaCampos_N : Tipo_N
end ;
12.3. Declaração de constantes
A síntaxe da declaração de constantes de um tipo destes, é a seguinte :
const
Nome : Nome_Registo = ( Campo_1 : Val_1, … , Campo_N : Val_N) ;
em que N é o número de campos do registo.
12.4. Exemplos
type
var
Complexo = record
Re, Im : Real ;
end ;
Data = record
Dia : 1 . . 31 ;
Mes : 1 . . 12 ;
Ano : 1900 . . 2000
end ;
Z1, Z2 : Complexo ;
Sistema : Array [1 . . 10] Of Complexo ;
Aniversario : Data ;
Cliente_1, Cliente_2 : record
Nome : String ;
Numero : 1 . . 9999 ;
Saldo : Real ;
end ;
Apontamentos de Delphi Pascal
20
Registos
12.5. Observações
Um registo pode ser um campo num outro registo, assim como se pode definir tabelas cujos
elementos sejam registos, registos cujos campos (ou alguns) sejam tabelas, e assim
sucessivamente.
Cada registo é considerado como uma entidade autónoma no que diz respeito às definições de
campo. Portanto, cada campo dentro de um dado registo deve ter um nome único, mas o
mesmo nome de campo pode ser usado em diferentes registos.
12.6. Acesso aos campos do registo
O acesso a cada uma dos campos dum registo é feito através de uma combinação do nome
duma variável do tipo registo e do campo que se pretende aceder, separados por um ponto (.). Isto é,
Variável.Campo
Se um campo representa um elemento estruturado, então os elementos desse campo podem ser
acedidos incluindo o elemento estruturado na designação de campo. Por exemplo, se um campo
representa uma tabela, um seu elemento pode ser acedido pela expressão
Variável.Campo [índice]
Identicamente, se um campo representa um registo, um elemento desse registo pode ser
acedido pela expressão
Variável.Campo.Subcampo
onde Subcampo refere-se a um campo dentro desse registo.
Se definir-se uma tabela unidimensional (vector) cujos elementos sejam registos, a acesso a um
desses registos é feito através da seguinte forma :
Tabela [indice]
e o acesso a um determinado campo é feito da seguinte forma :
Tabela [indice].Campo
Exemplos :
Z1.Re := 2 ;
Z1.Im := -3 ;
Aniversario.Dia := 1 ; Aniversario.Mes := 4 ; Aniversario.Ano := 1994.
Sistema[5].Re := -1 ;
Sistema[5].Im := 2 ;
Observação :
Os campos de um registo podem ser utilizados da mesma forma que as variáveis normais. As
características particulares que se aplicam a cada campo são determinadas pelo seu tipo.
12.7. A instrução WITH
A necessidade de especificar várias designações de campo, pode tornar-se fastidiosa e reduzir a
legibilidade do programa. Em tais situações, a estrutura WITH permite referenciar as componentes
de um registo, utilizando apenas os seus identificadores de campo (omitindo o nome do registo).
A forma geral da estrutura WITH é a seguinte :
with VarRegisto do
Instrução ;
ou se 2 ou mais variáveis de registo são incluídos na estrutura :
with VarRegisto_1, . . . , VarRegisto_N do
Instrução ;
Apontamentos de Delphi Pascal
Registos
21
A parte da instrução na estrutura refere-se a qualquer instrução executável, podendo ser
estruturada. Dentro desta instrução qualquer referência a um campo duma das variáveis de registo
especificadas, não necessita de incluir o respectivo nome, a não ser que aquele nome de campo seja
comum a 2 ou mais variáveis.
Se um nome de campo é comum a 2 ou mais registos, o seu âmbito é limitado ao registo mais
interno. Qualquer referência a um campo com o mesmo nome, mas associado a outra variável de
registo, deve incluir o nome daquela variável como parte da designação de campo.
A forma geral especificada em segundo lugar é equivalente à seguinte estrutura encaixada :
with VarRegisto_1 do
...
with VarRegisto_N do
Instrução ;
Por esta razão é que, se um nome de campo é comum a 2 ou mais registos, o seu âmbito é
limitado ao registo mais interno (última variável de registo especificada).
Exemplos :
with Z1, Z2 do
begin
Re := 2 ;
Im := -3
end ;
{ Z1 = ? ; Z2 = 2 −3 i }
with Aniversario do
begin
Dia := 1 ;
Mes := 4 ;
Ano := 1994
end ;
12.8. Operações com registos
O tipo mais simples de operação que envolve registos, é a atribuição de uma variável de registo
completo a outra. Isto obriga a que ambas as variáveis tenham a mesma composição, isto é, que sejam
do mesmo tipo de registo. Por exemplo, Z1 := Z2 ;
No entanto, as operações mais comuns são aquelas que envolvem os elementos individuais da
variável de registo (campos).
12.9. Registos variantes
Até agora, apenas se consideraram registos cuja composição se mantém invariável ao longo do
programa. Contudo, também é possível definir um registo cuja composição (ou parte) possa variar ao
longo do programa, dependendo do valor que é atribuído a um dado campo do registo (o campo das
etiquetas). Tal registo designa-se por registo variante (ou parte variante do registo).
A forma geral da parte variante de um registo, é a seguinte :
case CampoEtiquetas : Tipo of
Etiqueta_1 : ListaCamposVariantes_1 ;
...
Etiqueta_N : ListaCamposVariantes_N
{ Variante_1 }
{ Variante_N }
em que,
CampoEtiquetas é um tipo ordenado já definido anteriormente;
Tipo fora previamente definido por enumeração ou subdomínio (ou Boolean);
ListaCamposVariantes_k (1 ≤ k ≤ N) é expressa sob a forma de uma enumeração de campos, isto é,
( CampoVariante_1, ... , CampoVariante_M )
Cada valor do tipo associado ao CampoEtiquetas deve aparecer uma vez (e uma só vez) como
uma etiqueta de CASE, na parte variante subsequente da definição do registo. A parte activa do
Apontamentos de Delphi Pascal
22
Registos
registo consistirá então nos campos que correspondem a uma dada etiqueta de CASE, correspondente
ao valor atribuído ao identificador do campo das etiquetas.
Os campos de um registo variante e o identificador de campo das etiquetas podem ser acedidos
da mesma maneira que os campos dos registos fixos.
Exemplo :
type
Divisoes = ( Primeira, Divisao_Honra, Segunda_B, Terceira ) ;
Equipa = record
Nome : String ;
{ parte fixa } Jogos, Vitorias, Empates, Derrotas : 0 . . 34 ;
Pontos : 0 . . 102 ;
case Divisao : Divisoes of
Primeira : ( ) ;
{ parte variante } Divisao_Honra : ( ) ;
Segunda_B : ( Zona : ( Norte, Centro, Sul ) ) ;
Terceira : ( Serie : ( 'A' . . 'F' ) ) ;
end ;
Generalidades :
Só pode haver uma parte variante em cada registo que está sempre depois da sua parte fixa.
A um “CampoEtiquetas” corresponde uma só “ListaCamposVariantes”.
Todas as possíveis variantes devem aparecer listadas. Se a uma etiqueta não corresponder
nenhum novo campo indicar ( ).
A cada variante corresponde uma só lista de campos (que por sua vez pode ter variantes).
É possível definir um registo sem parte fixa.
A estrutura WITH pode ser usada, tanto com registos do tipo variante como do tipo fixo.
Se um campo variante individual for acedido, então deve estar atribuído um valor apropriado
ao identificador do campo das etiquetas.
Os nomes dos campos num registo, incluindo os dos campos variantes, devem ser únicos.
Embora um dado registo possa ter só uma parte fixa e uma parte variante, é possível incluir
uma definição variante noutra. Pode-se criar campos variantes encaixados num único registo.
Advertência :
Um novo grupo de campos variantes torna-se activo, sempre que um novo valor for atribuído
ao identificador de campo das etiquetas. Além disso, se o identificador de campo das etiquetas não
existir, então um novo grupo de variantes ficará activo como resultado de uma referência a um
campo variante não activo. Qualquer mudança inadvertida (ou indesejada) nos campos variantes
activos podem, portanto, ser evitada. Este problema surge nos programas que utilizam
subprogramas.
Para minimizar a probabilidade de tais erros, uma mudança de variante não é permitida nas
seguintes circunstâncias :
• numa estrutura WITH se um nome de um campo variante aparece naquela instrução.
• sempre que um campo variante tenha sido transferido para um subprograma como um
parâmetro actual passado por referência.
Além disso, um identificador de campo das etiquetas não pode ser transferido para um subprograma
como parâmetro actual passado por referência.
Apontamentos de Delphi Pascal
Conjuntos (“SET”)
23
12.10. Registos de registos (exemplo)
Existe a possibilidade de um campo dum registo ser também um registo.
type
Pessoa = record
Nome : record
Proprio, Apelido : String;
end ;
BIdentidade : Integer ;
Sexo : ( Masculino, Feminino ) ;
DNascimento : Data
end ;
12.11. Variantes com variantes (exemplo)
type
Tipodomeio
Tipodometodo
Tipodomaterial
Instrumento
=
=
=
=
( Cordas, Sopro ) ;
( Percursao, Arco ) ;
( Metal, Madeira ) ;
record
case Meio : Tipodomeio of
Cordas : ( case Metodo : Tipodometodo of
Percursao : ( case Teclado : Boolean of
False : (Gama : 1 . . 20000) ;
True : (Teclas : 1 . . 100)
)
Arco : ( Tamanho : (Viola, Violoncelo, Violino) )
)
Sopro : ( case Material : Tipodomaterial of
Metal : ( Tecnica : (Pistoes, Vara) ) ;
Madeira : ( Palheta : (Simples, Dupla) )
)
end;
13. Conjuntos (“SET”)
Em Delphi Pascal, define-se formalmente um conjunto (SET), como uma colecção de objectos
do mesmo tipo (simples e ordenado). Portanto, um conjunto pode ser uma colecção de inteiros,
caracteres ou elementos enumerados.
13.1. Definição
Pode-se definir um conjunto incluindo-o como parte de uma declaração de tipo ou de variável.
No entanto, a forma mais útil e usual é quando se declara como tipo.
A Definição dum conjunto como tipo, pode ser feita de 2 maneiras :
• Começa-se por construir um tipo de dados (TipoBase), cujos elementos são simples e
ordenados; depois, define-se o tipo conjunto que se deseja, em termos do tipo base. Ou seja,
type
TipoBase = ( Elem1, ..., ElemN ) ;
TipoBase = PrimElem . . UltElem ;
TipoConjunto = set of TipoBase ;
• O TipoBase é construído aquando da definição do tipo conjunto. Ou seja,
type
TipoConjunto = set of ( Elem1, ..., ElemN ) ;
type
TipoConjunto = set of PrimElem . . UltElem ;
Apontamentos de Delphi Pascal
24
Conjuntos (“SET”)
A definição dum conjunto como variável, também pode ser feita de 2 maneiras :
• Começa-se por construir o TipoBase e, depois, são declaradas variáveis, em termos do tipo
base. Ou seja,
type
TipoBase = ( Elem1, ... , ElemN ) ;
PrimElem . . UltElem ;
var
Var1, ..., VarN : set of TipoBase ;
• O TipoBase é construído aquando da declaração das variáveis de conjunto. Ou seja,
var
Var1, ..., VarN : set of ( Elem1, ... , ElemN ) ;
Var1, ..., VarN : set of PrimElem . . UltElem ;
Observações :
• Cada variável de conjunto, pode representar um subconjunto de elementos do TipoBase.
• Pode-se também definir um conjunto em termos de um tipo simples, padrão e ordenado (por
ex., inteiros e caracteres), ou de uma gama de valores de um tipo simples, padrão e ordenado.
Em tais situações, o referido tipo torna-se no TipoBase.
Exemplos :
type
var
cor_primaria
cor
conj_alg
=
=
=
( vermelho, amarelo, azul ) ;
set of cor_primaria ;
set of 0 . . 9 ;
roxo, verde, castanho : cor ;
conj_letras : set of 'a' . . 'z' ;
13.2. Construção de um conjunto
Cada elemento do conjunto consiste na enumeração (ordenada ou não) de elementos da base,
separados por vírgulas (,) e delimitados por parêntesis rectos ([ ]).
A forma geral para a construção de um conjunto, é a seguinte :
[ Expr1, Expr2, ..., ExprN ]
onde os valores associados às expressões incluídas são do mesmo tipo do tipo base e, são conhecidos
por elementos do conjunto. Estas expressões podem ser constantes, variáveis, etc.
Se alguns dos elementos do conjunto são valores consecutivos, então podem ser representados
como uma gama de valores.
13.3. Exemplos
1.
2.
3.
4.
5.
6.
7.
verde := [amarelo, azul] ;
castanho := [vermelho, amarelo, azul] ;
preto := [ ] ;
conj_letras := ['s', 'e', 't'] ;
[13] ;
[i+j, i-j] ;
['0' . . '9', 'A', 'B', 'C'] ;
13.4. Generalidades
•
Uma colecção de elementos não pode ser incluída num conjunto mais do que uma vez. Contudo, é
possível que um único elemento seja especificado uma ou mais vezes, particularmente se a
especificação do conjunto incluir quer elementos explícitos quer variáveis (uma variável pode
representar um elemento do conjunto que já foi especificado, resultando, portanto, numa
duplicação desejada). Em tais situações, a especificação repetida é ignorada.
Apontamentos de Delphi Pascal
Conjuntos (“SET”)
•
•
•
•
•
25
Exemplo : [ amarelo, azul, cor ]
Se cor for amarelo ou azul aquele conjunto é formado por amarelo e azul (o outro é repetido).
Se cor for vermelho aquele conjunto é formado por amarelo, azul e vermelho.
O mesmo acontece se alguns elementos do conjunto forem expressos como gama de valores. Se o
1º e o último da gama forem o mesmo, então a gama será interpretada como um único elemento.
Além disso, se a ordem do 1º for superior à do último, então o conjunto é vazio.
Exemplos :
a) [ '9'. .'6', 'A', 'B', 'C' ] ≡ [ 'A', 'B', 'C' ]
b) [ '0'. .'0', 'A', 'B', 'C' ] ≡ [ '0', 'A', 'B', 'C' ]
Um conjunto pode conter um único elemento, vários elementos ou estar vazio ([ ]).
O nº máximo de elementos da base depende do computador utilizado.
Para N elementos da base, existem 2N elementos possíveis do SET.
Uma vez construído um conjunto, este pode ser atribuído a uma variável do mesmo tipo,
utilizando uma instrução de atribuição, da seguinte forma :
Variável := [ Expr1, Expr2, ..., ExprN ]
13.5. Operações com conjuntos
Existem 3 operações diferentes que podem ser efectuadas em conjuntos, resultando daí novos
conjuntos. Estes novos conjuntos designam-se por conjunto união, intercepção e diferença, dos 2
conjuntos iniciais, conforme o caso.
As 3 operações são as seguintes :
União
+
Ex: [ verde, azul ] + [ verde, preto ] → [ verde, azul, preto ]
×
Intercepção
Ex: [ verde, azul ] * [ verde, preto ] → [ verde ]
Complementar
−
Ex: [ verde, azul ] − [ verde, preto ] → [ azul ]
13.6. Comparação de conjuntos
Pode-se utilizar 4 operadores relacionais a conjuntos para formar expressões lógicas. Estes
operadores são os seguintes :
Igualdade
=
Os conjuntos contém os mesmos elementos, por qualquer ordem.
Desigualdade
<> Os conjuntos não contém exactamente os mesmos elementos.
Está Contido
<= Todos os elementos do 1º conjunto pertencem ao 2º.
Contém
>= Todos os elementos do 2º conjunto pertencem ao 1º.
13.7. Teste de pertença
Existe um operador relacional adicional, IN, que é usado para formar expressões lógicas. Este
operador permite determinar se um dado valor pertence ou não a um dado conjunto (se o valor é ou
não elemento do conjunto).
Este operador é usado da seguinte forma :
Expressão IN Conjunto ;
em que,
Expressão, é um elemento dum conjunto ou uma variável, desde que pertença ao conjunto,
Conjunto, é geralmente um conjunto ou uma variável do tipo conjunto.
Exemplo :
If not dia IN [1 . . 31] Then writeln ('Não é dia do mês de Abril') ;
Apontamentos de Delphi Pascal
26
Subprogramas
13.8. Problema
O Crivo de Eratóstenes é o método mais eficiente para gerar os números primos (2 ... N), pois
não efectua multiplicações nem divisões. Este método consiste nos seguintes passos :
1. Considerar o conjunto com todos os números inteiros de 2 até N.
2. O 1º elemento daquele conjunto é primo; logo, é colocado no conjunto dos primos.
3. Retirar do conjunto aquele elemento, assim como todos os seus múltiplos.
4. Voltar ao passo 2, até que o conjunto fique vazio.
Resolução (Algoritmo) :
Inicializar os 2 conjuntos (Crivo e Primos)
Enquanto o Crivo não ficar vazio
Procurar o 1º elemento do Crivo (que é primo)
Acrescentar aquele elemento ao conjunto dos Primos
Retirar aquele elemento e todos os seus múltiplos do Crivo
14. Subprogramas
14.1. Introdução
As aplicações (programas) em Delphi Pascal podem ser escritos facilmente numa forma
modular, permitindo que um problema global seja decomposto numa sequência de subproblemas
individuais. A modularidade proporciona 2 importantes vantagens :
Para tarefas que devem ser efectuadas mais do que uma vez a modularidade evita a necessidade
de programação redundante (repetida) do mesmo conjunto de instruções. Em vez disso, cada
módulo pode ser definido uma vez e depois acedido de vários pontos diferentes do programa.
Um conjunto diferente de dados pode ser processado de cada vez que o módulo é acedido. O uso
de módulos num programa pode reduzir consideravelmente o comprimento do programa.
De ainda maior importância é a clareza lógica resultante da decomposição de um programa em
módulos individuais e concisos, em que cada módulo representa uma parte bem definida do
problema global. Tais programas são mais fáceis de escrever e corrigir, e a sua estrutura lógica é
mais evidente do que programas que não tenham este tipo de estrutura. Isto é particularmente
verdade em relação a programas muito compridos e complicados. Muitos programas em Pascal
estão modularizados ainda que não envolvam a execução repetida das mesmas tarefas. De facto,
a decomposição de um programa em módulos individuais é geralmente considerada uma parte
importante de uma boa prática de programação.
Em Delphi Pascal existe dois tipos de módulos (subprogramas ou rotinas) : procedimentos e
funções. Apesar destas estruturas serem semelhantes, são acedidas e trocam informação de forma
diferente.
14.2. Conceito de procedimento (procedure)
Um procedimento é uma subdivisão do programa em unidades correspondentes a
subproblemas definidos durante o desenvolvimento do algoritmo.
O compilador do Delphi Pascal possuí procedimentos predefinidos, tais como : continue, break,
writeln, readln, etc. .
Apontamentos de Delphi Pascal
Subprogramas
27
14.2.1. Definição
A estrutura geral de um procedimento é a seguinte forma :
procedure Nome ( ListaParâmetrosFormais ) ;
declarações
begin
instruções
end;
{ cabeçalho }
em que,
ListaParâmetrosFormais consiste numa sequência de parâmetros (pode ser vazia), os quais estão
associados à troca de informação (entrada/saida) entre o procedimento e o local de chamada;
declarações é onde se declaram os identificadores locais (que apenas são utilizados dentro do
procedimento;
instruções traduzem o algoritmo necessário para calcular o resultado pretendido, utilizando os
informação introduzida pelo cabeçalho.
14.2.2. Chamada
Um procedimento é referenciado (chamado) simplesmente escrevendo o seu nome, seguido por
uma lista de parâmetros reais, tal como se mostra a seguir :
NomeProcedimento ( ListaParâmetrosActuais ) ;
em que,
ListaParâmetrosActuais está relacionada com a ListaParâmetrosFormais, contendo exactamente
a mesma quantidade de parâmetros, dos mesmos tipos e a mesma sequência.
14.2.3. Exemplo
procedure maximo ( x, y : real ; var max : real ) ;
begin
if (x > y) then max := x
else max := y
end ;
O parâmetro max (variável real) é que devolve o resultado pretendido pelo procedimento.
Exemplos de chamadas do procedimento maximo :
maximo ( 4.5, 7.8, M )
{ M variável real }
maximo ( a, b, c ) ;
{ a, b variáveis ou constantes reais; c variável real }
14.3. Conceito de função (function)
Uma função é um subprograma, em muitos aspectos semelhante ao procedimento que, ao
contrário daquele, fornece apenas um valor no seu ponto de chamada.
O compilador de Delphi Pascal possuí funções standard, tais como : round, sqrt, sqr, exp, ... .
14.3.1. Definição
A estrutura geral de um procedimento é a seguinte forma :
function Nome ( ListaParâmetrosFormais ) : Tipo ;
declarações
begin
instruções
end;
Apontamentos de Delphi Pascal
{ cabeçalho }
28
Subprogramas
em que,
ListaParâmetrosFormais consiste numa sequência de parâmetros (pode ser vazia), os quais estão
associados à entrada de informação para a função;
Tipo especifica o tipo de dados do resultado produzido pela função;
declarações é onde se declaram os identificadores locais (que apenas são utilizados dentro da
função;
instruções traduzem o algoritmo necessário para calcular o resultado pretendido, utilizando os
informação introduzida pelo cabeçalho; numa destas instruções, ao identificador que representa o
nome da função deve ser atribuído o valor que a função fornece ao seu ponto de chamada (isto é, o
resultado da execução da função, que é um elemento do tipo Tipo).
Podem ser atribuídos valores ao nome da função em 2 ou mais pontos do bloco; no entanto,
uma vez feita uma atribuição esta não pode ser alterada posteriormente.
14.3.2. Chamada
A função é chamada, não por uma instrução de chamada (como nos procedimentos), mas por
qualquer expressão que envolva o cálculo do seu valor. Ou seja, especificando o seu nome numa
expressão como se fosse uma normal variável. O nome da função deve ser seguido por uma lista de
parâmetros actuais, a qual está relacionada com a lista de parâmetros formais. Portanto, não existe
uma forma geral de chamada da função, pois depende de como se pretende utilizar.
14.3.3. Exemplo
function maximo ( x, y : real ) : real ;
begin
if x > y then maximo := x
else maximo := y
end ;
Note-se que é a instrução maximo := x (y) que atribui o valor do máximo ao resultado da função.
Exemplos de chamadas da função maximo :
m := 2 * maximo (a, b);
x := maximo (x, maximo (y, z) );
MostrarResultados (maximo (k, 2.5) );
14.4. Generalidades
•
•
•
•
•
•
•
•
•
•
Quando um subprograma é chamado, o controlo é automaticamente transferido para o
princípio do subprograma. As instruções de execução dentro do subprograma são então
executadas, tomando em conta quaisquer declarações especiais que sejam únicas ao
subprograma. Quando todas as instruções de execução tiverem sido executadas, o controlo é
automaticamente devolvido à instrução imediatamente a seguir à chamada do subprograma.
Cada subprograma pode ser chamado várias vezes no mesmo programa, assim como pode ser
chamado por outros subprograma (procedimentos e funções).
Os subprogramas podem (em certos casos) ser testados independentemente.
O subprograma já testado, pode ser utilizado em novos programas.
Quanto mais complexo o programa, maior a necessidade de subdivisão em subprogramas.
Os subprogramas aumentam a clareza do programa, tornando mais simples a sua compreensão,
modificação ou extensão.
A utilização de subprograma reduz :
o comprimento total do programa,
as áreas de potenciais erros,
o esforço de programação.
Apontamentos de Delphi Pascal
Subprogramas
29
14.5. Declaração dos subprogramas
Os subprogramas são declarados na zona reservada a declarações, imediatamente antes da
palavra-chave BEGIN do corpo do programa principal.
Dentro de um mesmo programa, não existe uma ordem para a escrita dos subprogramas.
Apenas se um determinado subprograma faz uso de outros subprogramas, estes têm que estar
declarados antes.
14.6. Domínio dos identificadores
O domínio de um identificador refere-se à região na qual o identificador está declarado e pode
ser utilizado. Este conceito aplica-se a todos os tipos de declarações, e não somente a variáveis e
constantes.
Os identificadores que aparecem nas instruções de execução de um subprograma podem ter
sido declarados externamente, num bloco de programa que contém o subprograma, ou localmente,
dentro do próprio subprograma.
Os identificadores que são declarados dentro de um bloco que contém o subprograma podem
ser utilizados em qualquer ponto dentro desse bloco, quer internamente quer externamente ao
subprograma identificadores globais ao subprograma.
Os identificadores locais não são definidos fora do subprograma e, portanto, não podem ser
utilizados externamente.
Exemplo :
program amostra (input, output) ;
var a, b, c : integer ;
procedure máximo ;
var max : integer ;
begin
if a > b then max := a
else max := b ;
if c > max then max := c ;
Writeln ('O máximo é ', max )
end ;
begin
Writeln ('Quais os valores de a, b e c ?') ;
Readln (a, b, c) ;
while (a <> 0) do
begin
maximo ;
Writeln ('Quais os valores de a, b e c ?') ;
Readln (a, b, c)
end
end .
Identificadores locais ao procedimento maximo : max.
Identificadores globais ao procedimento maximo : a, b, c.
Generalidades :
• Os identificadores locais são preferíveis aos globais, desde que isto não seja inconsistente
com a lógica global do programa. Desta forma, o programa torna-se mais legível. Também
minimiza a probabilidade de erros de programação causada por referências incorrectas ou
inconsistentes aos identificadores.
Apontamentos de Delphi Pascal
30
Subprogramas
•
•
•
É possível utilizar o mesmo identificador para representar entidades diferentes em partes
diferentes de um programa (um identificador declarado localmente dentro de um
subprograma, pode ter o mesmo nome de um outro declarado globalmente que foi declarado
externamente). Em tais situações, a definição local terá maior precedência no seu domínio;
contudo, fora deste domínio, o identificador local está indefinido.
A utilização de identificadores locais facilita a minimização do espaço de memória usado por
esses identificadores.
É possível declarar um subprograma dentro de outro, permitindo que os subprogramas
sejam encaixados uns dentro dos outros. Nestes casos, um subprograma não pode ser
chamado de fora do bloco que o contém.
14.7. Parâmetros
Muitos programas em Pascal requerem que a informação seja transferida entre um
subprograma e o ponto em que o subprograma é chamado.
Uma maneira de conseguir isto, é utilizar variáveis globais, apesar de existirem alguns aspectos
não desejáveis no seu uso alterando o valor de uma variável global num subprograma, pode,
inadvertidamente alterar alguma informação fora deste e vice-versa.
Outra maneira, é usar parâmetros, o que oferece uma melhor abordagem à referida
transferência. Cada valor é transferido entre o parâmetro actual, que está incluído na chamada do
subprograma e o correspondente parâmetro formal, que está definido no próprio subprograma.
Quando o subprograma é chamado, os parâmetros actuais substituem os parâmetros formais, criando
assim um mecanismo de transferência de informação entre o subprograma e o seu ponto de chamada.
A maneira pela qual a informação é transferida depende, contudo, da maneira como os parâmetros
são definidos e utilizados.
Um subprograma pode conter 4 classes diferentes de parâmetros formais :
• parâmetros passados por valor,
• parâmetros passados por referência (variável),
• parâmetros de procedimento e,
• parâmetros de função.
14.7.1. Regras
Existem certas regras que se devem respeitar de forma a se estabelecer a correspondência, ao
substituir a lista de parâmetros reais pela lista de parâmetros formais, que são :
• O número de parâmetros nas duas listas deve ser o mesmo.
• Cada parâmetro actual corresponde ao parâmetro formal que ocupa a mesma posição na lista.
• Parâmetros formais e reais correspondentes devem ser da mesma classe e do mesmo tipo.
14.7.2. Parâmetros passados por valor
Os parâmetros passados por valor podem considerar-se como parâmetros de entrada nos seus
subprogramas respectivos. Quando a informação é transferida entre um parâmetro actual e um
parâmetro passado por valor, o valor do parâmetro actual é atribuído àquele. Este valor pode então
ser processado dentro do subprograma. Valores que são representados por parâmetros passados por
valor não podem, contudo, ser transferidos na direcção contrária, isto é, do subprograma para a parte
de chamada do programa.
Os parâmetros passados por valor são declarados simplesmente ao incluir os seus nomes e
correspondentes tipos de dados dentro do cabeçalho do subprograma, sem prefixos (tal como VAR).
É a ausência de tais prefixos que automaticamente identifica esta classe de parâmetros.
Refira-se que qualquer alteração do valor dos parâmetros passados por valor dentro do
subprograma não afectará o valor de nenhum dos parâmetros reais. Tais parâmetros permitem uma
transferência de informação num único sentido.
Apontamentos de Delphi Pascal
Subprogramas
31
Além disso, e uma vez que são os valores dos parâmetros actuais que são transferidos, e não os
parâmetros propriamente ditos, existe uma flexibilidade considerável na maneira como os
parâmetros reais podem ser escritos. Em particular, um parâmetro actual pode ser expresso como
uma constante, variável ou expressão (desde que o valor do parâmetro seja do mesmo tipo de dados).
Geralmente, os parâmetros formais utilizados em funções, são parâmetros passados por valor,
já que, o único valor de saída produzido pela função é representado pelo nome da função e não por
um parâmetro (por definição, uma função produz apenas um valor simples no seu ponto de
chamada).
14.7.3. Parâmetros passados por referência
Este tipo de parâmetros são normalmente usados para transferir a informação entre os
subprogramas e as suas instruções de chamada, permitindo a entrada e a saída do bloco de chamada.
Os parâmetros passados por referência são declarados, incluindo-os nos cabeçalhos dos
respectivos subprogramas, com o prefixo VAR.
Quando um subprograma contendo um parâmetro passado por referência é acedido, o
parâmetro actual na chamada ao subprograma é substituído pelo parâmetro formal no subprograma
propriamente dito. Portanto, o parâmetro actual será utilizado durante a execução do subprograma. É
este processo de substituição que permite uma transferência de informação nos 2 sentidos, entre a
chamada ao subprograma e o subprograma propriamente dito.
Por outro lado, deve ser salientado que só uma variável pode ser substituída por outra variável.
Portanto, os parâmetros actuais que são substituídos por parâmetros passados por referência devem
ser eles próprios variáveis; não podem ser constantes ou expressões.
Outra consequência do processo de substituição é o facto que qualquer mudança do valor do
parâmetro passado por referência dentro de um subprograma, mudar também o valor do
correspondente parâmetro actual fora do subprograma. Estes parâmetros podem afectar o programa
globalmente, mesmo que o seu âmbito seja local ao subprograma em que estão declarados.
14.7.4. Exemplo
Program exemplo (input, output);
Var a, b, c : real ;
Procedure maximo1 ( x, y : real; var aux : real ) ;
begin
If ( x > y ) Then aux := x
Else aux := y
end ;
Function maximo2 (x, y : real) : real ;
begin
If (x > y) Then maximo2 := x
Else maximo2 := y
end ;
Begin
write ('Quais os valores de a e de b ?') ;
readln (a, b) ;
maximo1 (a, b, c) ;
writeln ('O máximo entre a e b é : ', c) ;
c := maximo2 (a, b) ;
writeln ('O máximo entre a e b é : ', c)
End .
{ x, y → parâmetros formais }
Nas chamadas do procedimento e da função, os respectivos parâmetros formais são
substituídos pelos correspondentes parâmetros actuais.
Apontamentos de Delphi Pascal
32
Subprogramas
No procedimento maximo1, os parâmetros formais x e y, são passados por valor, e o aux é
passado por referência. Na função maximo2, os parâmetros formais x e y, são passados por valor.
14.8. Recursividade
Uma das características mais interessantes da linguagem Pascal é a capacidade de um
subprograma se chamar a si mesmo. Isto é conhecido por recursividade.
Ao escrever–se um subprograma recursivo, é essencial que este inclua uma condição de
finalização, para evitar que a recursividade continue indefinidamente. Contudo, enquanto a condição
de finalização se mantiver insatisfeita, o subprograma simplesmente se chama a si mesmo no local
apropriado, tal como faria qualquer outro subprograma.
Por exemplo, considere-se o problema do cálculo de factoriais. Para um dado N, a expressão
que define o factorial de N é a seguinte :
factorial (0) ← 1
⇐ N=0
1
N !=
factorial (N) ← N × factorial (N - 1)
N × (N − 1)! ⇐ N ≠ 0
Neste caso, a condição de finalização é a seguinte : N = 0 ⇒ N! = 1.
Algoritmo :
Se N = 0 Então factorial ← 1
Senão factorial ← N × factorial (N − 1)
Função recursiva :
Function factorial (N : integer) : integer;
Begin
If (N = 0) Then factorial := 1
Else factorial := N * factorial (N - 1)
End;
Simulação :
factorial (3) = ?
3 ≠ 0 ⇒ factorial ← 3 × factorial (2)
factorial (2) = ?
2 ≠ 0 ⇒ factorial ← 2 × factorial (1)
factorial (1) = ?
1 ≠ 0 ⇒ factorial ← 1 × factorial (0)
factorial (0) = ?
0=0
factorial (0) = 1
factorial ← 1 × 1 = 1
factorial ← 2 × 1 = 2
factorial ← 3 × 2 = 6
Observações :
• A execução da função faz criar diferentes registos de memória para as sucessivas chamadas :
N
3
2
1
0
factorial
6
2
1
1
• A utilização de diferentes registos para as sucessivas chamadas de um algoritmo recursivo,
torna-o muitas vezes menos eficiente (em termos de espaço de memória) que o
correspondente algoritmo iterativo.
Apontamentos de Delphi Pascal
Subprogramas
33
14.9. Rotinas predefinidas
14.9.1. Rotinas aritméticas
A seguir apresentam-se algumas funções e procedimentos predefinidos, cujos argumentos e
resultados são valores numéricos.
function Abs (X : Integer) : Integer ;
Devolve o valor absoluto de X
function Abs (X : Real) : Real ;
Devolve o valor absoluto de X
function Arctan (X : Extend) : Extend ;
Devolve o arco-tg de X (resultado em radianos)
function Cos (X : Extend) : Extend ;
Devolve o coseno de X (X em radianos)
function Exp (X : Real) : Real ;
Devolve a exponencial, de base e, de X
function Frac (X : Extend) : Extend ;
Devolve a parte fraccionária de X
function Int (X : Extend) : Extend ;
Devolve a parte inteira de X
function Ln (X : Real) : Real ;
Devolve o logaritmo neperiano de X
function Pi : Extend ;
Devolve o valor de Pi = 3.1415926535897932385
function Random (X : Integer) : Integer ;
Devolve um inteiro aleatório entre 0 e X-1
function Random : Extend ;
Devolve um real aleatório entre 0 e 1
procedure Randomize ;
Inicia o gerador de números aleatórios automaticamente com um valor aleatório (obtido a
partir do relógio do sistema)
function Round (X : Extend) : LongInt ;
Devolve o arredondamento às unidades de X
function Sin (X : Extend) : Extend ;
Devolve o seno de X (X em radianos)
Apontamentos de Delphi Pascal
34
Subprogramas
function Sqr (X : Extend) : Extend ;
Devolve o quadrado X
function Sqrt (X : Extend) : Extend ;
Devolve a raiz quadrada de X
function Trunc (X : Extend) : LongInt ;
Devolve a parte inteira de X
14.9.2. Rotinas de ordem
Uma rotina de ordem envolve apenas tipos ordenados, como sejam os inteiros, os caracteres e
os lógicos. No entanto, se o argumento e o resultado são do mesmo tipo. A seguir apresentam-se
algumas dessas rotinas.
procedure Dec (var X : Tipo [ ; N : Longint] ) ;
Devolve X com o elemento do conjunto Tipo que se encontra N posições atrás do valor X
(Tipo corresponde a um qualquer tipo ordenado) Dec (X, N) = X − N. Quando não se
especifica o valor de N, está implicito que N = 1 Dec (X) = X − 1.
procedure Inc (var X : Tipo [ ; N : Longint] ) ;
Devolve X com o elemento do conjunto Tipo que se encontra N posições à frente do valor
X (Tipo corresponde a um qualquer tipo ordenado) Inc (X, N) = X + N. Quando não se
especifica o valor de N, está implicito que N = 1 Dec (X) = X + 1.
function Ord (X : Tipo) : LongInt ;
Devolve a ordem de X (posição de X) no conjunto Tipo, em que Tipo corresponde a um
tipo ordenado (se Tipo = Char a ordem está associada à tabela ASCII)
function Succ (X : Tipo) : Tipo ;
Devolve o sucessor de X no conjunto Tipo (Tipo é um qualquer tipo ordenado)
function Pred (X : Tipo) : Tipo ;
Devolve o antecessor de X no conjunto Tipo (Tipo é um qualquer tipo ordenado)
14.9.3. Rotinas lógicas
Estas rotinas devolvem um valor lógico (True ou False), consoante um determinado teste é
verdadeiro ou falso. A seguir apresentam-se algumas dessas rotinas.
function Odd (X : LongInt) : Boolean ;
Devolve True se X é impar e False, caso contrário.
procedure IsValidIdent (Ident : String) : Boolean ;
Devolve True se Ident for um identificador válido em Delphi Pascal (ver Identificadores).
Apontamentos de Delphi Pascal
Subprogramas
35
14.9.4. Rotinas com strings e caracteres
São rotinas em que os argumentos e/ou os resultados são strings. Algumas dessas rotinas
apresentam-se a seguir :
function AnsiCompareStr (S1, S2 : String) : Integer ;
Compara S1 com S2 e devolve um valor positivo se S1 > S2, negativo se S1 < S2 ou 0 se
S1 = S2. Esta comparação é influenciada pelo local do Windows e a ordem dos caracteres é
contrária à que consta na tabela ASCII. Por ex. : AnsiCompareStr (‘a’, ‘A’) < 0.
function AnsiCompareText ( S1, S2 : String ) : Integer ;
O mesmo que AnsiCompareStr, só que na comparação efectuada, não há distinção entre
caracteres minúsculos e maiúsculos. Por ex. : AnsiCompareText (‘DELPHI’, ‘delphi’) = 0.
function AnsiLowerCase ( S : String ) : String ;
Converte todos os caracteres da string S em caracteres minúsculos. Esta conversão usa o
local do Windows corrente.
function AnsiUpperCase ( S : String ) : String ;
Converte todos os caracteres da string S em caracteres maiúsculas. Esta conversão usa o
local do Windows corrente.
procedure AppendStr ( var Dest : String ; S : String ) ;
Junta ao fim da string Dest a string S. É o mesmo que : Dest : = Dest + S.
function CompareStr ( S1, S2 : String ) : Integer ;
Compara S1 com S2 e devolve um valor positivo se S1 > S2, negativo se S1 < S2 ou 0 se
S1 = S2. Esta comparação é baseada na ordem (valor em 8-bit) de cada carácter da tabela
ASCII e não está dependente do local do Windows. Por ex. : CompareStr (‘a’, ‘A’) > 0.
function CompareText ( S1, S2 : String ) : Integer ;
O mesmo que CompareStr, só que na comparação efectuada, não há distinção entre
caracteres minúsculos e maiúsculos. Por ex. : CompareText (‘DELPHI’, ‘delphi’) = 0.
function Concat ( S1 , S2 [, S3, …, Sn] : String ) : String ;
Concatena 2 ou mais strings numa só. É o mesmo que : S := S1 + S2 [+ S3 + … + Sn].
function Copy ( S : String ; I , N : Integer ) : String ;
Devolve uma sub-string da string S, contendo N caracteres com início em S[I]. Se I é
superior que o comprimento de S, é devolvido uma string vazia. Se N especificar mais
caracteres que os disponíveis, apenas são devolvidos os restantes caracteres, de S[I] até ao
fim de S. Por exemplo, Copy(‘Delphi Pascal’, 8, 6) = ‘Pascal’.
procedure Delete ( var S : String ; I , N : Integer ) ;
Remove a sub-string com N caracteres da string S, com início em S[I]. Se I é maior que o
comprimento de S, nenhum carácter é eliminado. Se N especificar mais caracteres do que
o que resta desde S[I], é removido o resto da string. Por ex. : Delete(‘Delphi Pascal’, 7, 7) =
‘Delphi’ (estrutura incorrecta só para exemplificar).
Apontamentos de Delphi Pascal
36
Subprogramas
procedure Insert ( S1 : String ; var S2 : String ; I : Integer ) ;
Insere S1 em S2 a partir da posição S2[I]. Por ex. : Insert (‘3.0 ‘, ‘Delphi Pascal’, 8) = ‘Delphi
3.0 Pascal’ (estrutura incorrecta só para exemplificar).
procedure Length (S : String) : Integer ;
Devolve o número de caracteres da string S. Por ex., Length (‘Delphi’) = 6.
function LowerCase (S : String) : String ;
Devolve uma string com o mesmo texto da string S, mas com todas as letras convertidas
em minúsculas. A conversão afecta apenas os caracteres ASCII (em 7-bit) entre 'A' e 'Z'.
Para converter os caracteres internacionais (em 8-bit), usar AnsiLowerCase.
function UpperCase (S : String) : String ;
Devolve uma string com o mesmo texto da string S, mas com todas as letras convertidas
em maiúsculas. A conversão afecta apenas os caracteres ASCII (em 7-bit) entre 'a' e 'z'.
Para converter os caracteres internacionais (em 8-bit), usar AnsiUpperCase.
function Pos (S1, S2 : String) : Integer ;
Procura a string S1 em S2 e devolve um inteiro, que corresponde ao índice do primeiro
carácter de S1 dentro de S2. Pos não distingue as letras minúsculas das maiúsculas. Se S1
não for encontrada em S2, é devolvido zero (0).
function UpCase (Ch : Char) : Char ;
Devolve o carácter maiúsculo do carácter Ch, em que Ch está no conjunto { ‘a’, … , ‘z’ }.
function Chr (X : Byte) : Char ;
Devolve o carácter de ordem X, segundo a tabela ASCII
14.9.5. Rotinas de data/hora
São rotinas que servem para consultar qualquer informação relativa a uma data ou hora, a qual
á dada pelo relógio do sistema.
function Now : TDateTime ;
Devolve a data e a hora actual, armazenada no relógio do sistema.
function Time : TDateTime ;
Devolve apenas a hora actual, armazenada no relógio do sistema.
function Date : TDateTime ;
Devolve apenas a data actual, armazenada no relógio do sistema.
function DayOfWeek (DT : TDateTime) : Integer ;
Devolve o dia da semana da data DT, através de um inteiro entre 1 e 7 : Domingo é o
primeiro dia da semana e Sábado é o sétimo.
14.9.6. Rotinas de conversão
As rotinas de conversão permitem converter um valor de um certo tipo para um valor de um
outro tipo (converter a string ‘452’ no inteiro 452). Para que a conversão tenha êxito, é necessário que
o valor a converter tenha sentido no novo tipo (converter a string ‘452A’ para inteiro não faz sentido);
Apontamentos de Delphi Pascal
Subprogramas
37
no entanto, caso isso não aconteça, é provocada uma excepção EConvertError. A seguir apresentamse algumas dessas rotinas.
function IntToStr (X : Integer) : String ;
Converte o inteiro X numa string. O inteiro tem que estar na sua representação decimal.
function StrToInt (S : String) : Integer ;
Converte a string S num número inteiro (na notação decimal ou hexadecimal).
function FloatToStr (X : Extended) : String ;
Converte o valor real X, em ponto flutuante, numa string. A conversão usa o formato
geral do número com 15 dígitos significantes.
function StrToFloat (S : String) : Extended ;
Converte a string S num valor real em ponto flutuante. A string S deve consistir de uma
sinal opcional (+ ou −), uma string de dígitos com um ponto decimal opcional e um 'E' ou
'e' opcional seguido por um inteiro com sinal. Caracteres brancos no início e no fim da
string são ignorados.
A variável global DecimalSeparator define o carácter que deve ser usado como um ponto
decimal. Milhares de separadores e símbolos correntes não são permitidos na string.
function StrToDateTime (S : String) : TDateTime ;
Converte uma string numa data/hora. A string especificada como parâmetro S deve estar
no formato MM/DD/AA HH:MM:SS. A especificação de AM ou PM como parte da hora
é opcional, assim como os segundos.
function DateTimeToStr (DT : TDateTime) : String ;
Converte a data/hora DT numa string. Se a data contida em DT não é válida, a data a
converter é a 00/00/00; se a hora contida em DT não for válida, a hora a converter é
00:00:00 AM.
function StrToDate (S : String) : TDateTime ;
Converte a string S numa data, segundo o formato do Windows. A string S deve consistir
em dois ou três números, separados pelo carácter definido pela variável global
DateSeparator. A ordem para o mês, o dia e o ano é determinado pela variável global
ShortDateFormat possíveis combinações são : m/d/a, d/m/a e a/m/d.
Se a string contém apenas dois números, isto é interpretado como uma data (m/d ou
d/m) do ano actual. Os valores para o ano entre 0 e 99 assumem-se ser do século actual.
function DateToStr (DT : TDateTime) : String ;
Converte a data contida na data DT numa string.
function StrToTime (S : String) : TDateTime ;
Converte a string S numa hora. A string deve consistir em dois ou três números,
separados pelo carácter definido pela variável global TimeSeparator, opcionalmente
seguida por um indicador AM ou PM. Os números representam hora, minuto e
(opcionalmente) segundo, por esta ordem. Se o tempo (hora) é seguida por AM ou PM, é
assumido ser no formato de 12 horas. Se não for incluído qualquer indicador AM ou PM,
assume-se que a hora está no formato de 24 horas.
Apontamentos de Delphi Pascal
38
Subprogramas
function TimeToStr (DT : TDateTime) : String ;
Converte a hora que se encontra em DT numa string.
function IntToHex (X , Dig : Integer) : String ;
Converte o inteiro X numa string com a sua representação em hexadecimal (base 16). O
parâmetro Dig indica o número mínimo de dígitos hexadecimais a devolver.
14.10. Caixas de Diálogo de Mensagens
As caixas de diálogo de mensagens servem para comunicar o utilizador, fornecendo certa
informação que está a ser tratada pela aplicação.
14.10.1. ShowMessage
A sintaxe desta função é a seguinte :
procedure
ShowMessage ( Mens : String ) ;
ShowMessage mostra uma simples caixa de mensagem, apenas com um botão OK. O
parâmetro Mens é a mensagem (string) que aparece na caixa de mensagem. O nome do projecto (em
Delphi) que está a criar a caixa de mensagem aparece como título da caixa de mensagem.
Exemplo : (o projecto tem o nome Exemplo.dpr)
14.10.2. MessageBox
A sintaxe desta função é a seguinte :
function MessageBox ( Mens, Título : PChar ; Flags : Longint ) : Integer ;
Utiliza-se a função MessageBox para apresentar uma mensagem numa caixa de diálogo
genérica com um ou mais botões, em que,
• Título é o título da caixa de diálogo e é opcional
• o valor do parâmetro Mens é a mensagem, que pode ter mais de 255 caracteres se necessário; as
mensagens longas são automaticamente repartidas por várias linhas na caixa de mensagem
• os valores do parâmetro Flags determinam os botões que aparecem na caixa de mensagem e o
comportamento desta caixa; estes valores podem ser combinados para obter o efeito desejado
Apontamentos de Delphi Pascal
Subprogramas
39
O valor devolvido pelo método MessageBox é 0, se não há memória suficiente para criar a caixa de
mensagem, ou um dos seguintes valores :
Valor
IDABORT
IDCANCEL
IDIGNORE
IDNO
IDOK
IDRETRY
IDYES
Ordem
3
2
5
7
1
4
6
Exemplo :
If Application.MessageBox ('Pretende mesmo abandonar a aplicação ?', 'Confirmação',
MB_YESNO + MB_DEFBUTTON1) = IDYES
Then Exit;
14.10.3. MessageDlg
A sintaxe desta função é a seguinte :
function
MessageDlg ( Mens : String; Tipo : TMsgDlgType;
TMsgDlgButtons; Ajuda : Longint ) : Word ;
Botões :
MessageDlg mostra uma caixa de diálogo com uma mensagem no centro do écran, a qual
necessita de obter uma resposta do utilizador, em que,
• A caixa de mensagem mostra o valor do parâmetro Mens.
• Usar o parâmetro Tipo para indicar o objectivo do diálogo. Ou seja, determina o tipo de caixa
mensagem que aparece. Os tipos possíveis são :
Valor do parâmetro
Tipo de caixa de mensagem
mtWarning
mtError
mtInformation
mtConfirmation
mtCustom
Aviso
Erro crítico
Informação
Confirmação
O título corresponde ao nome do projecto
Usar o parâmetro Botões para indicar quais os botões que aparecerão na caixa de mensagem.
Os valores possíveis são :
MbYes
mbNo
mbOk
mbCancel
mbHelp
mbAbort
mbRetry
mbIgnore
mbAll
• Usar o parâmetro Ajuda para especificar o ID context para o tópico de Ajuda que aparecerá
quando o utilizador clicar no botão de Ajuda ou pressionar F1 enquanto o diálogo está a ser
mostrado.
•
Apontamentos de Delphi Pascal
40
Subprogramas
MessageDlg devolve o valor do botão que o utilizador seleccionou. Os possíveis valores
devolvidos são os seguintes :
mrNone
mrAbort
mrYes
mrOk
mrRetry
mrNo
mrCancel
mrIgnore
mrAll
Exemplo :
If MessageDlg (Quer abandonar a aplicação ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
Then begin
MessageDlg (‘A aplicação vai ser fechada !’, mtInformation, [mbOk], 0);
Close;
end;
14.10.4. MessageDlgPos
A sintaxe desta função é a seguinte :
function
MessageDlgPos ( Mens : String; Tipo : TMsgDlgType; Botões :
TMsgDlgButtons; Ajuda : Longint; X, Y : Integer ) : Word ;
MessageDlgPos mostra uma caixa de diálogo com mensagem num determinado local do écran,
especificado através das coordenadas do canto superior esquerdo da caixa, em que os parâmetros
Mens, Tipo, Botões e Ajuda têm a mesma função dos utilizados pela MessageDlg, e os parâmetros X
e Y são utilizados para especificar as coordenadas do écran onde o diálogo deverá aparecer.
MessageDlgPos devolve os mesmos valores que devolve a função MessageDlg.
Exemplo :
MessageDlgPos (‘A aplicação vai ser fechada !’, mtInformation, [mbOk], 0, 200, 300);
14.11. Caixas de Diálogo de Edição de Dados
As caixas de diálogo de edição de dados servem para comunicar o utilizador, no sentido deste
fornecer a informação necessário para que a execução do programa continue normalmente.
14.11.1. InputBox
A sintaxe desta função é a seguinte :
function InputBox ( Título, Prompt, ValorDefeito : String ) : String ;
InputBox mostra uma caixa de diálogo de entrada para permitir que o utilizador introduza
uma string na própria caixa de diálogo, em que o parâmetro Título é o título da caixa de diálogo, o
parâmetro Prompt é o texto que alerta o utilizador para introduzir a string na caixa de edição, e o
parâmetro ValorDefeito é a string que aparece por defeito na caixa de edição (quando a caixa de
diálogo aparece pela primeira vez).
Se o utilizador carregar no botão Cancel, o InputBox devolve a string por defeito. Se carregar no
botão OK, o InputBox devolve a string que está na caixa de edição.
Apontamentos de Delphi Pascal
Ficheiros
41
Exemplo :
UserName := InputBox ('Por favor introduza o seu nome', 'Nome : ', 'Carlos');
14.11.2. InputQuery
A sintaxe desta função é a seguinte :
function InputQuery ( Título, Prompt : String; var Valor : String ) : Boolean ;
InputQuery funciona como o InputBox, mas esta função devolve True se o utilizador carregar
no botão OK e False se o utilizador carregar no botão Cancel ou pressionar a tecla Esc.
O parâmetro Valor é a string que aparece por defeito na caixa de edição, a qual, recebe também
a string que o utilizador introduziu naquela caixa após se carregar no botão OK.
Exemplo :
Nome := ‘Carlos’;
If InputQuery ('Por favor introduza o seu nome', 'Nome : ', Nome)
Then ShowMessage ('Nome = ' + Nome);
15. Ficheiros
15.1. Introdução
Geralmente, existem 2 tipos de ficheiros que podem ser criados e acedidos por um programa de
computador : ficheiros permanentes e ficheiros temporários.
Os ficheiros permanentes são mantidos num dispositivo auxiliar de memória (disco, disquete,
CD, etc.) e preservados após a execução do programa. O seu conteúdo pode ser acedido e/ou
modificado por qualquer programa, em qualquer momento. Em Pascal chamam-se ficheiros externos.
Os ficheiros temporários são armazenados na memória principal do computador (RAM),
perdendo-se assim que o programa que o criou termine a sua execução. Em Pascal, chamam-se
ficheiros internos.
Todos os ficheiros (permanentes e temporários) podem ser organizados numa de 2 maneiras
diferentes : sequencial ou aleatória (ficheiro de acesso directo).
Num ficheiro sequencial, todos os seus componentes são armazenados sequencialmente. Para
se aceder a um componente particular, é necessário começar a pesquisa no início do ficheiro, até se
encontrar aquela componente.
Num ficheiro de acesso aleatório, cada componente pode ser acedido directamente, sem se
proceder à leitura do ficheiro desde o seu início.
Apontamentos de Delphi Pascal
42
Ficheiros
O Pascal ISO comporta apenas ficheiros sequenciais, embora algumas implementações também
comportem ficheiros de acesso aleatório. Apenas serão referidos os ficheiros sequenciais.
15.2. Ficheiros de texto
Leitura de dados a partir de ficheiros de texto :
f : TextFile ;
⇒
f será o nome interno de um ficheiro
A : Tipo ;
⇒
A de qualquer tipo simples
AssignFile (f, ‘Ficheiro’) ;
⇒
associar a ‘Ficheiro’ o nome interno f
Reset (f) ;
⇒
abre o ficheiro f e prepara-o para a leitura de dados
Readln (f, A) ;
⇒
lê A e muda de linha (em f)
Read (f, A) ;
⇒
lê A e continua na mesma linha (em f)
se A é uma String utilizar apenas Readln
CloseFile (f) ;
⇒
fecha o ficheiro f
var
Escrita de dados em ficheiros de texto :
f : TextFile ;
A : Tipo ;
AssignFile (f, ‘Ficheiro’) ;
Rewrite (f) ;
⇒
⇒
⇒
⇒
f será o nome interno de um ficheiro
A de qualquer tipo simples
associar a ‘Ficheiro’ o nome interno f
abre o ficheiro f e prepara-o para escrita de dados
Se ‘Ficheiro’ contiver dados, estes são apagados
Writeln (f, A) ;
⇒
escreve A e muda de linha (em f)
Write (f, A) ;
⇒
escreve A e continua na mesma linha (em f)
Se A é uma String utilizar apenas a instrução Writeln
CloseFile (f) ;
⇒
fecha o ficheiro f
var
Exemplo :
type Identificacao = record
Nome, Morada : String ;
BIdentidade, Telefone : Integer ;
end;
Registo = array [1 . . 20] of Identificacao ;
procedure Guardar ;
var f : TextFile ;
i : Integer; X : Registo ;
begin
AssignFile (f, ‘Ficheiro_Saida’) ;
Rewrite (f) ;
for i := 1 to 20 do
begin
O formato escolhido é o seguinte :
Writeln (f, X[i].Nome) ;
1ª linha = Nome
Writeln (f, X[i].Morada) ;
2ª linha = Morada
Writeln (f, X[i].BIdentidade, ‘ ‘, X[i].Telefone) ;
3ª linha = BI e Telefone, separados por ‘ ‘
{ ou Write (f, X[i].BIdentidade) ;
3ª linha = BI
Writeln (f, X[i].Telefone) ;
4ª linha = Telefone }
end ;
CloseFile (f) ;
end;
Apontamentos de Delphi Pascal
Ficheiros
43
procedure Abrir ;
var f : TextFile ;
i : Integer ; X : Registo ;
begin
AssignFile (f, ‘Ficheiro_Entrada’) ;
Reset (f) ;
for i := 1 to 20 do
begin
O formato de leitura é o mesmo utilizado na escrita
Readln (f, X[i].Nome) ;
(ver Procedure Guardar)
Readln (f, X[i].Morada) ;
Readln (f, X[i].BIdentidade, X[i].Telefone) ;
{ ou Read (f, X[i].BIdentidade) ; Readln (f, X[i].Telefone) ;
}
end ;
CloseFile (f) ;
end;
15.3. Ficheiros de registo
Leitura de dados a partir de ficheiros de registo :
⇒
⇒
⇒
⇒
⇒
⇒
f : File Of Registo ;
A : Registo ;
AssignFile (f, ‘Ficheiro’) ;
Reset (f) ;
Read (f, A) ;
CloseFile (f) ;
var
f será o nome interno de um ficheiro do tipo Registo
A é uma variável de registo (Record)
associar a ‘Ficheiro’ o nome interno f
abre o ficheiro f e prepara-o para a leitura de dados
lê A (em f) { a instrução Readln não é aplicável }
fecha o ficheiro f
Escrita de dados em ficheiros de registo :
⇒
⇒
⇒
⇒
⇒
⇒
f : File Of Registo ;
A : Registo ;
AssignFile (f, ‘Ficheiro’) ;
Rewrite (f) ;
Write (f, A) ;
CloseFile (f) ;
var
f será o nome interno de um ficheiro do tipo Registo
A é uma variável de registo (Record)
associar a ‘Ficheiro’ o nome interno f
abre o ficheiro f e prepara-o para a escrita de dados
escreve A (em f) { a instrução Writeln não é aplicável }
fecha o ficheiro f
Exemplo :
type Identificacao = record
Nome, Morada : String[50] ; { 50 = comprimento da String }
BIdentidade, Telefone : Integer ;
end;
Registo = array [1 . . 20] of Identificacao;
procedure Guardar ;
// guarda todo o registo duma só vez
var f : File Of Registo ;
A : Registo ;
begin
AssignFile (f, ‘Ficheiro_Saida’) ;
Rewrite (f) ;
Write (f, A) ;
CloseFile (f) ;
end ;
procedure Guardar ;
// guarda o registo elemento a elemento
var f : File Of Identificacao ;
i : Integer ;
A : Registo ;
begin
AssignFile (f, ‘Ficheiro_Saida’) ;
Rewrite (f) ;
for i := 1 to 20 do
Write (f, A[i]) ;
CloseFile (f) ;
end ;
Apontamentos de Delphi Pascal
44
Ficheiros
procedure Abrir ;
// lê o registo de uma só vez (como o guardou)
var f : File of Registo ;
A : Registo ;
begin
AssignFile (f, ‘Ficheiro_Entrada’) ;
Reset (f) ;
Read (f, A) ;
CloseFile (f) ;
end ;
procedure Abrir ;
// lê o registo elemento a elemento (como o guardou)
var f : File of Identificacao ;
i : Integer ;
A : Registo ;
begin
AssignFile (f, ‘Ficheiro_Entrada’) ;
Reset (f) ;
for i := 1 to 20 do
Read ( f, A[i]) ;
CloseFile (f) ;
end ;
NOTA :
Cada uma das formas de guardar o registo está associado a uma das formas de o ler.
15.4. As funções “eoln” e “eof”
Estas funções apenas se aplicam a ficheiros de texto e de leitura (entrada), retornando um valor
lógico (Boolean). Para se poder utilizar um ficheiro de leitura este tem já que existir.
A função eoln (“End Of Line” = Fim de Linha) devolve o valor True, se a informação lida
corresponder ao carácter indicador de fim de linha, e o valor False caso contrário. Portanto, a função
EOLN mantém-se False, até que um carácter de fim de linha seja detectado, o que obriga a tornar-se
True. A função volta a tornar-se False logo que outro carácter é examinado.
A forma geral desta função é a seguinte:
eoln ( Ficheiro ) ;
A função eof (“End Of File” = Fim de Ficheiro) devolve o valor True, se a informação lida
corresponder ao carácter indicador de fim de ficheiro, e o valor False caso contrário. O seu
funcionamento é exactamente igual ao da função EOLN.
A forma geral desta função é a seguinte :
eof ( Ficheiro ) ;
Exemplo :
procedure Abrir ;
var f : TextFile ;
N : Integer ;
X : Array [1 . . 200] Of Integer ;
begin
AssignFile (f, Fich) ;
Reset (f) ;
N := 0 ;
repeat
repeat
N := N + 1 ;
Read (f, X[N]) ;
until eoln (f) ;
Readln (f) ;
{ Depois de se ler a linha toda, tem que se mudar para a seguinte }
until eof (f) ;
end ;
Apontamentos de Delphi Pascal
Índice
i
ÍNDICE
1. Identificadores-----------------------------------------------------------1
2. Tipos de dados predefinidos standard (simples) -----------------1
2.1. Inteiros (Integer) ------------------------------------------------------------- 1
2.2. Reais (Real)-------------------------------------------------------------------- 1
2.3. Lógicos (Boolean)------------------------------------------------------------ 2
2.4. Caracteres (Char) ------------------------------------------------------------- 2
2.5. String---------------------------------------------------------------------------- 3
3. Tipos de dados predefinidos não standard ----------------------- 3
3.1. TDateTime -------------------------------------------------------------------- 3
3.2. TTimeStamp ------------------------------------------------------------------ 3
4. Operadores -------------------------------------------------------------- 4
4.1. Aritméticos--------------------------------------------------------------------- 4
4.2. Lógicos ------------------------------------------------------------------------- 4
4.3. Relacionais--------------------------------------------------------------------- 4
5. Constantes--------------------------------------------------------------- 5
6. Variáveis ----------------------------------------------------------------- 5
7. Constantes tipificadas (“typed constants”) ----------------------- 5
8. Expressões -------------------------------------------------------------- 6
8.1. Prioridades dos operadores ------------------------------------------------- 6
8.2. Operadores com a mesma prioridade ------------------------------------ 6
8.3. Uso de parêntesis------------------------------------------------------------- 6
8.4. Conclusão ---------------------------------------------------------------------- 7
ii
Índice
9. Dados definidos pelo utilizador -------------------------------------7
9.1. Dados definidos por enumeração ----------------------------------------- 7
9.2. Dados definidos por subdomínio (gama de valores) ------------------ 7
9.3. Observações ------------------------------------------------------------------- 8
10. Instruções---------------------------------------------------------------8
10.1. De atribuição ----------------------------------------------------------------- 8
10.2. Composta --------------------------------------------------------------------- 8
10.3. Condicionais ----------------------------------------------------------------- 9
10.3.1. Selecção alternativa (estrutura IF)----------------------------------------------------- 9
10.3.2. Selecção múltipla (estrutura CASE) -------------------------------------------------10
10.4. Repetitivas (ciclos) --------------------------------------------------------- 11
10.4.1. Repetição "Enquanto" (estrutura While ... Do)------------------------------------11
10.4.2. Repetição "Até Que" (estrutura Repeat ... Until) ----------------------------------12
10.4.3. Repetição com controlador (estrutura For) ----------------------------------------13
10.4.4. Rotinas de controlo dos ciclos--------------------------------------------------------13
10.5. Goto --------------------------------------------------------------------------- 14
11. Tabelas (“Arrays”) -------------------------------------------------- 15
11.1. Tabela de uma dimensão-------------------------------------------------- 15
11.1.1. Definição---------------------------------------------------------------------------------15
11.1.2. Declaração de variáveis ----------------------------------------------------------------15
11.1.3. Declaração de constantes--------------------------------------------------------------16
11.1.4. Identificação dos elementos ----------------------------------------------------------16
11.1.5. Representação gráfica ------------------------------------------------------------------16
11.1.6. Generalidades ---------------------------------------------------------------------------16
11.1.7. Exemplos --------------------------------------------------------------------------------16
11.2. Tabela de duas dimensões------------------------------------------------ 17
11.2.1. Definição---------------------------------------------------------------------------------17
11.2.2. Declaração de variáveis ----------------------------------------------------------------17
11.2.3. Declaração de constantes--------------------------------------------------------------17
11.2.4. Identificação dos elementos ----------------------------------------------------------17
11.2.5. Representação gráfica ------------------------------------------------------------------17
11.2.6. Exemplos --------------------------------------------------------------------------------18
11.3. "Arrays" de várias dimensões-------------------------------------------- 18
Índice
iii
12. Registos---------------------------------------------------------------- 18
12.1. Definição --------------------------------------------------------------------- 18
12.2. Declaração de variáveis --------------------------------------------------- 19
12.3. Declaração de constantes------------------------------------------------- 19
12.4. Exemplos -------------------------------------------------------------------- 19
12.5. Observações -----------------------------------------------------------------20
12.6. Acesso aos campos do registo -------------------------------------------20
12.7. A instrução WITH ---------------------------------------------------------20
12.8. Operações com registos--------------------------------------------------- 21
12.9. Registos variantes ---------------------------------------------------------- 21
12.10. Registos de registos (exemplo)-----------------------------------------23
12.11. Variantes com variantes (exemplo) ------------------------------------23
13. Conjuntos (“SET”) -------------------------------------------------- 23
13.1. Definição ---------------------------------------------------------------------23
13.2. Construção de um conjunto ----------------------------------------------24
13.3. Exemplos --------------------------------------------------------------------24
13.4. Generalidades ---------------------------------------------------------------24
13.5. Operações com conjuntos ------------------------------------------------25
13.6. Comparação de conjuntos ------------------------------------------------25
13.7. Teste de pertença-----------------------------------------------------------25
13.8. Problema---------------------------------------------------------------------26
14. Subprogramas -------------------------------------------------------- 26
14.1. Introdução -------------------------------------------------------------------26
14.2. Conceito de procedimento (procedure) --------------------------------26
14.2.1. Definição-------------------------------------------------------------------------------- 27
14.2.2. Chamada -------------------------------------------------------------------------------- 27
14.2.3. Exemplo--------------------------------------------------------------------------------- 27
iv
Índice
14.3. Conceito de função (function) -------------------------------------------27
14.3.1. Definição---------------------------------------------------------------------------------27
14.3.2. Chamada ---------------------------------------------------------------------------------28
14.3.3. Exemplo ---------------------------------------------------------------------------------28
14.4. Generalidades ---------------------------------------------------------------28
14.5. Declaração dos subprogramas-------------------------------------------29
14.6. Domínio dos identificadores ---------------------------------------------29
14.7. Parâmetros-------------------------------------------------------------------30
14.7.1. Regras ------------------------------------------------------------------------------------30
14.7.2. Parâmetros passados por valor -------------------------------------------------------30
14.7.3. Parâmetros passados por referência -------------------------------------------------31
14.7.4. Exemplo ---------------------------------------------------------------------------------31
14.8. Recursividade ---------------------------------------------------------------32
14.9. Rotinas predefinidas -------------------------------------------------------33
14.9.1. Rotinas aritméticas ---------------------------------------------------------------------33
14.9.2. Rotinas de ordem-----------------------------------------------------------------------34
14.9.3. Rotinas lógicas --------------------------------------------------------------------------34
14.9.4. Rotinas com strings e caracteres -----------------------------------------------------35
14.9.5. Rotinas de data/hora-------------------------------------------------------------------36
14.9.6. Rotinas de conversão ------------------------------------------------------------------36
14.10. Caixas de Diálogo de Mensagens--------------------------------------38
14.10.1. ShowMessage --------------------------------------------------------------------------38
14.10.2. MessageBox ----------------------------------------------------------------------------38
14.10.3. MessageDlg ----------------------------------------------------------------------------39
14.10.4. MessageDlgPos------------------------------------------------------------------------40
14.11. Caixas de Diálogo de Edição de Dados-------------------------------40
14.11.1. InputBox -------------------------------------------------------------------------------40
14.11.2. InputQuery-----------------------------------------------------------------------------41
15. Ficheiros -------------------------------------------------------------- 41
15.1. Introdução ------------------------------------------------------------------- 41
15.2. Ficheiros de texto ----------------------------------------------------------42
15.3. Ficheiros de registo --------------------------------------------------------43
15.4. As funções “eoln” e “eof” ------------------------------------------------44