Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Diego1981 - Agosto 31, 2021, 01:58:59 pm

Titolo: ASCII
Inserito da: Diego1981 - Agosto 31, 2021, 01:58:59 pm
Buongiorno
come da titolo si capisce che sono nei meandri profondi della confusione
Ho letto post sull'argomento qui nel sito ed anche dal sito ufficiale di Lazarus e mi sembra di avere capito che devo mettere mano alle opzioni del compilatore quindi prima vorrei essere sicuro dei disastri che posso combinare
La domanda è questa
perchè se converto da decimale i valori 120-156 ottengo questi 2 caratteri "xœ"
ma se faccio l'operazione inversa , durante il debug, vedo i seguenti valori 120-197-147?
Se ho capito bene è questione di codepage....ma.....bo
grazie mille come sempre
Titolo: Re:ASCII
Inserito da: bonmario - Agosto 31, 2021, 06:32:17 pm
Avere a disposizione del codice, e magari sapere cosa vuoi fare e cosa ottieni di diverso da quello che ti aspetti, sarebbe sempre meglio ...
Così a grandi linee, mi viene da dire che stai usando delle variabili di tipo "string", che da qualche versione del compilatore sono in formato UTF-8, quindi potrebbe esserci la differenza che segnali tu.

Prova a dare un occhio a questo link: https://wiki.freepascal.org/String

P.S. Tieni conto che in Lazarus non c'è un solo debugger, ed alcuni di questi a volte ti cambia a valori sotto il naso, e quello che vedi non è il reale valore della variabile.
Per esempio, le variabili di tipo TDate, sono dei numeri decimali, ma se li guardi da debugger, spesso te le fa vedere nel formato GG/MM/AAAA

Ciao, Mario
Titolo: Re:ASCII
Inserito da: Diego1981 - Settembre 01, 2021, 02:10:53 pm
Ciao Mario
grazie intanto

ho semplificato il codice e come dicevi tu ho utilizzato delle variabili di tipo string
sono 2 bottoni con un memo e il risultato è quello che dicevo
leggendo qua e la ho trovato la funzione WinCPToUTF8 per i caratteri sopra il 127 che senza non mi permetteva di vedere proprio niente nel memo


procedure TForm1.Button1Click(Sender: TObject);
var
  s1,s2:string;
begin
  Memo1.Clear;
  s1:=''; s2:='';
  S1:=WinCPToUTF8(chr(120));
  S2:=WinCPToUTF8(chr(156));
  Memo1.Append(s1);
  Memo1.Append(s2);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i:Integer;
  str:String;
begin
  Memo1.Clear;
  str:='xœ';
  for i:=1 to Length(str) do
    begin
      Memo1.Append(IntToStr(Ord(str)));
    end;
end;
Titolo: Re:ASCII
Inserito da: bonmario - Settembre 01, 2021, 02:21:17 pm
Scusa, ma non capisco se quello che hai postato l'hai postato per dire che hai risolto, o per dire che hai ancora qualche problema. In questo caso, quale problema hai ?

P.S. Guardando velocemente il codice, vedo che usi "length", ma essendo la stringa UTF-8, e sapendo in partenza che userai caratteri speciali, probabilmente sarebbe più corretto usare UTF8Length, che io però non ho mai usato ...

Se metti in debug il tuo programma, probabilmente "Length(str)" è uguale a 3.

Prova a dare un occhio qui: https://wiki.freepascal.org/Unicode_Support_in_Lazarus

Ciao, Mario
Titolo: Re:ASCII
Inserito da: Diego1981 - Settembre 01, 2021, 02:51:40 pm
scusami  forse non mi sono spiegato
ho inserito il codice per darti l'idea di come ho provato ad eseguire il tutto
il concetto è che se dagli interi 120-156 ottengo 2 caratteri (o simobli) non riesco ad eseguire l'operazione inversa
ora butto un occhio agli altri link che mi hai dato
gentilissimo
Titolo: Re:ASCII
Inserito da: bonmario - Settembre 01, 2021, 03:08:50 pm
Hai le idee un po' confuse !!!

In parole povere, siccome le stringhe sono codificate UTF-8, quando tu metti nella stringa str:='xœ'; ci stai mettendo dentro 3 caratteri in codice ASCII, ma allo stesso tempo son 2 caratteri in codifica UTF-8.

Tanto è vero, che UTF8Lenght della tua stringa restituisce 2, mentre Length restituisce 3.

C'è anche un altra cosa, che non ho mai dovuto gestire, quindi non ti so aiutare, credo che "Ord" funzioni con i caratteri ASCII, non so se ne esiste qualcosa di equivalente anche per i caratteri UTF-8, anche perché, in UTF-8, un singolo carattere può essere rappresentato con 1 o con 2 codici ASCII

Ciao, Mario
Titolo: Re:ASCII
Inserito da: DragoRosso - Settembre 02, 2021, 12:50:47 am
Il tipo string non è adatto a mantenere caratteri di alcun tipo che non rappresentino altro che testo, in qualsiasi formato, lingua o dialetto, MA ESCLUSIVAMENTE TESTO.

Il contenuto di un tipo string viene valutato e rappresentato in modalità e con risultati diversi a seconda del contesto. In particolare, "l'assemblaggio" di caratteri non testuali può presentare parecchie sorprese.

La codifica UTF8 è una codifica a lunghezza variabile fino a 4 byte (*), e la cui particolarità è che i primi 127 caratteri ASCII corrispondono esattamente alla rappresentazione UTF8 con lunghezza 1 byte.

Altra pecularità è che in prima posizione in un "carattere" UTF8 non può mai esserci un valore 192 o 193.

Inoltre ci sono dei "buchi" nelle rappresentazioni possibili: i valori UNICODE da 127 a 159 (U+007F / U+009F) non sono trattati come caratteri ma come "comandi" nello standard UTF8.

(*): in realtà UTF8 potrebbe contenere fino a 8 byte, ma per allinearlo a UNICODE (la cui lunghezza massima è di 4 byte con UNICODE 32) la rappresentazione oltre la quarta posizione non è ammessa.

Se trasformi dei valori da 0 a 255 in caratteri UTF8  la rappresentazione del valore corrispondente produce un carattere UTF8 complesso: un valore oltre al 126 dipende dal sistema OS in uso e dalla sua "lingua", un valore 230 trasformato in UTF8 in ambiente cinese rappresenta un UTF8 diverso da un 230 inglese e una volta composta la stringa dovresti fare un parsing inverso (ammettendo che un UTF8 possa essere riconvertito in byte). 

Dopo questo escursus molto approssimativo e forse un pò "pesante", chiudo per consigliare l'uso di TByteArray per contenere valori o del formato più versatile TBytes.

Ciao
Titolo: Re:ASCII
Inserito da: Diego1981 - Settembre 02, 2021, 12:58:58 pm
Ciao Drago
ti ringrazio prima di tutto
in effetti ho notato che l'argomento è abbastanza discusso e anche ostico