Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 15 di 43
  • livello principiante
Indice lezioni

I tipi (parte seconda)

Si continua ad esaminare i tipi di dati: i tipi Real, i tipi String e i tipi strutturati.
Si continua ad esaminare i tipi di dati: i tipi Real, i tipi String e i tipi strutturati.
Link copiato negli appunti

I tipi real

I tipi real definiscono insiemi di numeri che possono essere rappresentati con
la notazione in virgola mobile.

I tipi real fondamentali sono riportati di seguito

Tipo Intervallo Cifre significative Dimensione in byte
Real48 2.9 x 10-39..1.7 x 1038 11-12 6
Single 1.5 x 10-45..3.4 x 1038 7-8 4
Double 5.0 x 10-45..1.7 x 10308 15-16 8
Extended 3.6 x 10-4951..1.1 x 104932 19-20 10
Comp -263 + 1..263 - 1 19-20 8
Currency -922337203685477.5808.. 922337203685477.5807 19-20 8

Il tipo real generico equivale al double.

Seguono alcune considerazioni sui tipi real fondamentali

  • Il tipo Real48 viene mantenuto per compatibilità con il tipo real delle
    versioni precedenti di Object Pascal. Non essendo un tipo che utilizza un formato di
    memorizzazione non nativo per le CPU intel determina prestazioni più lente.
  • Extended è il tipo real che permette maggiore precisione ma a sua volta è
    meno portabile.
  • Il tipo Comp (computazionale) è nativo per le CPU Intel e rappresenta un
    integer a 64 bit. Pur essendo un tipo integer viene classificato come real in quanto non
    si comporta come tipo ordinal; non è infatti possibile incrementare o decrementare un
    valore comp. Viene mantenuto per compatibilità con le versioni precedenti. Al
    suo posto si consiglia l'uso del tipo Int64.
  • Currency è un tipo di dati che viene utilizzato per i calcoli valutari poiché
    ne riduce al minimo gli errori di arrotondamento. È caratterizzato da punto decimale
    fisso e viene memorizzato come un integer a 64 bit scalato, con le ultime quattro cifre
    meno significative che rappresentano i decimali. Valori di questo tipo vengono
    automaticamente moltiplicati o divisi per 10000 quando vengono usati in espressioni con
    altri tipi real.

I tipi String

L'Object Pascal possiede, a differenza di altri linguaggi come ad esempio il C ed il
C++, tipi di dati dedicato alla gestione dell stringhe. I tipi string supportati
dall'Object Pascal sono i seguenti

Tipo Lunghezza massima Memoria richiesta Usato per
ShortString 255 caratteri da 2 a 256 byte compatibilità con versioni
precedenti
AnsiString ~231 caratteri da 4 byte a 2GB caratteri a 8 bit (ANSI)
WideString ~230 caratteri da 4 byte a 2GB caratteri UNICODE; server e
interfacce COM

AnsiString è il tipo preferito per la maggior parte della applicazioni. A
volte viene anche chiamato LongString.

I tipi string possono essere mischiati nelle assegnazioni e nelle espressioni in quanto
il compilatore effettua automaticamente le conversioni del caso. Bisogna invece fare
attenzione nel passaggio di parametri alle funzioni ed alle procedure che deve rispettare
il tipo dei parametri dichiarati insieme alla funzione o procedura.

Il tipo generico per il tipo string è string. Non si tratta
proprio di un tipo ma di una parola chiave del linguaggio che identifica un tipo di dati
contenete una stringa. Come stato predefinito la parola chiave string
si riferisce al tipo AnsiString (se non è seguita da un numero fra parentesi
quadre). È possibile cambiare string in ShortString
tramite la direttiva del compilatore {$H-}.

Anche per il tipo string esistono funzioni predefinite come Length che
restituisce la lunghezza in caratteri di una stringa e SetLength che ne regola la
lunghezza.

Due variabili di tipo string possono essere confrontate tramite gli operatori
relazionali. In tal caso il confronto avviene confrontando l'ordinalità dei caratteri che
occupano la stessa posizione. Ad esempio la stringa "AB" risulterà minore di
"AC". Confrontando stringhe di differente lunghezza, la dove i caratteri della
stringa più lunga non hanno corrispondenza nella stringa più corta, vengono considerati
maggiori. Di conseguenza la stringa "AB" risulterà maggiore della stringa
"A".

