* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Ottobre 16, 2024, 10:47:19 am

Inserisci il nome utente, la password e la durata della sessione.

104 Visitatori, 0 Utenti

Autore Topic: array of const  (Letto 586 volte)

cappe

  • Newbie
  • *
  • Post: 41
  • Karma: +0/-0
array of const
« il: Ottobre 09, 2024, 07:46:25 am »
Ciao a tutti,
   faccio una domanda che, forse, potrebbe essere interessante. Come si a passare un array of string in una funzione che accetta array of const in maniera semplice.

Ad esempio :

Codice: [Seleziona]
program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, sysutils
  { you can add units after this };

procedure caio(par : array of const);
begin
end;

var
  pp : TStringArray;
begin
  pp := TStringArray.Create('rrr', 'rrre', 'www', 'eeee');
  caio (pp);   // <-   non funziona
end.
     

Avevo trovato con TVarRec ma è lunga da fare. Esiste un modo più semplice?

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2908
  • Karma: +20/-4
Re:array of const
« Risposta #1 il: Ottobre 09, 2024, 10:23:58 am »
ciao cappe

ho fatto qualche prova ma non ci sono riuscito

in questo link https://www.freepascal.org/docs-html/ref/refsu69.html

leggo
"The elements of the array of const are converted to a special variant record"

ho paura che TVarRec sia l'unico modo


Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1348
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:array of const
« Risposta #2 il: Ottobre 10, 2024, 11:07:47 am »
A livello di compilazione "array of const" è equivalente ad "array of TVarRec" come ha accennato @nomorelogic.

La gestione è un pò più complicata di un tipo variant, ma di fatto non molto di più se si pensa che si stanno usando tipi "a caso" in un array ...

Codice: [Seleziona]
procedure TForm1.Prova(tip: array of const);
var i: TVarRec;
begin
  for i in tip  do
    begin
      if (i.VType = VTInteger)  then
        ShowMessage(inttostr(i.VInteger));
      if (i.VType = vtAnsiString)  then
        ShowMessage(String(i.VAnsiString));
      if (i.VType = vtExtended)  then
        ShowMessage(floattostr(Double(i.VExtended^)));
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var p: integer;
    a: string;
    b: double;
begin
  p := 10;
  a := 'Pollo arrosto';
  b := 234.87;
  Prova([p,a,b]);
end;

Occhio ai tipi, ad esempio il tipo VtAnsiString o VtExtended potrebbero essere diversi in realtà o "rappresentare" dati diversi: ad esempio se il progetto è impostato come UNICODE, i tipi string non sono più AnsiString ma diventano Unicode e quindi ciò che abbiamo scritto và implementato anche con VtUnicode ... il tipo VtExtended può rappresentare anche un valore di tipo single e quindi quando faccio il casting sul VExtended devo fare attenzione, ad esempio dovrei controllare la lunghezza del dato in modo da identificarlo tra single e double.

Occhio che usare una tale codifica potrebbe esporre il codice a certe e sicure anomalie in futuro, difficili poi da analizzare.
Con tutta sincerità, a meno che non sia indispensabile io non userei "array of const" per alcun motivo, come non userei TVarRec in quanto fortemente dipendente dalla versione del compilatore.

L'uso di array "aperti" con dati misti dovrebbe essere evitato il più possibile, a meno che i dati non siano a priori certi e noti (ad esempio: sicuramente double, interi e stringhe UNICODE).

Bye
« Ultima modifica: Ottobre 10, 2024, 11:12:17 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1348
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:array of const
« Risposta #3 il: Ottobre 10, 2024, 12:15:23 pm »
   faccio una domanda che, forse, potrebbe essere interessante. Come si a passare un array of string in una funzione che accetta array of const in maniera semplice.

Per venire alla tua domanda specifica dopo la dissertazione del post precedente , purtroppo in Lazarus non sono riuscito a fare funzionare ciò che dovrebbe essere logicamente funzionante e banale, ossia l'associazione tra tipi.
Il seguente codice funziona in Delphi ma non c'è modo di farlo funzionare in Lazarus, neanche usando i puntatori ... sicuramente sono io che sbaglio qualcosa ...

EDIT: usando il puntatore a tipo invece di un puntatore puro risolve la situazione in Lazarus.

Codice: [Seleziona]
type
TMioArray = array of string;
PTMioArray = ^TMioArray;

procedure TForm1.Prova(tip: array of const);
var i: TVarRec;
    punta: pointer;
    s: string;
begin
  for i in tip  do
    begin
      if (i.VType = VtInteger)  then
        ShowMessage(inttostr(i.VInteger));
      if (i.VType = VtAnsiString)  then                         //In Lazarus deve essere usato AnsiString, in Delphi invece UnicodeString
        ShowMessage(String(i.VAnsiString));
      if (i.VType = VtPointer)  then
       begin
        punta := PTMioArray(i.VPointer);
        for s in TMioArray(punta) do
          ShowMessage(s);
       end;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var p: integer;
    a: string;
    b: double;
    ar: TMioArray;
begin
  p := 10;
  a := 'Pollo arrosto';
  b := 234.87;
  setlength(ar, 2);
  ar[0] := 'Pippo';
  ar[1] := 'Pluto';
  Prova([PTMioArray(ar), p, a, b]);
//  Prova([ar, p, a, b]); //<--- Questo funziona solo in Delphi, In Lazarus si deve usare un "puntatore a ar" al posto di ar ... non usare @ar !!!!
end;
« Ultima modifica: Ottobre 10, 2024, 06:02:13 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1348
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:array of const
« Risposta #4 il: Ottobre 10, 2024, 06:15:25 pm »
Si può usare anche con lo TStringArray ovviamente, ma bisogna usare il puntatore specializzato comunque:

