[gelöst] - Insert geht nicht mehr...

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

[gelöst] - Insert geht nicht mehr...

Beitrag von pluto »

Hallo,
in einem neuen Test Projekt wollte ich die Insert Methode von Lazarus verwenden. Aber sie ging nicht.
Der String der eingefügt werden sollte wurde immer am Anfang eingefügt.
Hier mal ein kleiner Beispiel Code:

Code: Alles auswählen

 
procedure TForm1.BitBtn1Click(Sender: TObject);
var
  s1,s2:string;
begin
  s1:=edit1.Text;
  s2:='nase';
  insert(s1,s2,5);
  edit2.Text:=s2;
end;   
 

nase wird nicht an der 5 Stelle eingefügt sondern am Anfang. In meinem Test Projekt ging es eigentlich darum WideStrings und ein UTF8Char in einem wideString einzufügen.
Also habe ich versucht mit utf8Insert die Aufgabe zu erledigen, aber das ging auch nicht, der hat gar nix gemacht.
Als Parameter hat er Strings verlang, was ich seltsam fand, er wollte keine WideStrings.

Also habe ich ein neues Test Projekt aufgemacht, von dem stammt auch der Code von oben.
Ich habe gestern einfach selbst eine Insert Methode geschrieben die sogar auch geht:

Code: Alles auswählen

 
function InsertPL(const asrc:widestring; const aS1:Widestring; const aIndex:Integer):widestring;
var
  str1,str2:widestring;
begin
  str1:=UTF8Copy(asrc,1, aindex);
  str2:=UTF8Copy(asrc,aindex+1, UTF8Length(asrc));
  result:=str1+aS1+str2;
end;
 

wie ihr sieht es sie recht kurzt, die von Lazarus ist wesentlich länger. Aber sie Funktioniert wenigensts so wie sie soll.

Kann mir jemand das bestätigen ? habe ich ein Fehler gemacht bei der Anwendung ?
Was meiner Insert Methode angeht, kann sie jemand von euch beurteilen und testen ? In meinem eigentlichen Test Projekt Funktioniert sie aufjedenfall *freu*

Was mir auch aufgefallen ist, ich dachte immer insert ist eine Funktion und keine Procedur... wurde das geändert ?
Zuletzt geändert von pluto am So 26. Okt 2008, 17:29, insgesamt 1-mal geändert.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

pluto hat geschrieben:Kann mir jemand das bestätigen ? habe ich ein Fehler gemacht bei der Anwendung ?


Erstens kann ich dein Problem nicht nachvollziehen.
Insert funktioniert doch bestens.

Dann ist dein InsertPl höchst seltsam. Du musst dich entscheiden, ob du mit Widestring oder Ansistring UTF-8 arbeiten willst. Du mischst da alles fröhlich durcheinander. UTF8Copy erwartet String nicht Widestring.
Falls das funzt ist es eher Zufall.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Insert geht nicht mehr...

Beitrag von pluto »

Bei mir geht insert nicht. Das beispiel von oben fügt Insert Nase nicht an Position 5 ein sondern Am Anfang.

das mit UTF8Copy könnte ich auch noch wieder ändern in Copy. Das erwartet widestring.
mach doch mal bitte ein Beispiel wie DU insert angewendet hast, damit es geht.... kann ja sein das ich irgendetwas Falsch gemacht habe.

Erstens kann ich dein Problem nicht nachvollziehen.

Was genau verstehst du an mein Problem nicht ? Das Problem ist doch ganz einfach....
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

pluto hat geschrieben: Das beispiel von oben fügt Insert Nase nicht an Position 5 ein sondern Am Anfang.


Das ist ja auch richtig.

Die Funktion bedeutet "füge s1 an Positon 5 in s2 ein"

pluto hat geschrieben:Was genau verstehst du an mein Problem nicht ? Das Problem ist doch ganz einfach....


Ich verstehe es nicht, weil's kein Problem ist.

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Insert geht nicht mehr...

Beitrag von pluto »

ich hatte auch mal zwischendurch die Parameter vertauscht. Aber es geht immer noch nicht. Naja wenn es bei dir geht muss es an mir liegen.
MFG
Michael Springwald

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Insert geht nicht mehr...

Beitrag von mschnell »

theo hat geschrieben:Die Funktion bedeutet "füge s1 an Positon 5 in s2 ein"

Wobei es ein fürchterliches Problem ist, was "Positon 5" heißt, wenn da UTF8 im Spiel ist.
Bei UTF8-Strings heißt "Positon 5" der fünfte Subcode. Und jeder Character kann aus 1, 2, 3 oder 4 Subcodes bestehen

