* * * *

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 18, 2024, 06:02:08 pm

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

348 Visitatori, 0 Utenti

Autore Topic: [RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici  (Letto 1423 volte)

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Risolto un problema, se ne presenta ovviamente(!) un altro.
Come già detto, nel topic sulle vocali accentate (https://www.lazaruspascal.it/index.php?topic=2680.0) tutto funziona perfettamente ma...
Ma inserendo la routine all'interno di un programma più complesso sorgono errori incomprensibili. Dunque...

Lo scopo è, in poche parole, estrarre da un file di testo TXT tutte le parole formate da caratteri alfabetici (con eventuali vocali accentate) escludendo tutti gli altri, eventualmente convertendole tutte in minuscolo / maiuscolo.

Ho iniziato con vari tentativi, partendo proprio dal carattere di spazio.

1) Il file banale di testo testo Varie_parole.TXT (1 nello screenshot) sono presenti diversi righi, alcuni dei quali contengono una sola parola senza vocali accentate, altri parole con vocali accentate, altri ancora più parole separate da uno spazio (lasciate perdere il significato, è solo un esempio).

2) Caricando il file di testo (con il programma che riporto in calce) nel ListBox1 (2) lo sottopongo a elborazione premendo il Button1 ("Separa parole", 3), infine (ma non è necessario) elimina le eventuali righe vuote (4a e 4b).

3) Nel listbox2 dovrebbero(!) essere trasferite le singole parole (4a e 4b), eventualmente suddivise su più righi se in listbox1 sono su un unico rigo, separate da spazio.
 
Come si può notare alcune parole vengono correttamente suddivise mentre altre no. Inoltre alcune presentano spazi all'inizio, in altre viene escluo l'ultimo carattere.



E' da stamattina che sto facendo vari tentativi ma non riesco proprio a capire dove sbaglio.

Codice: [Seleziona]
unit A_2022_11_09_Prog_230_Pulisci_file_Testo_A_pas;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Menus, StdCtrls, LazUtf8;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    ListBox1: TListBox;
    ListBox2: TListBox;
    MainMenu1: TMainMenu;
    MenuItem1: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    MenuItem5: TMenuItem;
    MenuItem6: TMenuItem;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ListBox2Click(Sender: TObject);
    procedure MenuItem2Click(Sender: TObject);
    procedure MenuItem5Click(Sender: TObject);
    procedure MenuItem6Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.MenuItem2Click(Sender: TObject);
// Carica file di testo in ListBox1
Var NomeFile: string;
Var sl: TStringList;
  begin
    if OpenDialog1.Execute then
    Begin
    NomeFile:= OpenDialog1.FileName;
    //ShowMessage (NomeFile);
      if FileExists(NomeFile) then
          Begin
            ShowMessage('Il file: ' + NomeFile + ' esiste');
            end
            else if  FileExists(NomeFile) =False Then
            ShowMessage('Il file: ' + NomeFile + ' NON esiste');

       sl:=TStringList.Create;
       try
          sl.LoadFromFile(NomeFile);
          ShowMessage('righe lette: ' + IntToStr(sl.Count));
          ListBox1.Items.LoadFromFile(NomeFile);
          finally
          sl.Free;
       end;
    end;
  end;

procedure TForm1.MenuItem5Click(Sender: TObject);
begin
 Label1.Caption:='';
 Label2.Caption:='';
 Label2.Caption:='';
 ListBox1.Clear;
end;

procedure TForm1.MenuItem6Click(Sender: TObject);
begin
 Label1.Caption:='';
 Label2.Caption:='';
 Label2.Caption:='';
 ListBox2.Clear;
end;

