* * * *

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.
Aprile 19, 2024, 05:32:45 pm

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

381 Visitatori, 0 Utenti

Autore Topic: [RISOLTO] For ... Do ... Begin ... End  (Letto 855 volte)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
[RISOLTO] For ... Do ... Begin ... End
« il: Dicembre 09, 2022, 04:10:27 pm »
La stringa Caratteri_Validi contiene tutti i caratteri alfabetici minuscoli, comprese le vocali accentate: 'qwertyuiopèéòàùìasdfghjklzxcvbnm'
La stringa Elemento contiene alcuni di quei caratteri alfabetici, oltre alla presenza di qualche carattere numerico: 'pa5ro8la'

Lo scopo è quello di esaminare, uno alla volta, i caratteri di Elemento e confrontarli con (uno alla volta) i caratteri della stringa Caratteri_Validi.
Se c'è una corrispondenza, "riempe" la Stringa_valida un carattere valla volta, altrimenmti esclude il carattere estraneo.

In parole povere, quindi, da ''pa5ro8la'' si dovrebbe arrivare a 'parola', che verrebbe finalmente aggiunta a ListBox1.

Però non appena il conteggio parte...
For Conta_Caratteri:= 1 to Length(Caratteri_Validi) do;
...immediatamente Conta_Caratteri, invece che a 1, viene inizializzato con 38 (la lunghezza di Caratteri_Validi).
La stessa cosa, ovviamente(!) succede con...
For Conteggio_Stringa:= 1 To Length(Elemento) do;

Perché i conteggi non partono da 1, come dovrebbero?

Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
Var Elemento, Caratteri_Validi, Stringa_valida, Carattere_selezionato: string;
Var Conta_Caratteri, Conteggio_Stringa: integer;
begin
       Stringa_valida:='';
       Conteggio_Stringa:=0;
       Elemento:='pa5ro8la';
       Caratteri_Validi:='qwertyuiopèéòàùìasdfghjklzxcvbnm'; // Intero alfabeto minuscolo, comprese vocali accentate
       Begin
          // DOVREBBE(!) leggere un carattere alla volta, partendo DAL PRIMO di "Caratteri_Validi"
          // INVECE "Conta_Caratteri" invece di 1 inizia subito dalla lunghezza di "Caratteri_Validi" (38)
          For Conta_Caratteri:= 1 to Length(Caratteri_Validi) do;
             Begin
                For Conteggio_Stringa:= 1 To Length(Elemento) do;
                // La stessa cosa con  "Conteggio_Stringa". Perché?
                    Begin
                       Carattere_selezionato:= Copy(Elemento,Conteggio_Stringa,1);
                         If Pos(Carattere_selezionato,Caratteri_Validi) > 0  Then
                             Begin
                                  Stringa_valida:=Stringa_valida + Carattere_selezionato;
                             End;
                    End;
             end;
        End;
                  ListBox1.Items.Add(Stringa_valida);
                  Refresh;
End;
« Ultima modifica: Dicembre 09, 2022, 04:37:07 pm da AlexLazarus »

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:For ... Do ... Begin ... End
« Risposta #1 il: Dicembre 09, 2022, 04:32:55 pm »
Mettendo il "punto e virgola" dopo ogni "do", stai facendo finire lì i 2 cicli for.
Prova a cancellare quei 2 "punto e virgola", e vedrai che parte da 1.

Ciao, Mario

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:For ... Do ... Begin ... End
« Risposta #2 il: Dicembre 09, 2022, 04:36:36 pm »
Mettendo il "punto e virgola" dopo ogni "do", stai facendo finire lì i 2 cicli for.
Prova a cancellare quei 2 "punto e virgola", e vedrai che parte da 1.

Malediz, porc, dannaz... ho perso tutta la mattinata, la soluzione era proprio davanti ai miei occhi e non me ne sono accorto!

P.S. Grazie!

giacomarko

  • Full Member
  • ***
  • Post: 105
  • Karma: +6/-0
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #3 il: Dicembre 09, 2022, 05:28:10 pm »
In questo modo rifai il loop di controllo del carattere da testare, partendo dal primo fino all'ultimo carattere ammesso, moltiplicato per tutti i caratteri stringa da controllare ... funziona ma... :-[