Codice: [Seleziona]
type
TMioArray = array of string;
PTMioArray = ^TMioArray;

procedure TForm1.Prova(tip: array of const);
var i: TVarRec;
    punta: pointer;
    s: string;
begin
  for i in tip  do
    begin
      if (i.VType = VtInteger)  then
        ShowMessage(inttostr(i.VInteger));
      if (i.VType = VtAnsiString)  then                         //In Lazarus deve essere usato AnsiString, in Delphi invece UnicodeString
        ShowMessage(String(i.VAnsiString));
      if (i.VType = VtPointer)  then
       begin
        punta := PTMioArray(i.VPointer);
        for s in TMioArray(punta) do
          ShowMessage(s);
       end;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var p: integer;
    a: string;
    b: double;
    ar: TMioArray;
    strar: TStringArray;
begin
  p := 10;
  a := 'Pollo arrosto';
  b := 234.87;
  setlength(ar, 2);
  ar[0] := 'Pippo';
  ar[1] := 'Pluto';
  strar := TSTringArray.Create('rrr', 'rrre', 'www', 'eeee');
  Prova([PTMioArray(strar), PTMioarray(ar), p, a, b]);
//  Prova([PTMioarr(ar), p, a, b]);
//  Prova([pp, p, a, b]); //<--- Questo funziona solo in Delphi, In Lazarus si deve usare un "puntatore a ar" al posto di ar ... non usare @ar !!!!
 
end;
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

cappe

  • Newbie
  • *
  • Post: 41
  • Karma: +0/-0
Re:array of const
« Risposta #5 il: Ottobre 11, 2024, 09:27:54 am »
Grande,
  ti chiamerò Drago Rosso il magnifico.

ottima soluzione e farò così.

cappe

  • Newbie
  • *
  • Post: 41
  • Karma: +0/-0
Re:array of const
« Risposta #6 il: Ottobre 11, 2024, 09:32:34 am »
Aspetta, però c'è un problema il tipo PStringArray deve essere conosciuto dall'iteratore VType. Quindi può andar bene se non utilizza qualcosa di già pronto.

L'idea è buona però bisogna vedere se funziona in qualcosa di già costruito, penso di no.

Ad ogni modo è un bellissimo esempio anche per chiarire

Provo
« Ultima modifica: Ottobre 11, 2024, 09:35:10 am da cappe »

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1348
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:array of const
« Risposta #7 il: Ottobre 11, 2024, 10:03:57 am »
La lunghezza dell'array passato c'è comunque in quanto viene passata la struttura completa alla routine e il compilatore ovviamente sà come sbrogliare le cose.

Per l'iterazione, invece è necessario vedere se viene implementata l'interfaccia IEnumerator nel dato managed. Nel caso degli array, in FPC puoi sempre effettuare la enumerazione (se è questo che intendi).

Invece se intendi capire quale tipo di array viene passato e quindi ti ritrovi dalla parte della routine (per poter poi usare la corretta dereferenziazione) quello è da vedere: ad esempio ora si passano array di stringhe, ma potrei passare array di double.

Occorre verificare se le RTTI siano ancora valide e rilevabili ... in FPC sia le RTTI che le RTL sono sempre state un tallone di Achille.

Però, visto che si usa il passaggio con il puntatore direi che non dovrebbe essere un problema.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1348
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:array of const
« Risposta #8 il: Ottobre 11, 2024, 10:39:52 am »
La definizione di TVarRec definisce le seguenti tipologie di tipi:

Codice: [Seleziona]
   const
      vtInteger       = 0;
      vtBoolean       = 1;
      vtChar          = 2;
      vtExtended      = 3;
      vtString        = 4;
      vtPointer       = 5;
      vtPChar         = 6;
      vtObject        = 7;
      vtClass         = 8;
      vtWideChar      = 9;
      vtPWideChar     = 10;
      vtAnsiString    = 11;
      vtCurrency      = 12;
      vtVariant       = 13;
      vtInterface     = 14;
      vtWideString    = 15;
      vtInt64         = 16;
      vtQWord         = 17;
      vtUnicodeString = 18;

Per qualsiasi ulteriore tipo (come negli esempi sopra,  un'array) viene usato il VtPointer.

Nei variant (TVarType) sono invece identificati questi tipi, in più ci sono una serie di routine che aiutano a runtime a definire ulteriori caratteristiche del variant (ad esempio IsVarArray).

Codice: [Seleziona]
  varEmpty = 0;
   varNull = 1;
   varSmallInt = 2;
   varInteger = 3;
   varSingle = 4;
   varDouble = 5;
   varDate = 7;
   varCurrency = 6;
   varOleStr = 8;
   varDispatch = 9;
   varError = 10;
   varBoolean = 11;
   varVariant = 12;
   varUnknown = 13;
   varDecimal = 14;
   varShortInt = 16;
   varByte = 17;
   varWord = 18;
   varLongWord = 19;
   varInt64 = 20;
   varQWord = 21;

EDIT: a livello di curiosità, il costrutto "array of const" è quello usato ad esempio nella definizione della funzione Format che se fate presente viene usata allo stesso modo degli esempi riportati sopra:

Citazione
Format('%d - %s - %f', [p, a, b]);
« Ultima modifica: Ottobre 11, 2024, 10:49:05 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

 

Recenti

How To

Utenti
Stats
  • Post in totale: 19038
  • Topic in totale: 2270
  • Online Today: 111
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 104
Total: 104

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.