guarda un po'...
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button2: TButton;
procedure Button2Click(Sender: TObject);
private
type tpippo = record
a:integer;
b:string[20];
end;
Var A_pippo:array of tpippo;
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button2Click(Sender: TObject);
var x:integer;
begin
setlength(a_pippo,0);
for x:=0 to 9 do begin
setlength(a_pippo,x+1);
a_pippo[x].a:=x;
a_pippo[x].b:=inttostr(x);
end;
showmessage(inttostr(length(A_pippo)));
end;
end.
Ma scusa se fosse un TStringArray io posso fare così
begin
arr := TStringArray.create('eee','rrr');
end;
e funziona, ma con un array di record?
Se vuoi creare un array di stringhe costanti puoi farlo anche così:
var
strarr: array of string = ['uno', 'due', 'tre'];
Per un array l'indicazione che pensavo di fornirti è creare una procedura di inizializzazione, ovviamente da chiamare per ciascun elemento. Non ho conoscenza di una procedura che consente di inizializzare a dei valori voluti un array di record.
Perchè farlo a differenza di quanto suggerito da @Narciso (fermo restando che và comunque bene anche la sua soluzione): perchè nel caso tu cambi la struttura puoi sfruttare la procedura per fare si che la compilazione non avvenga se non aggiorni l'inizializzazione. Io sui record uso molto spesso le procedure per inserire i dati, non inserisco i dati direttamente nei campi del record perchè se cambio qualcosa (refactoring) con le procedure ho una segnalazione di errore e ciò mi consente di modificare il codice a "colpo sicuro".
Esempio:
type
RProva = record
private
fNome: string;
fCognome: string;
public
procedure Init(const Nome: string; const Cognome: string);
end;
....
....
procedure RProva.Init(const Nome, Cognome: string);
begin
fNome := Nome;
fCognome := Cognome;
end;
...
...
var
Prova: array of RProva;
//EDIT2: al posto della definizione di Prova in modalità classica, puoi usare anche i generici se ti piace di più, non cambia il codice:
//Prova: TArray<RProva>;
i: RProva;
begin
SetLength(Prova, 10);
for i in Prova do
i.Init('Non usato', 'Non usato');
end;
Se aggiorno il record con ad esempio l'aggiunta di una data:
type
RProva = record
private
fNome: string;
fCognome: string;
fDataNascita: TDate;
public
procedure Init(const Nome: string; const Cognome: string; DataNascita: TDate);
end;
La compilazione mi genererebbe un errore ovunque usi la procedura Init, e così via ove usi le funzioni o procedure per inserire i dati (o anche per leggerli se fosse importante).
EDIT: per spiegare meglio, se uso direttamente i campi potrei dimenticare da qualche parte nel sorgente di settare la data di nascita senza che me ne accorga, e ciò non è bello ...
E' leggermente differente che usare i campi direttamente, ma questo è un mio modo di programmare, non deve essere preso assolutamente come campione.
Ciao
Forse non mi sono spiegato bene. Io un array di stringhe posso inizializzarlo così:
program Project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Sysutils,
Classes
{ you can add units after this };
var
c : TStringArray;
begin
c := TStringArray.Create('eee', 'rrr');
end.
Però non riesco a farlo con un array di record
P.S. @nomorelogic esempio interessante
se guardi nel link che ti ho indicato c'è questo pezzo di codice
type
tConstArray = array of TVarRec;
[...]
var
x: TConstArray;
y: TConstArray =
(
(vtype : vtChar; vchar : '1'),
(vtype : vtInteger; vinteger : 1),
(vtype : vtPointer; vpointer : nil)
);
non so se funziona (oggi non riesco a provare in quanto sono in giro)
ma pensavo tu intendessi qualcosa del genere
x:= TConstArray.Create (
(
(vtype : vtChar; vchar : '1'),
(vtype : vtInteger; vinteger : 1),
(vtype : vtPointer; vpointer : nil)
)
);
L'idea è questa
program Project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes
{ you can add units after this };
type
calimero = record
sonoNero : Boolean;
end;
sfigati = array of calimero;
var
io : calimero;
tu : calimero;
noi : sfigati;
begin
io.sonoNero:=True;
tu.sonoNero:=True;
noi := sfigati.Create(io, tu);
end.
e funziona.
Vorrei fare noi := sfigati.Create(io, tu); senza dichiarare le variabili io e tu, cioè se è possibile assegnare i valori del record direttamente dentro noi := sfigati.Create
dovresti provare con qualcosa tipo
noi := sfigati.Create( ( sononero: True ), ( sononero: True ) );
oppure se puoi fare in modo che calimero sia un oggetto
noi := sfigati.Create( TCalimero.Create(true), TCalimero.Create(true) );
è da provare ma la strada credo sia questa
ok, ok
quà c'è un workaround, lo ammetto (la funzione _GetSfigato)
però così il sorgente è comunque abbastanza leggibile e manutenibile
inoltre ho scoperto (si perché non lo sapevo o l'avevo dimenticato :o) che si può creare un array anche con le parentesi quadre...
program test_creazione_array;
type
Tcalimero = record
sonoNero : Boolean;
end;
Tsfigati = array of Tcalimero;
function _GetSfigato(AValue: boolean): Tcalimero;
begin
result.sonoNero:=AValue;
end;
var
ErrorMsg: String;
sf1, sf2, sf3, sf4: Tsfigati;
a1, a2: Tcalimero;
begin
a1.sonoNero:=True;
a2.sonoNero:=True;
sf1 := Tsfigati.create(a1,a2);
WriteLn('sf1: ', Length(sf1));
sf2 := [a1,a2];
WriteLn('sf2: ', Length(sf2));
sf3 := [ _GetSfigato(True), _GetSfigato(True) ];
WriteLn('sf3: ', Length(sf3));
sf4 := Tsfigati.Create( _GetSfigato(True), _GetSfigato(True) );
WriteLn('sf4: ', Length(sf4));
end.