Una variabile string può essere indicizzata come se si trattasse di un array. I tal
caso è possibile accedere i caratteri di una stringa utilizzando la seguente sintassi.

S[i] dove S è una variabile di tipo string e i un intero indicante la posizione
all'interno della stringa S.

Per cui, S[2] := 'A' assegna alla posizione 2 della stringa S il carattere 'A'.

Molta attenzione va fatta nella manipolazione delle stringhe tramite la tecnica vista
in precedenza in quanto, in presenza di stringhe di tipo AnsiString o WideString che in
realtà rappresentano stringhe terminate con null, la sovrascrittura dell'ultimo carattere
(il null appunto) potrebbe causare un errore di violazione di accesso.

I tipi Short String

Come visto nella tabella dei tipi string, il tipo ShortString può essere
lungo da 0 a 255 caratteri. Mentre la sua lunghezza varia dinamicamente, la memoria che
occupa viene allocata staticamente e corrisponde a 256 byte; all'interno del primo byte è
riportata la lunghezza in caratteri della stringa. Ne consegue che per ottenere la
lunghezza di una stringa ShortString è possibile leggere il valore ordinale del
carattere presente alla posizione 0 secondo la rappresentazione ad array. L'operazione Ord(S[0])
è equivalente a Length(S) dove S è una variabile string.

L'Object Pascal supporta anche dei sottotipi di ShortString la cui lunghezza
varia da 0 a 255. Questi tipi vengono definiti specificando un numerale tra parentesi
quadre dopo la parola chiave string. Per esempio

Type String50 = String[50];

definisce un tipo String50 la cui lunghezza massima è di 50 caratteri. Questo tipo di
dichiarazione permette di risparmiare spazio in memoria poiché per contenere un variabile
del tipo String50 verranno allocati solamente 51 byte a differenza dei 256 del tipo base ShortString.

I tipi Long String (AnsiString)

Come accennato in precedenza il tipo AnsiString viene anche definito LongString.
Il tipo AnsiString rappresenta una stringa allocata dinamicamente la cui
lunghezza massima è limitata solamente dalla memoria disponibile. Una variabile di questo
tipo non è altro che un puntatore che occupa 4 byte. Il sistema utilizzato, totalmente
gestito in maniera invisibile all'utente, è simile ad una lista di caratteri. Ciò
permette appunto di avere una lunghezza dipendente solamente dalla memoria disponibile nel
sistema. Un'altra caratteristica di questo tipo è che, trattandosi di puntatori, due o
più variabili di questo tipo possono far riferimento allo stesso valore senza spreco
aggiuntivo di memoria.

I tipi Wide String

L'allocazione di variabili di questo tipo è il medesimo di quello per variabili di
tipo AnsiString con la differenza che le stringhe rappresentate utilizzano
caratteri UNICODE a 16 bit. Si differenzia solamente per efficienza che risulta minore in
quanto non utilizza accorgimenti come il contatore dei riferimenti utilizzato invece dal
tipo AnsiString. Questo tipo è utilizzato prevalentemente per la compatibilità
con i tipi nelle funzionalità COM.


I tipi strutturati

Fanno parte di questa categoria di tipi i Set, gli Array, i Record,
i file oltre alle classi ed alle interfacce. Una istanza di tipo
strutturato raccoglie sotto di se più valori. I tipi Set possono a loro volta
contenere valori di tipo strutturato eccezion fatta per il tipo Set che può
contenere solamente valori di tipo ordinale.

Set

Il tipo set implementa quello che in matematica viene definito insieme. Un set può
contenere solamente valori dello stesso tipo ordinale senza seguire alcun ordinamento
intrinseco. Altresì non ha significato che un elemento sia inserito due volte in un Set.
L'intervallo di validità dei valori di un tipo Set dipende dall'intervallo di validità
del tipo ordinal utilizzato per creare il Set. Questo tipo ordinale che
origina il Set viene chiamato tipo base. Il costrutto utilizzato per
dichiarare un tipo Set è il seguente

Set of TipoBase

Esempi di dichiarazione di tipi Set sono i seguenti:

Type TChars = 'A'..'Z';

