Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Vergleichen von UnicodeStrings
ud11 - Do 13.01.11 13:01
Titel: Vergleichen von UnicodeStrings
Hallo zusammen,
zum Vergleichen von zwei WideStrings benutze ich die Funktion WideCompareStr. Diese liefert mir aber interessanter weise beim Vergleichen von "Cœur" (mit Ligatur) mit "Coeur" (ohne Ligatur) eine 0, was ja so viel bedeutet wie "gleich".
Das ist so eine Sache, immerhin ist der Text mit Ligatur ja nur 4 Zeichen, der ausgeschriebene 5 Zeichen lang...
(ä und ae sind ja schließlich auch nicht gleich)
Ich bin jetzt etwas verunsichert: Was mache ich kaputt, wenn ich statt dem WideCompareStr einfach den = Operator von Delphi benutze?
Bin für alle Hinweise, Anmerkungen und Tipps dankbar!
Uli
jaenicke - Do 13.01.11 13:28
Hallo und :welcome:
Ganz wichtig ist dabei erst einmal die Delphiversion. Ab Delphi 2009 sollten die Vergleiche auch bei normalen Strings, die Unicodetext enthalten, korrekt ablaufen. Und ich denke einmal, dass auch WideStrings noch einmal ggf. überarbeitet wurden.
Vorher habe ich es nicht ausprobiert.
BenBE - Do 13.01.11 15:26
Strings normalisieren und danach binär vergleichen.
ud11 - Do 13.01.11 15:46
Hi & danke für die superschnelle Antwort!
An der Delphi-Version liegt's nicht (getestet mit D2009), denn es wird ja lediglich die Windows-API Funktion "CompareStringW" (siehe SysUtils) aufgerufen. Das macht also quasi das Betriebssystem "falsch".
Wenn ich nur wissen muss, ob zwei Unicode-Strings *wirklich* gleich sind, gibt es da eine andere API-Funktion, die man dem Delphi "=" Operator vorziehen sollte?
Ich weiss, dass Unicode von vorne bis hinten ein "Grab" ist und mag mir nicht (noch) ein Eigentor schießen, deswegen habe ich etwas "Angst" vor dem "=" Operator, obwohl der in *diesem* Fall das richtige Ergebnis (nämlich ungleich) liefert!
Viele Grüße
Uli
Moderiert von
Martok: Doppelposting entfernt.
@Benny: Was meinst du mit "normalisieren"?
Delete - Do 13.01.11 22:32
Warm ist Unicode ein Grab? Was wäe denn deiner Meinung nach kein Grab?
bummi - Do 13.01.11 23:19
@Luckie
Strings aus einem IMMER 32 breiten CHAR, ich denke dann wären die Stringroutinen wieder um Welten schneller.
Delete - Fr 14.01.11 03:16
Richtig, aber alle Textdateien wären auf einmal vier mal so groß.
Tankard - Fr 14.01.11 06:01
Luckie hat folgendes geschrieben : |
| Warm ist Unicode ein Grab? Was wäe denn deiner Meinung nach kein Grab? |
kann mir mal einer sagen was grap ist?
also ich kenne nur "crap"
gruss
tankard
Gausi - Fr 14.01.11 11:23
Tankard hat folgendes geschrieben : |
kann mir mal einer sagen was grap ist?
also ich kenne nur "crap"
|
"Grab" ist ein gängiger deutscher Begriff. Aus der Wikipedia:
| Zitat: |
| Das Grab ist die Begräbnisstätte für verstorbene Lebewesen. Es ist der Ort auf den sich der Totenkult der Kulturen bezieht. |
ud11 - Fr 14.01.11 12:58
Ihr seid doof :-)
Unicode ist deswegen ein "Grab", weil man dadurch mehr Probleme bekommen hat als gelöst wurden :-) Aber von mir aus ist es auch "crap". Aber jetzt genug damit!
Habe noch eine Windows-API namens "CompareStringOrdinal" gefunden, die in meinem Fall anscheinend gut funktioniert. Leider gibt es diese erst ab Vista. D.h. für XP habe ich immer noch das Problem, verwende dort aber jetzt einfach den nativen "=" Operator. Bis jetzt sieht es gut aus. Aber das sah es zuvor ja auch, bis jemand mit den Ligaturen ankam. Ich bin daher gespannt, ob und wie es als nächstes Knallt.
Trotzdem Danke für's Zuhören
Martok - Fr 14.01.11 13:58
Und falls jemand die einzige sinnvolle Möglichkeit Text abzulegen die wir haben nicht nur als Grab sehen will, sondern verstehen will was hier warum passiert, so sei der
OldNewThing-Artikel [
http://blogs.msdn.com/b/oldnewthing/archive/2005/06/17/430194.aspx] zu NTFS FileSortOrder und die WP zu
Collation [
http://en.wikipedia.org/wiki/Collation]s empfohlen.
Welche Collation für den Vergleich verwendet wird, legt der erste Parameter von
CompareStringW [
http://msdn.microsoft.com/en-us/library/dd317759(VS.85).aspx] fest.
D7-RTL
1: 2: 3: 4: 5:
| function WideCompareStr(const S1, S2: WideString): Integer; {$IFDEF MSWINDOWS} begin SetLastError(0); Result := CompareStringW(LOCALE_USER_DEFAULT, 0, PWideChar(S1), Length(S1), |
LOCALE_USER_DEFAULT ist also die Collation, die sich aus dem Gebietsschema ergibt. Auf einem PC mit DE_DE wird hier "Cœur" ordnungsgemäß umgeschrieben in "Coeur". Deutsch hat diese Ligatur nicht :!: . Stellt man das Gebietsschema auf FR, dann natürlich nicht mehr. Alternativ: CompareStrW mit LOCALE_INVARIANT aufrufen, wenn für den User unvorhersehbares (aber überall gleiches) Verhalten gewünscht ist.
Macht jedes DBMS übrigens genauso.
Delete - Fr 14.01.11 20:14
ud11 hat folgendes geschrieben : |
| Unicode ist deswegen ein "Grab", weil man dadurch mehr Probleme bekommen hat als gelöst wurden |
Das ist Unsinn. Man muss nur wissen, wie man mit Unicode umzugehen hat. Ein Grab waren damals die Codepages für den ASCII-Zeichensatz, anstatt es gleich richtig zu machen. Hast du einen Text mit einer nicht deutschen Codepage bekommen, waren die Sonderbuchstaben im deutschen Alphabet alle Müll. Ich weiß nicht, wie alt du bist, aber ich habe die unsäglichen Zeiten mit den Codepages unter DOS noch am eigenem Leib erfahren.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!