Ist der String "12345", dann ist an Position 5 die "5", ( ss := copy(s, 5, 1); oder c := s[5]; )
Ist der String "äö345", dann ist an Position 5 die "3", ( ss := copy(s, 5, 1); oder c := s[5]; )
Ist der String "äöü45", dann ist an Position 5 das "ö"
aber nicht als char, sondern nur wenn man zwei Zeichen in einen String kopiert ( ss := copy(s, 5, 2)
( ss := copy(s, 5, 1) oder c := s[5]; ergibt gar kein sinnvolles Zeichen, sondern nur den ersten Subcode vom ü.
Ist der String "ä2ö45", dann ist an Position 5 überhaupt kein sinnvolles Zeichen, sondern der zweite Subcode vom ö.

Ein Problem ergibt sich dadurch, dass in Lazarus mit Default-Einstellungen (aber nicht bei FPC mit Default-Einstellungen) Konstanten als UFT8-String erscheinen und nicht automatisch korrekt konvertiert werden, wenn sie auf ANSIString oder WideString Variablen zugewiesen werden (bei FPC mit Default-Einstellungen sind sie Widestring-Konstanten und werden vermutlich richtig(er) konvertiert).

Der FPC-Compiler kennt den Type UTF8String gar nicht, sondern er ist nur ein Synonym für ANSIString, und kann deshalb nicht automatisch Konvertierungen einbauen.

Ein weiteres Problem ergibt sich dadurch dass bei Lazarus alle String-Parameteter der LCL UTF8Strings sind, die aus demselben Grund wiederum nicht automatisch korrekt zu und von Widestrings und ANSIStrings konvertiert werden. (Aus diesem Grund stellt Lazarus den FPC aus so ein, dass String Konstanten als UTF8Stgring erscheinen.)

Unicode mit Lazarus ist somit nur benutzbar, wenn man entweder überall UTF8 verwendet und sich darüber klar ist dass die Positionsangaben nicht Character, sondern Subcodes sind (also nie s[i], length(s), insert, delete, copy oder so in "traditioneller Manier" bemutzen !), oder wenn man mit intern mit Widestrings arbeitet und bei jeder Verbindung zur LCL von Hand die Konvertierung aufruft. Dass auch String-Konstanten konvertiert werden müssen kann man sicherlich keinem Außenstehenden als "Feature" verkaufen, er wird es als Bug ansehen :(.

-Michael

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

mschnell hat geschrieben:Wobei es ein fürchterliches Problem ist, was "Positon 5" heißt, wenn da UTF8 im Spiel ist.


Mach's nicht komplizierter als es ist, die Fkt. UTF8Insert (LCLProc) macht das wie ein normales Insert.
Genauso wie UTF8Pos, UTF8Copy,UTF8Delete, UTF8LowerCase etc.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

mschnell hat geschrieben:bei FPC mit Default-Einstellungen sind sie Widestring-Konstanten und werden vermutlich richtig(er) konvertiert.


Wie soll denn das gehen, wenn der Compiler gar kein UCS-2 lesen kann? http://www.mail-archive.com/fpc-devel@l ... 12483.html

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Insert geht nicht mehr...

Beitrag von pluto »

ich habe doch in den Test beispiel extra einfach nur String genommen als Test Variable. Nicht mal da hat es geklappt. Ich weiß immer noch nicht wo mein Fehler ist. Da ich meine das die Parameter richtig sind die ich nutzte.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

pluto hat geschrieben:ich habe doch in den Test beispiel extra einfach nur String genommen als Test Variable. Nicht mal da hat es geklappt. Ich weiß immer noch nicht wo mein Fehler ist. Da ich meine das die Parameter richtig sind die ich nutzte.


Du machst einfach einen Denkfehler. Du sagst zu nachfolgendem Code: "nase wird nicht an der 5 Stelle eingefügt sondern am Anfang."
Das ist schon richtig: "nase" wird gar nicht eingefügt sondern s1 wird in s2 ('nase') eingefügt. Soo schwierig?
Du gibst ja richtigerweise auch s2 aus.

Code: Alles auswählen

s1:=edit1.Text;
  s2:='nase';
  insert(s1,s2,5);
  edit2.Text:=s2;

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Insert geht nicht mehr...

Beitrag von pluto »

Ah, ich glaube ich habe jetzt den Fehler verstanden.... In ein neuen test Projekt ging das einfügen eben.

Komischerweise hatte ich mit Insert noch nie Probleme. Hat sich da was geändert Intern ?
MFG
Michael Springwald

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Insert geht nicht mehr...

Beitrag von mschnell »

theo hat geschrieben:Wie soll denn das gehen, wenn der Compiler gar kein UCS-2 lesen kann? http://www.mail-archive.com/fpc-devel@l ... 12483.html

Inzwischen hat sich tatsächlich bestätigt, dass Lazarus meine Test-Source-Datei nicht in UCS-2 abgespeichert hat. Ich bin da einem Fake von Ultraedit aufgesessen. (Tut mir leid, dass ich damit Verwirrung gestiftet habe.)

In der Free-Pascal-developers-Mailing-Liste wurde mir aber versichert, dass FPC String-Konstanten (zumindest wenn sie WideStrings zugewiesen werden) als WideString anlegt (also entsprechend aus der Source-Datei konvertiert, wenn diese als ANSI oder UTF-8 kodiert ist). Eine Kompiler-Option, die Lazarus benutzt (anscheinend um Probleme mit der UTF-8-basierenden LCL zu vermeiden), produziert - so wird da konstatiert - das Verhalten, dass String-Konstanten als UTF-8 angelegt (und dann nicht korrekt in Widestrings konvertiert) werden.

Ich kann am Montag die Mail 'raussuchen.

-Michael

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

mschnell hat geschrieben:In der Free-Pascal-developers-Mailing-Liste wurde mir aber versichert, dass FPC String-Konstanten (zumindest wenn sie WideStrings zugewiesen werden) als WideString anlegt (also entsprechend aus der Source-Datei konvertiert, wenn diese als ANSI oder UTF-8 kodiert ist). E


Das kann evtl. schon sein, zeigt aber nur wieder, dass unter FPC UTF-8 die Mutter von allem Unicode ist. ;-)
D.h. WideString (UCS-2, UTF-16) bedarf immer einer Konvertierung, sonst kann es der FPC gar nicht lesen.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Insert geht nicht mehr...

Beitrag von theo »

pluto hat geschrieben:Hat sich da was geändert Intern ?


Mit einiger Sicherheit nicht. Solche Grundfunktionen sind stein-alt und ändern sich nicht einfach so zum Spass.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Insert geht nicht mehr...

Beitrag von mse »

theo hat geschrieben:Das kann evtl. schon sein, zeigt aber nur wieder, dass unter FPC UTF-8 die Mutter von allem Unicode ist. ;-)
D.h. WideString (UCS-2, UTF-16) bedarf immer einer Konvertierung, sonst kann es der FPC gar nicht lesen.

Hier nochmals die Erklärung von Jonas Maebe in fpc-devel:
When you set the encoding of an FPC source file to UTF-8 (either by
adding a BOM or by using {$codepage utf-8}), then
a) all constant strings containing utf-8 characters will be decoded
and converted to utf-16 (widestring)
b) at run time, these widestrings will again be converted to the
active code page when assigning them to ansistrings or shortstrings