TSetOfChars = Set of TChars;

Per assegnare dei valori a varibili di tipo Set, facendo riferimento
all'esempio precedente, si procede come segue:

Var Caratteri : TSetOfChars;

...

Caratteri := ['A', 'F', 'B', 'T', 'X'];

Con analogia alla matematica ed agl'insiemi, un tipo Set può essere vuoto e viene
rappresentato con [].

Array

Gli array rappresentano una raccolta indicizzata di elementi tutti
appartenenti ad uno stesso tipo che, come per i tipi Set, prende il nome di Tipo
Base
. A differenza dei tipi Set, un array può contenere, proprio
perché indicizzato, più volte lo stesso valore. I tipi base utilizzabili nella
dichiarazione di array, possono essere qualsiasi dai tipi ordinal ai
tipi string, puntatori, altri array etc. Gli array possono
essere dichiarati staticamente o dinamicamente ed essere mono o
multi dimensionali. Un array monodimensionale rappresenta un vettore di elementi,
mentre array multidimensionali rappresentano matrici di elementi.

Array statici

Il costrutto che si utilizza per dichiarare array statici è il seguente

array [TipoIndice1, ..., TipoIndicen] of TipoBase;

Il numero di elementi che può contenere un array così definito è dato dal prodotto
delle dimensioni dei TipoIndice racchiusi tra parentesi quadre.

Gli array monodimensionali o vettori, hanno un solo TipoIndice come in questo esempio

Type TVettore100 = Array [1..100] of Integer;

In questo esempio è stato definito un vettore che può contenere al massimo 100 valori
integer.

Per accedere ai valori di una variabile array come sopra dichiarata si utilizza la
sintassi MioVettore[50] dove MioVettore è il nome della variabile di tipo TVettore100 e
50 l'indice dell'elemento 50 all'interno dell'array. Quando si definisce una variabile di
tipo array e non si assegnano valori a tutti gli elementi, gli elementi non assegnati
vengono comunque allocati e conterranno valori non definiti.

Si possono anche dichiarare array multidimensionali come di seguito

Type TMatrice10X10 = Array [1..10, 1..10] of
Integer;

In questo caso è stato dichiarato un tipo TMatrice10X10 composto da 10 righe e 10
colonne. La dichiarazione precedente equivale a dichiarare un tipo array di array come di
seguito

Type TMatrice10X10 = Array [1..10] of Array [1..10] of Integer;

Per accedere i valori di una variabile dichiarata come TMatrice10X10 si procede in
maniera simile agli array monodimensionali tranne per il fatto che, essendo questi a più
dimensioni, bisogna indicare un indice per ognuna delle dimensioni dell'array. Nel caso
dell'esempio precedente MiaMatrice[2, 3], dove la variabile MiaMatrice è di tipo
TMatrice10X10, accederà al valore contenuto alla riga 2 colonna 3 della matrice.

In Object Pascal sono definite funzioni per operare con gli indici e le dimensioni
degli array statici. Con Low e High si ottiene rispettivamente il limite
inferiore e quello superiore del primo tipo dell'array. Con Length si ottiene il
numero di elementi nella prima dimensione dell'array.

Array dinamici

A differenza degli array statici, gli array dinamici non hanno dimensioni e lunghezza
fisse e quindi la memoria viene riallocata quando si assegna un valore all'array o quando
si utilizza la funzione SetLength per impostarne le dimensioni.

Per dichiarare deigli array dinamici si utilizza il costrutto

Type NomeTipo = Array of TipoBase;

Quando si dichara un array dinamico questo non occupa memoria fino a quando non si
effettua una chiamata alla funzione SetLength.

Per esempio, se è stata dichiarata una variabile MioArray di tipo TMioArray = Array of
Integer per creare effettivamente l'array in memoria effettuando la chiamata
SetLength(MioArray, 100), si allocherà memoria per un array di 100 elementi integer. Da
ricordare che l'indicizzazione degli array dinamici si basa sempre su integer e comincia
da 0. In pratica gli array dinamici sono puntatori similmente ai LongString. Per
disallocare un array dinamico, è possibile assegnare alla variabile che lo referenzi il
valore Nil oppure passare la variabile stessa alla funzione Finalize;
questo verrà disallocato solamente nel caso in cui non siano presenti altri riferimenti
ad esso. Array di lunghezza 0 assumono il valore Nil.

