Essenzialmente in RPG una DS è intesa come un record in Pascal, cioè una
definizione di tipi dati eterogenei che possono essere trattati sia
unicamente che separatamente.
Il bello però è che se noi abbiamo una "DS1" formata da:
campo1 - 6 alfanumerico
campo2 - 3.0 numerico
campo3 - 20 alfanumerico
in RPG si può fare un'operazione MOVE da una qualsiasi stringa alfanumerica
di qualsiasi dimensione a una DS di questo tipo, e poi potremo riferirci
alle variabili per campo... esempio:
MOVE 'ABCDEF1234567890GHILMNO' DS1
avremo che
campo1 = 'ABCDEF'
campo2 = 123
campo3 = '4567890GHILMNO '
e vi assicuro che è davvero una cosa utilissima.
Vengo finalmente al dunque: come fareste voi ad implementare questa cosa in
Delphi?
Secondo me sarebbe una cosa che semplificherebbe tantissime cose.
Se volete scrivermi: gare...@mindless.com
Jax
Ciao
Paolo Pedrielli
Sintesi S.r.l.
EMail: pao...@sintesi.com --- Web: http://www.sintesi.com
"Jax" <rispo...@newsgroup.grazie> ha scritto nel messaggio
news:zxVt7.20753$C15.2...@news.infostrada.it...
si può scrivere la seguente routine:
procedure TMainForm.MasksDance;
var
VarRec : TVarRec;
I : integer;
S : string[25];
R : real;
begin
FillChar(VarRec, SizeOf(VarRec), ''); // inizializza il record variante
VarRec.fStr := 'Sarò un intero, poi un reale, poi di nuovo una stringa, ma
un''altra stringa';
Edit1.Text := IntToStr(VarRec.fInt);
Edit2.Text := FloatToStr(VarRec.fFloat);
Edit3.Text := string(VarRec.fPtr^); // attenzione a questa istruzione: si
tratta di un casting.
end;
Come si vede, il record VarRec è stato prima 'ripulito', poi il campo
stringa è stato riempito con una frase. Dopodicchè il contenuto dello spazio
di memoria occupato da VarRec è stato successivamente letto dal compilatore
*come se fosse* un intero, poi un reale, infine un puntatore.
In realtà il record variante è una struttura dati la cui dimensione è uguale
alla dimensione del suo campo più 'ingombrante' (nel caso di TVarRec i 26
byte del campo stringa); Leggere gli altri campi significa semplicemente
dire al compilatore di leggere quello che c'è nel record variante come se
fosse del tipo del campo preso in considerazione.
Il tipico uso del record variante era, nel pascal, la lettura/scrittura dei
registri della CPU. In delphi il tipo Variant altro non è che un record
variante un pò più sofisticato. Ma non a caso Borland mette in guardia da un
uso eccessivo di quel tipo di dato.
2) casting tra tipi.
Si può anche costringere esplicitamente il compilatore a leggere un dato di
un certo tipo come se fosse di un altro tipo. Si possono cioè scrivere
istruzioni di questo tipo:
var
I : integer;
R : Real;
S1, S2 : string;
begin
I := 13256;
R := real(I);
Edit1.Text := FloatToStr(R);
S1 := shortstring(I);
S2 := IntToStr(I)
Edit2.Text := S1;
Edit3.Text := S2; // notare la differenza
end;
Esattamente così (salva la necessità di debug). In altre parole la locazione
di memoria occupata da un intero viene letta dal compilatore *come se fosse*
un reale e poi una stringa.
Per concludere: in pascal (e quindi in delphi) i tipi definiscono la
dimensione di una locazione di memoria, mentre le variabili stabiliscono la
allocazione fisica di uno spazio dati di quella data dimensione. Quello che
si trova ad un certo segmento e ad un certo offset è semplicemente una
sequenza di 0 e di 1: sarà il programmatore a stabilire che quella sequenza
andrà considerata come se fosse un intero, o un puntatore, o qualunque altra
cosa.
Una ultima annotazione: queste tecniche (associate all'uso dei puntatori
generici, come nell'ultima riga del primo esempio) in pascal per DOS
venivano considerate "extreme programming", e utilizzate con grande
circospezione. In ambiente windows, invece, sono considerate il punto di
partenza per una tecnica di programmazione appena decente.
--
Sam Sahara
sa...@iol.it
http://samsahara.cjb.net
Jax <rispo...@newsgroup.grazie> wrote in message
zxVt7.20753$C15.2...@news.infostrada.it...
>...
> Il bello però è che se noi abbiamo una "DS1" formata da:
> campo1 - 6 alfanumerico
> campo2 - 3.0 numerico
> campo3 - 20 alfanumerico
>
> in RPG si può fare un'operazione MOVE da una qualsiasi stringa
alfanumerica
> di qualsiasi dimensione a una DS di questo tipo, e poi potremo riferirci
> alle variabili per campo... esempio:
> MOVE 'ABCDEF1234567890GHILMNO' DS1
> avremo che
> campo1 = 'ABCDEF'
> campo2 = 123
> campo3 = '4567890GHILMNO '
>
> e vi assicuro che è davvero una cosa utilissima....
supponi di avere un tipo record di questo genere:
Tmiorec = record
nome: string[20];
eta: smallint;
provincia: string[4];
end;
function MiaMove(aString: string; var amiorec: Tmiorec);
var vI: integer;
begin
vI := 1;
amiorec.nome := copy(astring,vI,sizeof(amiorec.nome));
vI := vI + sizeof(amiorec.nome);
amiorec.eta := strtoint(copy(astring,vI,sizeof(amiorec.eta)));
ecc...
ecc...
end;
Magari non ho capito il tuo problema...oppure questa funzione non č
esattamente quello che volevi...
saluti
--
ciao
Solid Snake IT
"Nemo mortalium omnibus horis sapit" (Plinio il VECCHIO)
> 2) casting tra tipi.
Questo lo conoscevo già e in molti casi è abbastanza utile, anche se con le 2000
funzioni di conversione già pronte non è che li si usa poi tantissimo (il più
usato credo sia PChar(string) per passare i parametri alle API :))
> circospezione. In ambiente windows, invece, sono considerate il punto di
> partenza per una tecnica di programmazione appena decente.
Addirittura? Io invece le considero un po' inutili e pericolose, infatti tento
di starne alla larga quando posso... non so perché, ma non mi piacciono queste
forzature.
Jax
> [cut]
> in RPG si può fare un'operazione MOVE da una qualsiasi stringa
alfanumerica
> di qualsiasi dimensione a una DS di questo tipo, e poi potremo riferirci
> alle variabili per campo... esempio:
> MOVE 'ABCDEF1234567890GHILMNO' DS1
> avremo che
> campo1 = 'ABCDEF'
> campo2 = 123
> campo3 = '4567890GHILMNO '
>
> e vi assicuro che è davvero una cosa utilissima.
>
Ho lavorato prima in RPG ed ho usato le DS poi sono passato al Clipper e poi
a Delphi
(transitando un attimo attraverso Visual Object e molto di sfuggita Visual
Basic)
Delle Data Structure non sento assolutamente la mancanza!
E' un buon sistema di lavorare quando sei costretto a fare i salti mortali,
che ti evita una capriola.
Se ci pensi solo un attimo puoi fare la stessa cosa con la funzione copy e
le eventuali dovute conversioni di tipo.
Tuttavia se ti sforzi di avere i dati puliti e separati già alla fonte (e
quasi sempre si può) poi vivi più tranquillo che,
se per caso qualcosa va storto, hai potuto farti tutti i controlli
necessari.
Tutto questo "secondo me".
Ciao.
--
Emilio Panozzo
mailto: emip...@tin.it
Attenzione, perchè non sempre è la stessa cosa. Una funzione di conversione
salva il *valore logico* di una variabile di un tipo in una variabile di un
altro tipo, il casting legge un *valore fisico* (cioè il contenuto della
locazione di memoria) secondo un tipo di dato diverso da quello originario.
Ad es:
var
S1, S2 : string;
I : integer;
begin
I1 := 1972;
S1 := StrToInt(I); // conversione da intero a stringa
Label1.Caption := Concat('Il valore logico di I è: ', S1);
S2 := shortstring(I); // casting di una stringa su un intero
Label2.Caption := Concat('Il valore fisico nella locazione di I è
rappresentabile, come se fosse una stringa, così : ', S2);
end;
Come si vede la stessa variabile intera I viene presa in considerazione
prima per il suo valore logico (che viene poi restituito in una stringa),
poi per il suo valore fisico (ovvero il contenuto della locazione di
memoria). Questo valore fisico viene quindi letto in S2 *come se fosse una
stringa*. Che si tratti di cose diverse lo dimostra il diverso output
(visualizzato nelle label).
In delphi uno dei tipici usi del casting è la scrittura di event handler
generici. Ad es.
procedure TMainForm.Button1Click(Sender : TObject);
begin
if (Sender is TButton) then
TButton(Sender).Caption := 'Clicked!'; // casting di TButton su un
generico oggetto
// codifiche alternative possono essere
// with (Sender as TButton) do Caption := 'Clicked!;
// (Sender as TButton).Caption := 'Clicked!;
end;
Ora, nel corpo del codice appena visto non si fa riferimento ad alcun Button
particolare per cui, ammettendo che sulla form dove è posto il Button1 di
cui sopra ci siano altri 10 TButton, l'event handler appena visto può essere
scritto una sola volta e poi direttamente collegato ad ognuno dei TButton a
design time, per mezzo dell'object inspector. Tutte le codifiche elencate
mostrano dei sofisticati esempi di casting, possibili solo in delphi (non in
pascal), che offrono la gestione del meccanismo del casting con l'utile
accessorio della gestione degli errori da parte della VCL.
Queste argomentazioni dimostrano, a monte, una cosa di cui sono sempre stato
convinto: per essere un decente programmatore delphi è necessario avere un
solido e sperimentato background pascal.