procedure TForm1.Button1Click(Sender: TObject);
// Separa parole e le mette in ListBox2
//Var Rigo,Car1, Car2, Parola, tempstr:String;
Var Car1, Car2, Rigo, Parola, tempstr :String;
Var  UTtempstr: UnicodeString;
Var I,Y, Numero_Massimo_Righe:Integer;
begin
Parola:='';
Numero_Massimo_Righe:=ListBox1.items.count;
Label1.Caption:=('');
Label2.Caption:=('');
For I := 0 to Numero_Massimo_Righe-1 do
     Begin
          Parola:= '';
          Rigo:= ListBox1.items.strings[I];
          tempstr := Rigo;
          UTtempstr := tempstr;
        for Y := 0 to UTF8Length(tempstr)-1 do
            Begin
             Car1 :=Copy(rigo,Y+1,1);
             car2 := Utf8Copy(tempstr, Y+1, 1);
                  // If ( (Car2 = 'è') Or (Car2 = 'è') Or (Car2 = 'é') Or (Car2 = 'ò' )Or (Car2 = 'à') Or (Car2 = 'ù') Or (Car2 = 'ì') Or (Car2 = ' ') Or (Car2 = '-') Or (Car2 = '(') Or (Car2 = ')') Or (Car2 = ',')) Then
                 If ( (Car2 = 'è') Or (Car2 = 'é') Or (Car2 = 'ò' )Or (Car2 = 'à') Or (Car2 = 'ù') Or (Car2 = 'ì') Or (Car2 = ' ')) Then
                     Begin
                          Parola:=Parola + Car2;
                          If Car1 =' '  then
                            Begin
                                 ListBox2.items.add(Parola);
                                 Parola:= '';
                            end;
                     End;
                 //Else
                 Parola:= Parola + LowerCase(Car1);
                      If Utf8Copy(tempstr, Y+1, 1) = (' ') then
                 //If Car1 = (' ')then    //  If Car1 = Chr(32)
                    Begin
                         ListBox2.items.add(Parola);
                         Parola:='';
                  end;
           end;
        ListBox2.items.add(Parola);
        Parola:='';
        end;
 Label2.Caption:='N. parole: ' + IntToStr(ListBox2.items.count);
end;

procedure TForm1.Button2Click(Sender: TObject);
// Conta i caratteri dell'intero file caricato
Var Rigo: String;
Var N_Caratteri: QWord;
Var I, Y, Z: Integer;
begin
N_Caratteri:=0;
Label1.Caption:='';
Label2.Caption:='';

     I := ListBox1.items.count;
 For Y := 0 to I-1 do
      Begin
       Rigo:= ListBox1.items.strings[Y];
       Z:= Length(Rigo);
       N_Caratteri:= N_Caratteri + Z;
      end;
 Label4.Caption:=('N. caratteri: ' + IntToStr(N_Caratteri));
end;

procedure TForm1.Button3Click(Sender: TObject);
// Elimina parole di lunghezza nulla
Var N_Parole: QWord;
Var I, Y,Z: Integer;
Var  Rigo: string;
begin
 N_Parole:= 0;
  I := ListBox2.items.count;
 For Y := I-1 downto 0 do
      Begin
           ListBox2.itemindex := Y;
           Rigo:= ListBox2.items.strings[Y];
           Z:= Length(Rigo);
       If (Z = 0) OR (Rigo =(' ')) then
           Begin
            ListBox2.DeleteSelected;
           end;
      end;
 Label1.Caption:=('Spazi vuoti eliminati: ' + IntToStr( ListBox2.items.count));
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

procedure TForm1.ListBox2Click(Sender: TObject);
begin
  //Label1.Caption:= ListBox2.items.strings[ListBox2.itemindex];
  Label3.Caption:='Lunghezza parola selezionata: ' + IntToStr(Length(ListBox2.items.strings[ListBox2.itemindex]));
end;


end.

...ed ecco il banale file di testo:

Codice: [Seleziona]
Perchà
Pà ab
c
d
v b
Perchò
Perchù
Perchì
Perché mai dovrei quantunquemente
Tre parolone basta

Quattro fdkgjh
Cinque lhgfb
g
[/]
« Ultima modifica: Novembre 13, 2022, 08:21:39 am da AlexLazarus »

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Gestione vocali accentate, spazio (e altri caratteri esclusivamente alfabetici)
« Risposta #1 il: Novembre 10, 2022, 07:29:03 pm »
Non puoi usare gli strumenti standard tipo:
Codice: [Seleziona]
 Car1 :=Copy(rigo,Y+1,1);
con i caratteri unicode. Devi usare o le stringhe Unicode (UnicodeString) o le funzioni Utf8Copy ad esempio.

Questo per tutto ciò che non è una semplice concatenazione (string + string).

Il Length, il Copy, etc ..... sono metodi che non funzionano con le stringhe che contengono caratteri UNICODE !!!

Secondo me forse è meglio che definisci le stringhe come UnicodeString, e dovresti avere risolto. Ovviamente su quelle stringhe non puoi usare Utf8Copy o procedure simili ma userai le normali funzioni Copy, Length, etc ...

P.S.: anche la funzione "lowercase" potrebbe non funzionare con i caratteri Unicode. Non tutti i caratteri hanno un "lowercase" o un "uppercase". Non sò come si comporta la funzione quando trova questi caratteri.

P.S.2: in ogni caso, se vuoi suddividere per parola ti consiglio di studiare la funzione "SplitString", con quella fai più o meno quello che vorresti fare ma che non stai facendo .... evviva i giochi di parole  ;D