In alternativa a due loop, si può utilizzare per la parte controllo un Set con la keyword In

il Set è la sequenza di lettere corrette,
al posto della ShowMessage:
componi la stringa quando il valore è vero,
viceversa non fai nulla

Chiaramente il Set lo puoi/devi definire ad un livello superiore di chiamata, in modo da non doverlo inizializzare ogni volta

Codice: [Seleziona]
// Test if a character is a letter
procedure TForm1.IsLetter(Letter : char);
var
  Alphabet : set of 'A'..'Z';
begin
  Alphabet := ['A'..'Z'];

  if Letter In Alphabet then
    ShowMessage(Letter+' is in the alphabet')
  else
    ShowMessage(Letter+' is NOT in the alphabet');
end;
SO: W11
Release Lazarus: 3.0 del 2023.12.17 win32/win64
Versione FPC: 3.2.2
DB: MySQL 5.0, MSAccess

brunello

  • Jr. Member
  • **
  • Post: 83
  • Karma: +0/-0
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #4 il: Dicembre 09, 2022, 05:29:52 pm »
oppure così
Codice: [Seleziona]
var
  Elemento, Caratteri_Validi, Stringa_valida: string;
  i: integer;
begin
  Stringa_valida := '';
  Conteggio_Stringa := 0;
  Elemento := 'pa5ro8la';
  Caratteri_Validi := 'qwertyuiopèéòàùìasdfghjklzxcvbnm'; // Intero alfabeto minuscolo, comprese vocali accentate
  for i := 1 to Length(Elemento) do
    if Pos(Elemento[i], Caratteri_Validi) > 0 then
      Stringa_valida := Stringa_Valida + Elemento[i]
  ListBox1.Items.Add(Stringa_valida);
  Refresh;

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #5 il: Dicembre 09, 2022, 10:28:55 pm »
Fate attenzione che le stringhe che contengono caratteri UTF8 (quelli accentati per intenderci) devono essere confrontati con le funzioni equivalenti UTF8 (quindi non con POS())....

Guardate una recente discussione su questo argomento (di cui non ricordo il link).

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

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #6 il: Dicembre 10, 2022, 07:50:24 am »
Fate attenzione che le stringhe che contengono caratteri UTF8 (quelli accentati per intenderci) devono essere confrontati con le funzioni equivalenti UTF8 (quindi non con POS())....
...uhmm... utilizzando POS() individuo tutte le vocali accentate (àèéìòù). Ho infatti appena completato un Video Tutorial che (spero) pubblicherò oggi pomeriggio.
Piuttosto, sarebbe certamente utile approfondire la gestione dei caratteri UTF8 per andare "oltre" il valore 127.
Esempio banalissimo (vedi anche screenshot) nel progetto qui di seguito indicato: il carattere ä viene individuato (ma davvero corrisponde a 195?) ma il viceversa produce un risultato... nullo.
P.S. La variabile s non c'entra nulla: è un rimasuglio di un test precedente. ;)
Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
Var Valore:  Integer;
Var Carattere: string;
begin
  If Length(Edit1.text)> 0 then
  Begin
    Carattere:= LeftStr(Edit1.Text,1);
    Valore:= integer(Ord(Edit1.text[1]));
    ShowMessage(Carattere);
    Label2.Caption:= ('Il valore ASCII di ' + Carattere + ' è: ' +  IntToStr(Valore));
  end;
end;

procedure TForm1.Button2Click( Sender: TObject);
Var Numero: Byte;
Var Carattere, S: String;

Begin
  Numero:= StrToInt(Edit2.Text);
  Carattere:= Chr(Numero);
  Label4.Caption:= ('Il carattere ASCII corrispondente è: ' + Carattere);
end;
[/]
« Ultima modifica: Dicembre 10, 2022, 07:52:36 am da AlexLazarus »

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #7 il: Dicembre 10, 2022, 10:05:50 am »
Occhio, che stai facendo confusione !!!
Con UTF8, alcuni caratteri occupano 2 bytes. Dall'ultima immagine che hai postato, vedi che c'è qualcosa che non va, perché invece di emettere il carattere, emette il punto di domanda. Probabilmente, quel carattere è dato dal valore ascii 195, + quello successivo.

