Riporto un immagine relativa ad uno spezzone di codice dove esistono in cascata più if. Ebbene il compilatore segnala un errore ad una prima Else, mentre, più avanti , per lo stesso tipo di sequenza, non segnala niente.
Mi sembrava una banalità, ma, sostituendo Else , posta immediatamente dopo, con un'altra if (<>), vengono segnalati altri errori più sotto.
Non descrivo tutto dettagliatamente per ingarbugliare anche l'esposizione del mio problema.
l'errore segnalato è:
frm2.pas(413,5) Fatal: Syntax error, ";" expected but "ELSE" found
Devo dire che nella parte dichiarativa della procedure ho inserito tipe e var di puntamento ai miei 3 array globali:
procedure TForm2.CompilaFrm2(sdtTratt, rifTb:String);
//procedure TForm2.compilaFrm2(sdtTratt: Integer; rifTb:String); // carica in GridMovv i movimenti presenti in tbMovv(M) o in tbResta(R)
type
PtbCor = ^string; // crea un puntatore generico di tipo String
PtbMov = ^TtbMovv;
PtbRes = ^TtbResta;
PtbRiep = ^TtbRiep;
var
tbCorr: PtbCor;
tbMovim: PtbMov;
tbResCas: PtbRes;
tbQuadra: PtbRiep;
swPrimo: Boolean;
sw: Boolean = False;
i, i1, nuRgTbCorr, nuRgTbMovv, nuRgTbRiep, nuRgTbResta: Integer;
nuRgdtTratt: Integer = 0;
begin
Che sia qui il problema?
quando una if ha anche la clausola else, non ci deve essere il ; dopo l'end che precede l'else
è errato scrivere
if condizione
begin
istruzione1;
end;
else
begin
istruzione2;
end;
in quanto il ; chiude l'istruzione
è invece corretto:
if condizione
begin
istruzione1;
end
else
begin
istruzione2;
end;
Sicuramente ho commesso uno strafalcione.
Tuttavia, prima di scrivere, ho provato anche la soluzione "if ... end else" (senza quindi il ;) ed il compilatore mi segnalato altri errori che per me sono indecifrabili.
Allego l'immagine con la segnalazione d'errore nel codice, mentre riporto qui sotto il messaggio d'errore :
frm2.pas(415,22) Error: Element zero of an ansi/wide- or longstring cannot be accessed, use (set)length instead
frm2.pas(427,22) Error: Element zero of an ansi/wide- or longstring cannot be accessed, use (set)length instead
L'errore è sicuramente legato al cattivo uso che faccio, dentro la unit frm2, nel puntare all'indirizzo di memori dei miei array globali, dchiarati nella unit frmmain:
unit frmmain;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset,
fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore
type
{ TForm1 }
TtbMovv = array of array of String;
TtbResta = array of array of String;
TtbRiep = array of array of String;
TForm1 = class(TForm)
. . .
Non ho saputo trovare nessuna nota informativa sull'uso di variabili di puntamento agli array. Perciò, quello che ho trovato e letto, l'ho interpretato così:
unit frm2;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, Grids, utilmie,
ExtCtrls, XMLPropStorage;
type
{ TForm2 }
TForm2 = class(TForm)
. . .
procedure TForm2.CompilaFrm2(sdtTratt, rifTb:String);
//procedure TForm2.compilaFrm2(sdtTratt: Integer; rifTb:String); // carica in GridMovv i movimenti presenti in tbMovv(M) o in tbResta(R)
type
PtbCor = ^string; // crea un puntatore generico di tipo String
PtbMov = ^TtbMovv;
PtbRes = ^TtbResta;
PtbRiep = ^TtbRiep;
var
tbCorr: PtbCor;
tbMovim: PtbMov;
tbResCas: PtbRes;
tbQuadra: PtbRiep;
swPrimo: Boolean;
sw: Boolean = False;
i, i1, nuRgTbCorr, nuRgTbMovv, nuRgTbRiep, nuRgTbResta: Integer;
nuRgdtTratt: Integer = 0;
begin
case rifTb of
'M':
begin
nuRgTbCorr:= Length(tbMovv) div 5;
tbCorr:= @tbMovim; // carico in tbCorr l'indirizzo di memoria tbMovim
end;
'R':
begin
nuRgTbCorr:= Length(tbResta) div 4;
tbCorr:= @tbResCas; // carico in tbCorr l'indirizzo di memoria di TtbResta
end;
'Q':
begin
nuRgTbCorr:= Length(tbRiep) div 6;
tbCorr:= @tbQuadra; // carico in tbCorr l'indirizzo di memoria di TtbRiep
end;
end;
1) Attenzioni ai tipi: ad esempio definisci "TtbMovv" come un array bidimensionale, e poi, assegni a "tbCorr" (che è un puntattore a una stringa) il puntatore all'array bidimensionale. Questo non và bene, almeno da quello che adesso ho capito. In questo modo tbcorr punterà al primo elemento dell'array bidimensionale, ma non è garantito che così tu possa accedere all'array bidimensionale completo.
Cerca di mantenere la corrispondenza tra tipi.
Purtroppo l'impiego dei puntatori rappresenta per me un ostacolo non facile da superare, anche per la mancanza di guide adeguate in merito all'argomento, soprattutto per i puntatori agli array.
Quando, inizialmente, ho dichiarato il puntatore agli array globali del mio programma, ho utilizzato una dichiarazione del tipo
PtbCor = ^array of array of string;
ma il compilatore si arrabbia e mi dice
frm2.pas(395,13) Error: Type identifier expected
frm2.pas(395,13) Fatal: Syntax error, ";" expected but "ARRAY" found
Ecco perchè poi ho usato la dichiarazione: |PtbCor = ^string;|
Effettivamente, dal punto di vista logico, mi sembra una nota stonata, ma non so se, per una peculiarità del linguaggio, non possa scrivere diversamente.
Prova questo e vedi se come spunto può starci (ho copiato solo il contenuto della Unit, la Form ha un pulsante Button1)
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
tar = array of array of string;
ptar = ^tar;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
public
end;
var
Form1: TForm1;
Arr1: tar;
pArr2: ptar;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
//Riempimento demo dell'array e sua istanziazione
setlength(Arr1, 3);
setlength(Arr1[0],2);
setlength(Arr1[1],3);
setlength(Arr1[2],2);
Arr1[0][0] := '00';
Arr1[0][1] := '01';
Arr1[1][0] := '10';
Arr1[1][1] := '11';
Arr1[1][2] := '12';
Arr1[2][0] := '20';
Arr1[2][1] := '21';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//Assegna ad Arr2 il puntatore a Arr1: gli array in questo modo sono di fatto "clonati" e condividono la stessa area di memoria
pArr2 := @Arr1;
ShowMessage(pArr2^[1][2]);
Arr1[1][2] := '45';
ShowMessage(pArr2^[1][2]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
var j, k: cardinal;
begin
//Procedura per la deallocazione di memoria: tutto ciò che viene creato a "mano" deve essere deallocato a "mano"
for j := Low(Arr1) to High(Arr1) do
for k := Low(Arr1[j]) to High(Arr1[j]) do
setlength(Arr1[j][k], 0);
setlength(Arr1, 0);
end;
end.