* * * *

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.
Novembre 27, 2024, 08:33:58 am

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

26 Visitatori, 2 Utenti
   

Autore Topic: Questa è bella  (Letto 1173 volte)

petrusic

  • Hero Member
  • *****
  • Post: 629
  • Karma: +0/-0
Questa è bella
« il: Marzo 13, 2021, 10:58:39 pm »
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 è:
Citazione
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:
Codice: [Seleziona]
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?

ciao ciao

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2922
  • Karma: +20/-4
Re:Questa è bella
« Risposta #1 il: Marzo 13, 2021, 11:26:34 pm »
quando una if ha anche la clausola else, non ci deve essere il ; dopo l'end che precede l'else

è errato scrivere

Codice: [Seleziona]
if condizione 
  begin
     istruzione1;
  end;
  else
    begin
      istruzione2;
   end;

in quanto il ; chiude l'istruzione

è invece corretto:
Codice: [Seleziona]
if condizione 
  begin
     istruzione1;
  end
  else
    begin
      istruzione2;
   end;
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 629
  • Karma: +0/-0
Re:Questa è bella
« Risposta #2 il: Marzo 14, 2021, 04:15:01 pm »
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 :
Citazione
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:
Codice: [Seleziona]
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ì:
Codice: [Seleziona]
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;                                                 
ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1407
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Questa è bella
« Risposta #3 il: Marzo 14, 2021, 04:56:48 pm »
Perchè usi i puntatori: a meno che non devi interfacciarti con librerie fatte tipicamente in C o C++ non c'è necessità di usare i puntatori.

Dichiarazione di una stringa:

var
   pippo: string;

Accesso al primo carattere della stringa:

  if pippo[1] = 'X' then
    begin
        //Fai qualcosa
    end;

Attento che:

Ansistring e WideString hanno la composizione dei caratteri diversa, ossia ansistring è formata da una serie di caratteri di 8 bit, mentre widestring (così come unicode) invece ha una lunghezza del carattere di 16 bit.

Se usi le funzioni tipiche delle stringhe non noti la differenza, mentre se usi puntatori o movimenti di memoria puoi andare incontro a spiacevoli inconvenienti.

Inoltre la comparazione qui sopra indicata è "CASE SENSITIVE", cioè 'X' e 'x' sono diversi.

P.S.: OVVIAMENTE NON PUOI ACCEDERE AD UNA POSIZIONE che và oltre la lunghezza della stringa stessa.

pippo := 'Ciao';
if pippo[7] = ....
  VIENE GENERATA UNA ECCEZIONE A RUNTIME !!!

« Ultima modifica: Marzo 14, 2021, 04:59:44 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1407
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Questa è bella
« Risposta #4 il: Marzo 14, 2021, 05:28:20 pm »
Citazione
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ì:

var
   tantipippo: array of array of string;    //array bidimensionale

//prima di tutto devi creare l'istanza dell'array con un numero di elementi (anzi con due numeri di elementi)
//qui te la faccio lunga, per dimostrarti il concetto
  setlegnth(tantipippo, 5);
  setlength(tantipippo[0], 3);
  setlength(tantipippo[1], 4);
  setlength(tantipippo[2], 3);
  setlength(tantipippo[3], 7);
  setlength(tantipippo[4], 3);
//avrai un array non simmetrico con un numero variabile di "sottoelementi", accederai così:

  tantipippo[0][0] := 'Sono il primo elemento in assoluto';
  tantipippo[0][1] := 'Sono il secondo elemento della prima riga';
  tantipippo[0][2] := 'Sono l'ultimo elemento della prima riga';

  tantipippo[1][0] := 'Sono il primo elemento della seconda riga';
  tantipippo[1][1] := 'Sono il secondo elemento della seconda riga';
  tantipippo[1][2] := 'Sono il terzo elemento della seconda riga';
  tantipippo[1][3] := 'Sono l'ultimo elemento della seconda riga';

  e così via .....

  tantipippo[0][0][1] := 'A';

  ShowMessage(tantipippo[0][0]);

  risualtato =>   Aono il primo elemento in assoluto


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