Provo a piegarmi con un esempio:
Codice: [Seleziona]
ShowMessage(IntToStr(Length('à')));

Il codice qui sopra, ti emetterà 2, e non 1 !!!

Ciao, Mario

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #8 il: Dicembre 10, 2022, 10:40:48 am »
L'uso dei caratteri (conversione, ricerca, comparazione) è stato sempre un problema, che se fino agli anni 2007 circa  veniva gestito con la funzionalità detta codepage (praticamente un set di caratteri standardizzati per ogni lingua) ed era relativamente semplice eseguire le operazioni standard, dopo quell'anno l'avvento dell'unicode come nuovo standard (ad esempio Windows è un sistema unicode) ha creato ancora più "caos".

Prima 2007 (ANSI su tabelle codepage): caratteri di 8 bit tabellati per ogni lingua, idioma, etc ...
Pos, chr, ord: funzioni sempre esistite senza alcun problema. L'unica vera spina del fianco era che il caricamento di un codepage specifico (tedesco ad esempio) non ti consentiva di usare i caratteri italiani e gli scambi testuali semplici erano impossibili (una stringa scritta in tedesco con le dieresi venivano rappresentate solo con il codepage tedesco, e se usavi un software con il codepage italiano venivano rappresentati "caratteri strani".

La standardizzazione di più idiomi ha portato alla adozione universale dello standard Unicode (tra i più noti UTF8 e UTF16).

Dopo 2007, Unicode: i caratteri non sono più formati da 8 bit ma da almeno 16 bit, fatto salvo che solo in UTF8 la rappresentazione dei primi 127 caratteri ASCII viene fatta a 8 bit, in pratica lettere, numeri, caratteri speciali e di punteggiatura occidentali standard (definiti secondo lo standard ASCII) vengono ancora rappresentati come 8 bit in UTF8, mentre qualsiasi altro carattere avrà una lunghezza di almeno 2 byte (sino ad arrivare a 7 byte con il recente inserimento dei caratteri emoticons). In UTF16 i caratteri vengono rappresentati sempre con 16 bit o 32 bit e attualmente sono "mappati" circa 128000 caratteri in tutte le lingue. SOLO I primi 128 caratteri di UTF8 e UTF16 vengono rappresentati in maniera simile ($xx per UTF8 e $00xx x UTF16)

Dopo 2007: caratteri rappresentati genericamente da due byte (eccetto per i caratteri chiamiamoli  "base" in UTF8), e relativamente semplice gestione delle stringhe, che però diventano totalmente incompatibili con la vecchia gestione pre UNICODE. Il software deve prevedere che i caratteri hanno una lunghezza variabile e non più di un byte. Impossibile anche effettuare una conversione corretta "misciando" codice ANSI e UNICODE, codice carattere e valore numerico non possono essere convertiti tra loro senza sapere che codifica si stà usando (ANSI, UTF8, UTF16 ?). La conversione Maiuscolo/Minuscolo e viceversa rappresenta un problema perchè non esiste nello standard un parametro di conversione di questo tipo.

...uhmm... utilizzando POS() individuo tutte le vocali accentate (àèéìòù). Ho infatti appena completato un Video Tutorial che (spero) pubblicherò oggi pomeriggio.
Piuttosto, sarebbe certamente utile approfondire la gestione dei caratteri UTF8 per andare "oltre" il valore 127.
Esempio banalissimo (vedi anche screenshot) nel progetto qui di seguito indicato: il carattere ä viene individuato (ma davvero corrisponde a 195?) ma il viceversa produce un risultato... nullo.

Ecco perchè quel carattere non viene rappresentato dal tuo software .... il codice di "ä" non è semplicemente "195" ma bensì "$c3a4", il tuo codice prende erroneamente solo il primo byte del carattere "$c3" che corrisponde a 195.

Mentre prima le ricerche, comparazioni, etc..., venivano effettuate a "byte" ora si devono usare tramite i "codepoint" cioè marcatori che definiscono la lunghezza del carattere (... di ogni singolo carattere ....) all'interno di una stringa. I "codepoint" sono implementati genericamente solo nella funzioni abilitate per le operazioni UNICODE, non per quelle standard.