Anche per gli array dinamici sono disponibili le funzioni standard Length, Low
ed High. Queste restituiscono rispettivamente il numero di elementi dell'array, 0
in ogni caso, e l'indice superiore dell'array. Nel caso di array vuoti High
restituisce -1. Interessante notare che si avrà in questo caso High < Low
(-1 < 0).

Record

Per fare subito un confronto con altri linguaggi, tra cui C e C++, questo tipo
corrisponde ai tipi struct (Struttura). Esso rappresenta un insieme di elementi
eterogenei fra loro, ovvero un tipo record può raggruppare in se tipi diversi di elementi.
Gli elementi di un record vengono detti campi; nella dichiarazione di un
tipo record occorre specificare un nome per il tipo record ed un nome ed un tipo per
ciascuno dei suoi campi. Ecco la struttura della dichiarazione di un record

Type NomeTipoRecord = Record

Campo1 : Tipo1;

...

Campon : Tipon;

End;

Come per gli array dinamici, la dichiarazione di una un tipo record, non alloca memoria
per i campi in esso contenuti. La memoria viene allocata al momento della dichiarazione di
una variabile di quel tipo record.

Un esempio di tipo record è

Type TPersona = Record

Nome : String[40];

Cognome : String[40];

Eta : Integer;

End;

Per accedere ai campi del record si utilizza la sintassi seguente

NomeVariabile.Nomecampo

Dall'esempio precedente

Var Persona : TPersona;

...

Persona.Nome := 'Carlo';

Persona.Cognome := 'Marona';

Persona.Eta := 25;

Se si devono accedere più volte i campi del record è possibile utilizzare il
costrutto With..do nel modo seguente

With Persona do

Begin

Nome := 'Carlo';

Cognome := 'Marona';

Eta := 25;

End;

Quando si dichiara un tipo record, si ha la possibilità di inserire nella sua
dichiarazione delle varianti alla sua struttura. Queste varianti vanno inserite dopo aver
dichiarato tutti i campi del record. L sintassi è la seguente

Type NomeTipoRecord = Record

Campo1 : Tipo1;

...

Campon : Tipon;

Case SelettoreVariante : TipoOrdinale of

ListaCostanti1 : (Variante1);

...

ListaCostantin : (Varianten);

End;

Il SelettoreVariante è facoltativo; se si omette è necessario omettere anche i due
punti successivi. Il SelettoreVariante deve essere di tipo ordinal.

Ogni ListaCostanti può essere composta da una costante dello stesso tipo di
SelettoreVariante o da un elenco di costanti, sempre del tipo di SelettoreVariante,
separate da virgole.

Ogni Variante è un elenco di dichiarazioni di con la stessa sintassi vista per la
dichiarazione dei campi della parte principale del record.

Le parti variant dei record condividono lo stesso spazio di memoria. Si può  
leggere o scrivere nei campi variant dei record in qualsiasi momento, tenendo conto che se
si scrive in un campo di un variant e subito dopo si scrive in un campo di un altro
variant, i dati possono essere sovrascritti. Se si specifica il un SelettoreVariante,
questo funziona come un campo normale nella parte principale del record. Per un
trattazione più approfondita si rimanda alla guida al linguaggio.

Tipi file

I tipi file rappresentano un insieme ordinato di elementi tutti dello stesso
tipo. Un tipo file viene dichiarato come segue

Type NomeTipoFile = File of Tipo;

dove NomeTipofile è un nome di identificatore valido e Tipo un tipo di dato qualsiasi
di dimensioni fissate. Non possono essere utilizzati quindi nelle dichiarazioni di tipi file
puntatori, array dinamici, long string, altri file o qualsiasi altro tipo strutturato che
contenga uno qualsiasi dei tipi precedentemente elencati.

Con riferimento all'esempio per i tipi record possiamo dichiarare un tipo file
come segue

Type TFileElenco = File of TPersona;

...

Var FileElenco : TFileElenco;

Dichiarare un tipo od una variabile facendo uso solamente della parola file
darà origine ad un tipo di file non tipizzato, senza tipo.

Ti consigliamo anche