If a file does not contain a BOM nor a {$codepage yyy} statement, then
constant strings are not parsed in anyway and will be appear literally
in the compiled program (and when assigning them to a widestring, they
will be "converted" from ansi to utf-16 and hence contain garbage at
the end).

This means that if you (ab)use ansistrings to store utf-8 strings
(rather than strings in the current ansi-encoding), you either have to
a) not use a bom/codepage, or
b) use UTF8Encode(widestringconstant)

Otherwise characters not representable using the active code page will
disappear during the run time conversion from widestring to ansistring
(and you won't end up with an utf-8 string in any case).

Das heisst, wenn der Quellcode beispielsweise in utf-8 abgespeichert ist und dem compiler dies mittels -Fcutf8 oder BOM mitgeteilt wird, werden zur Compilezeit string Konstanten, die Codepoints > 127 enthalten, in widestring gewandelt und als widestring ins exe eingebaut. Zuweisungen an widestring variabeln zur Laufzeit verwenden diese widestring Konstanten. Bei Zuweisungen zur Laufzeit an ansistring (oder UTF8String), wird die widestring Konstante mittels des widestring Managers unter Verwendung der aktuellen Systemcodierung in 8bit Darstellung gewandelt.
Lazarus LCL erwartet und liefert alle string in utf-8. Man muss sich also entscheiden, gibt man -Fcutf8 nicht an, tastet der Compiler die string Konstanten nicht an, es findet zur Kompilezeit keine Umwandlung in widestring statt, die in utf-8 codierten Texte im Quellcode bleiben utf-8 und können unverändert an LCL übergeben werden. In diesem Fall werden zur Laufzeit an widestring Variablen zugewiesene string Konstanten von 8Bit mittels des widestring Managers und der aktuellen Systemcodierung in utf-16 gewandelt. Da Windows in der Regel nicht utf-8 als Systemcodierung verwendet, sind die widestring Texte falsch. Auch beim Aufrufen von 8Bit Betriebssystem Routinen, beispielsweise Dateifunktionen, muss man aufpassen, da diese nicht utf-8 erwarten und zurückgeben.
Oder man gibt -Fcutf8 an, dann funktioniert die widestring Konvertierung zur Kompilierzeit, die 8Bit Betriebssystem Routinen werden automatisch in der richtigen Codierung aufgerufen, aber LCL Aufrufe müssen mit UTF8Encode()/UTF8Decode() ausgestattet werden.
So, dies war nun aber das letzte mal... ;-)

Martin

Antworten