Ciao
« Ultima modifica: Novembre 10, 2022, 07:43:35 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Gestione vocali accentate, spazio (e altri caratteri esclusivamente alfabetici)
« Risposta #2 il: Novembre 11, 2022, 08:16:44 am »
Ciao,
visto che leggi da un file di testo, potresti "convertire al volo" quello che leggi.

Io mi sono fatto anni fa questa funzioncina, che uso in queste occasioni per semplificarmi la vita !!!
Codice: [Seleziona]

type TTipoOperConvStr=(tocLeggiDaFileTxt, tocScriviFileTxt);

  function ConvertiStringaFileTxt(St: String; TipoConvStr: TTipoOperConvStr): String;
  begin
    {$IFDEF MSWINDOWS}
      case TipoConvStr of
        tocLeggiDaFileTxt: St:={CP1252ToUTF8(St)}WinCPToUTF8(St);
        tocScriviFileTxt:  St:={UTF8ToCP1252(St)}UTF8ToWinCP(St);
      end;
    {$ENDIF}
    Result:=St;
  end;

Nel caso in cui non ci sia già, devi aggiungere "LazUTF8" alla uses.

Ciao, Mario

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:Gestione vocali accentate, spazio (e altri caratteri esclusivamente alfabetici)
« Risposta #3 il: Novembre 11, 2022, 09:33:55 am »
[...] ti consiglio di studiare la funzione "SplitString",[...]

Buona idea, ma c'è un problema: volendo separare anche altri caratteri (parentesi, virgole, apostrofi eccetera), credo occorra fare una concatenazione di If ... Then auto-ricorsiva (non so se mi sono spiegato bene).
Comunque, ecco una prima bozza, magari da studiarci su:
Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
Var Stringa: TStringArray;
Var Spazio, OK: string;
  Var I,X,Y: Integer;
begin
    Y:=0;
  For X:=0 to length(Edit1.text) do
      Begin
        If Copy(Edit1.Text,X,1) = ' ' then Y:= Y +1;
      end;
  OK:= Edit1.text;
        For I := 0 to Y do
          Begin
            Stringa := OK.Split(' ');
            ListBox1.items.add(Stringa[I]);
          end;
end;
« Ultima modifica: Novembre 11, 2022, 09:35:27 am da AlexLazarus »

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:Gestione vocali accentate, spazio (e altri caratteri esclusivamente alfabetici)
« Risposta #4 il: Novembre 11, 2022, 10:21:09 am »
Ciao
https://www.freepascal.org/docs-html/rtl/strutils/splitstring.html


Prova ad usare questa funzione. Puoi mettere tutti i caratteri che vuoi, non solo lo spazio.

Stilgar
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:Gestione vocali accentate, spazio (e altri caratteri esclusivamente alfabetici)
« Risposta #5 il: Novembre 13, 2022, 08:18:47 am »
Tutto (o quasi...) funziona a dovere. Qui di seguito il mio piccolo contributo a chi ha seguito questo 3D.
Un ringraziamento speciale a DragoRosso che mi ha voluto dare una dritta. 😉

La procedura:
Codice: [Seleziona]
procedure TForm1.Button5Click(Sender: TObject);
// Pulsante Split 2
Var Stringa: TStringArray;
Var OK, Car_1 : string;
Var IA,XA,YA, ZA: Integer;
begin
 If ListBox1.items.count > 0 then
 Begin
 For ZA := 0 to  ListBox1.items.count -1 do // Esamina tutte le righe di ListBox1
         begin
              For XA:=0 to length(ListBox1.items.strings[ZA]) do // Esamina uno alla volta tutti caratteri della riga di ListBox1
                  Begin
                       Car_1:= Copy(ListBox1.items.strings[ZA],XA,1);
                       If Copy(ListBox1.items.strings[ZA],XA,1) = chr(32) then YA:= YA +1;
                  end;
              // ShowMessage(Copy(ListBox1.items.strings[ZA],XA,1) + '    YA: ' + IntToStr(YA) + '    ZA: ' + IntToStr(ZA));
                  OK:= ListBox1.items.strings[ZA];
                       For IA := 0 to YA +1 do
                           Begin
                                Stringa := OK.Split(' ');
                                ListBox2.items.add(Stringa[IA]);
                           end;
                  YA:=0;
         end;
end
 else ShowMessage('Non ci sono righe di caratteri nel ListBox1!');
end;

Il file .TXT dell'esempio visibile negli screenshot:

Codice: [Seleziona]
Questa è una frase in una riga

Qui sopra c'è un rigo vuoto
Qui di seguito ci sono tre   spazi
Per di più qui c'è un rigo
Grazie all'Italian community of Lazarus and Free Pascal

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #6 il: Novembre 13, 2022, 11:37:19 am »
Prova questo:

Codice: [Seleziona]
  //Aggiungi nella USES l'unità "Types":
  Uses: Types, .......
  //
  var p: TStringDynArray;
  //Qui carichi la ListBox, occhio all'encoding !!!!!!!!!!!!!!!!!!!!
  ListBox1.Items.LoadFromFile('c:\temp\prova.txt', TEncoding.UTF8);
  //Qui è quanto serve per fare ciò che vuoi
  p := ListBox1.Items.Text.Split([' ','.',',',':',';','?','!',#1310,#13,#10], TStringSplitOptions(1));
  ListBox2.Items.AddStrings(p, true);


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

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #7 il: Novembre 13, 2022, 04:20:03 pm »
Prova questo:

Codice: [Seleziona]
  //Aggiungi nella USES l'unità "Types":
 
[ ... ] 


Ciao

E adesso me lo dici? 😡

Ovviamente: grazie! 😉 Lo proverò appena posso.

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #8 il: Novembre 14, 2022, 10:35:57 am »
Prova questo:

Codice: [Seleziona]
  //Aggiungi nella USES l'unità "Types":
 [ ... eccetera ... ] 

MERAVIGLIOSO!
Tuttavia...
1) Compare un messaggio inquietante.
2) Non accetta alcuni caratteri speciali:

Codice: [Seleziona]
 p := ListBox1.Items.Text.Split([' ' , '.' , ',' , ':' , ';' , '?' , '!' , '(' , ')' , chr(39) , '"' , chr(174) , chr(175) , chr(203) , chr(194) ,  '*' , '/' , '1' , '2' , '3', '4', '5', '6' , '7' , '8' , '9' , '0' , chr(45),     #1310,#13,#10], TStringSplitOptions(1));

Poco male, ci mancherebbe!  ;)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #9 il: Novembre 14, 2022, 02:09:06 pm »

Tuttavia...
1) Compare un messaggio inquietante.
2) Non accetta alcuni caratteri speciali:


Il messaggio non è così inquietante, ce ne sono di peggiori (a cui magari fa seguito una bella BSOD di Windows  :o  :P )....

I caratteri ANSI che immetti con valore ASCII al disopra del 127 dovrebbero essere interpretati come caratteri unicode. Non sò sinceramente come si possano comportare sia il compilatore che l'Helper Split.

Potrebbe essere utile forzare il supporto a Unicode del compilatore tramite le OPZIONI PROGETTO, aggiungendo la voce indicata nell'immagine (-FcUTF8).

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

AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #10 il: Novembre 15, 2022, 06:38:32 pm »
Citazione
Potrebbe essere utile forzare il supporto a Unicode del compilatore tramite le OPZIONI PROGETTO, aggiungendo la voce indicata nell'immagine (-FcUTF8).

Ho aggiunto FcUTF8, ma l'unica variazione è l'assenza di messaggi.

SB

  • Scrittore
  • Sr. Member
  • *****
  • Post: 283
  • Karma: +1/-0
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #11 il: Novembre 16, 2022, 03:48:33 pm »
Vista la notevole varietà di caratteri che potresti trovare nel testo, secondo me la strada che avevi intrapreso inizialmente non era male. Va solo aggiustata un po'.
Metti in un'unica stringa tutti i caratteri che decidi di accettare come formanti una parola e per esclusione tutti gli altri diventano separatori:
Validi := 'abcdefgh...ABCDE...0123...àòùèì...';
Valuti un carattere alla volta usando Pos(Carattere, Validi) anzichè una sfilza di if
Costruisci le stringhe delle parole e sei a posto

Secondo me lo Split() va bene se i separatori sono pochi e noti

Invece di costruire le stringhe un carattere alla volta, potrebbe essere più conveniente individuare l'indice iniziale e l'indice finale e poi estrarre la sottostringa


AlexLazarus

  • Jr. Member
  • **
  • Post: 91
  • Karma: +1/-0
Re:[RISOLTO] Gestione vocali accentate, spazio e caratteri alfabetici
« Risposta #12 il: Novembre 17, 2022, 03:59:09 pm »
Metti in un'unica stringa tutti i caratteri che decidi di accettare come formanti una parola e per esclusione tutti gli altri diventano separatori:
Validi := 'abcdefgh...ABCDE...0123...àòùèì...';
Valuti un carattere alla volta usando Pos(Carattere, Validi) anzichè una sfilza di if
[... eccetera ...]

Vero: l'algoritmo che ho impostato non è per nulla efficiente, me ne rendo conto. Un po' per volta apporterò modifiche, pubblicando su questo forum gli aggiornamenti.

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18770
  • Topic in totale: 2232
  • Online Today: 415
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 348
Total: 348

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.