petrusic

  • Hero Member
  • *****
  • Post: 629
  • Karma: +0/-0
Re:Questa è bella
« Risposta #5 il: Marzo 14, 2021, 06:47:14 pm »
Perchè usi i puntatori: a meno che non devi interfacciarti con librerie fatte tipicamente in C o C++ non c'è necessità di usare i puntatori.
Nello spezzone di codice che ho riportato nel mio precedente post, a seconda del contenuto del paramtetro "rifTb"('M', 'R', 'Q'), devo accedere ai contenuto di un o dei tre array globali corrispondenti.
a me sembra che sia più logico farlo attraverso i puntatori.

L'alternativa a tale metodo è quella di copiare tutto l'array occorrente  in locale e poi utilizzare detto contenuto.
In questa fase di esercitazione-studio vorrei approfondire il concetto del puntamento agli array, però se è veramente così arduo addentrarsi in simili argomentazioni, allora sarò costretto, mio malgrado a rinunziare.

Con ciò voglio dire che conosco la strada alternativa, ma, abbandonando il percorso iniziato sui puntamenti agli array, non cresco nelle mie pur modeste conoscenze del pascal.
ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1407
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Questa è bella
« Risposta #6 il: Marzo 14, 2021, 07:45:06 pm »
 ... scusami, non avevo intenzione di scoraggiarti dal tuo intento (che non avevo compreso) ...

Vorrei darti due consigli:

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. Non saprei in Lazarus (sono nuovo di questo ambiente) come fare in maniera più formale, ma eventualmente forse ti conviene usare un puntatore generico e fare poi il casting.

2) Ricordati che un array (normalmente) ha il primo elemento in posizione 0 (chiamalo indice o altro), ma le stringhe (che sono anch'esse un array) hanno il primo elemento in posizione 1 (indice).

Lascio ad altri più esperti di Lazarus ad indicarti eventualmente la strada.

Buon proseguimento.
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

petrusic

  • Hero Member
  • *****
  • Post: 629
  • Karma: +0/-0
Re:Questa è bella
« Risposta #7 il: Marzo 15, 2021, 09:04:35 am »
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
Codice: [Seleziona]
  PtbCor = ^array of array of string;
ma il compilatore si arrabbia e mi dice
Citazione
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.


ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1407
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Questa è bella
« Risposta #8 il: Marzo 15, 2021, 03:39:56 pm »
Prova questo e vedi se come spunto può starci (ho copiato solo il contenuto della Unit, la Form ha un pulsante Button1)

Codice: [Seleziona]
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.
« Ultima modifica: Marzo 16, 2021, 09:30:44 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2922
  • Karma: +20/-4
Re:Questa è bella
« Risposta #9 il: Marzo 16, 2021, 06:41:19 pm »
DragoRosso, per favore, quando includi del sorgente, usa i tag "code"
si tratta del bottone col simbolo del cancelletto (o hashtag) "#"
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1407
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Questa è bella
« Risposta #10 il: Marzo 16, 2021, 09:31:31 pm »
 :) Fatto.
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2922
  • Karma: +20/-4
Re:Questa è bella
« Risposta #11 il: Marzo 17, 2021, 08:10:52 am »
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ì:

ciao

fondamentalmente un array lo devi vedere come un puntatore ad un'area consecutiva di memoria dedicata alla memorizzazione indicizzata di variabili dello stesso tipo


dai un'occhiata a questi link

https://freepascal.org/docs-html/ref/refsu14.html
https://wiki.lazarus.freepascal.org/Multidimensional_arrays

e poi anche qua
https://www.tutorialspoint.com/pascal/pascal_arrays.htm





Imagination is more important than knowledge (A.Einstein)

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19209
  • Topic in totale: 2289
  • Online Today: 100
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 2
Guests: 26
Total: 28

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.