Se si usano solo ed esclusivamente i caratteri inglesi tuttavia non si riscontreranno genericamente problemi, in quanto come si diceva UTF8 ha i primi 128 caratteri a solo 8 bit (che guarda caso corrispondono ai classici caratteri inglesi delle tastiere internazionali).

Perchè UTF8? Perchè molti ambienti di programmazione si sono concentrati molto su questa codifica in quanto usata per diversi aspetti universali. Qualsiasi carattere proveniente da un sito web è codifica in UTF8, alcuni database gestiscono i caratteri in UTF8, alcuni sistemi operativi gestiscono nativamente i caratteri in UTF8 (le api WINDOWS li gestiscono SOLO in UTF16, o meglio un sottoinsieme di UTF16).

Lazarus è uno di questi ambienti, Delphi invece usa principalmente UTF16 per compatibilità storica con Windows anche se il listato del programma viene salvato in UTF8  :o

Questo un link per divertivi a vedere la codifica dei vari caratteri, potete usare un programma tipo word o un qualsiasi sito web in una lingua nazionale (l'arabo ad esempio) per copiare / incollare il carattere che vi interessa e vedere la codifica o viceversa:
https://onlineutf8tools.com/convert-utf8-to-hexadecimal

Qui ulteriori riferimenti: https://it.wikipedia.org/wiki/Unicode.

Qui riferimenti x Lazarus e FPC: https://wiki.freepascal.org/Unicode_Support_in_Lazarus

Ci sono diversi Topic e POST su questi argomenti nel nostro forum, anche ben approfonditi e con esempi. Effettuate una ricerca per approfondire l'argomento.

P.S.: tanto per curiosità solo la lingua cinese ha un "set" documentato di oltre 80000 caratteri (di cui moltissimi di usa rarissimo) di cui implementati in unicode sembra ce ne siano circa 40000 (non c'è un dato ufficiale su questo perchè i caratteri Unicode sono asettici rispetto alla lingua, quindi ad esempio "caratteri" giapponesi e cinesi identici hanno una sola codifica).

Ciao
« Ultima modifica: Dicembre 10, 2022, 11:39:12 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

giacomarko

  • Full Member
  • ***
  • Post: 105
  • Karma: +6/-0
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #9 il: Dicembre 10, 2022, 11:29:04 am »
Grazie DragoRosso per la dettagliatissima spiegazione !!

curiosità personale...

nell'uso di In come nel mio suggerimento, questo problema si pone ancora ?

m
SO: W11
Release Lazarus: 3.0 del 2023.12.17 win32/win64
Versione FPC: 3.2.2
DB: MySQL 5.0, MSAccess

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] For ... Do ... Begin ... End
« Risposta #10 il: Dicembre 10, 2022, 11:54:05 am »
Grazie DragoRosso per la dettagliatissima spiegazione !!
curiosità personale...
nell'uso di In come nel mio suggerimento, questo problema si pone ancora ?
m

Da quel che sò, però in Lazarus non conosco precisamente l'implementazione, IN può essere usato in un set di al massimo 256 elementi, ossia un set non può contenere più di 256 elementi, quindi qualsiasi implementazione deve rispecchiare tale limite.

L'elemento di un set deve essere omogeneo, non si possono "misciare" numeri, caratteri od altro.

Secondo mè l'implementazione di un SET (e quindi di un IN) nel caso di caratteri UTF8 non appartenenti ai primi 128 caratteri di base provoca problemi (tempo fà avevo fatto un prova in Delphi, ma funzionava solo per caratteri con codifica a 16 bit, con caratteri misti 16 / 32 bit mi dava errore in compilazione ad esempio).

Occorrerebbe effettuare diverse prove, tenendo conto anche dei modificatori ($DEFINE) che possono essere inseriti per modificare il comportamento di Lazarus nei confronti della gestione UNICODE / ANSI.

Bisogna poi ricordarsi che FPC supporta solo parzialmente la funzionalità nativa UNICODE e che il supporto maggiore deriva da Lazarus. Questo implica principalmente problematica di "velocità" del codice e alcune attenzioni per le dovute conversione da fare a "mano".

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

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18772
  • Topic in totale: 2233
  • Online Today: 578
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 381
Total: 381

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.