Post by Andy StaatsDie auf die Datenbank zugreifende Funktion
(via ibpp) übergibt allerdings nur Strings zurück
Im ersten Schritt sollte man sich darüber klar werden,
was in der Datenbank gespeichert wird bzw. gespeichert
werden soll. Wenn der Datentyp sowas wie 'char*' bzw.
'std::string' ist, dann handelt es sich bei der Verwendung
von Unicode sicher nicht um Sequenzen von Zeichen, sondern
um Sequenzen von Bytes. Der wesentliche Unterschied ist,
dass die Bytes ein Encoding einer Sequenz von Zeichen
darstellen, aber selbst nicht direkt Zeichen sind. Um
zwischen Byte- und Zeichensequenzen zu konvertieren, muß
man diese halt decodieren bzw. encodieren, je nachdem, in
welche Richtung die Zeichen bewegt werden.
Post by Andy StaatsDas will ich nun ins Unicode-Format (das sind eigentlich chinesische
Zeichen) konvertieren und dann ausgeben.
Ich bin kein Unicode-Experte, aber "Unicode-Format"
erscheint mir ein falscher Begriff zu sein: Unicode
spezifiziert primär die Interpretation von Werten als
Zeichen und ist eigentlich selbst auch ein Encoding, halt
eins für 20 Bit Einheiten. Daneben definiert Unicode noch
ein paar spezifische Encodings für Unicode-Zeichen, etwa
UTF-8, UTF-16 und UCS4 (letzter ist eine geeignete interne
Darstellung von Unicode-Zeichen, obwohl often UCS2 verwendet
wird, was aber natürlich nicht alle Unicode-Zeichen darstellen
kann).
Wenn man Sequenzen von Zeichen in einer Datenbank ablegen
will, diese aber keine Unicode-Zeichen versteht und selbst
passend codiert, dann muß man halt die Codierung/Decodierung
selbst machen, etwa indem man die Unicode-Zeichen mittels
UTF-8 codiert und das Resultat als Byte-Folge ablegt.
Post by Andy StaatsTCHAR test[30];
for(int i = 0; i < strlen(fn.c_str()); i++)
{
test[i] = (TCHAR) fn.c_str()[i];
}
Für diesen Code sollte man Programmierer fristlos entlassen
können! Sowas darf man nicht mal als kleines Demo schreiben!
Insbesondere im Kontext von Encodings kann es schon mal
vorkommen, dass ein Byte den Wert Null hat, was aber noch
lange nicht signalisiert, dass der String dort zu Ende ist.
Sicher, bei Verwendung von UTF-8 wird das Null-Byte nicht
explizit verwendet, aber bei anderen Encodings, etwa UTF-16,
sehr wohl. Wenn man von diesem semantischen Problem absieht,
bleibt natürlich noch das Performance-Problem, dass man sich
mit der wiederholten Verwendung von 'strlen()' sichert: Was
spricht gegen die Verwendung von 'fn.size()'?
Damit kommen wir natürlich direkt zu dem nächsten semantischen
Problem, nämlich der Einladung für einen Buffer-Overflow: es
ist nur Platz für 30 Zeichen. Das heißt, der Ausdruck für den
Schleifenabbruch muß auch berücksichtigen, dass nur Platz für
maximal 30 Zeichen ist:
for (std::string::size_type i = 0, end = std::min(30, fn.size());
i < end; ++i)
... und der Ausdruck 'fn.c_str()[i]' mag ja nett gemeint sein,
aber ist ggf. auch deutlich ineffizienter als 'fn[i]', hat aber
trotzdem semantisch das gleich Ergebnis.
Post by Andy StaatsDas funktioniert auch schon partiell ganz gut,
Falsch! Das funktioniert garnicht bzw. dort wo es zu funktionieren
scheint nur aus Zufall. Wenn die Bytes etwa UTF-8 enthalten, dann
werden alle ASCII-Zeichen richtig dargstellt, der Rest allerdings
nicht. Was notwendig ist, ist das externe Encoding (vermutlich
UTF-8) in ein internes Encoding ("Unicode", was auf Windows
typischerweise UCS2 bzw., wenn man es richtig machen wollte
und/oder könnte, UTF-16 bedeutet) zu wandeln. Dazu kann man z.B.
die 'std::codecvt<...>'-Facets verwenden, wobei die nicht so
richtig leicht zu verwenden sind.
Post by Andy Staatsaber es werden eben
nicht alle Zeichen richtig konvertiert, wohl weil meines Wissens nach
einige chinesische Zeichen mit nur 1 Byte kodiert sind (und die kann
ich supergut umwandeln), aber einige andere Zeichen mit bis zu 3 Byte
kodiert sind (und diese werden nun zerhackt).
Wenn das externe Encoding UTF-8 ist, dann kann ein Zeichen mit
bis zu 6 Bytes dargestellt werden. Dabei enthält das erste
Byte eine Art Zähler, aus wievielen Bytes ein Zeichen besteht
und ggf. die ersten Bits. Etwa so (dargestellt ist der relevant
Anfang des Bytes; Datenbits als Punkte):
- 0....... => ein Byte: ASCII Zeichen
- 10...... => Continuation Byte: nie erstes Byte, 6 Datenbits
- 110..... => ein weiteres Byte, plus 5 Daten Bits
- 1110.... => zwei weitere Bytes, plus 4 Daten Bits
- 11110... => drei weitere Bytes, plus 3 Daten Bits
- ...
Post by Andy StaatsHat also jemand eine Idee, wie ich den String in ein Unicode-Char
(TCHAR?) umwandeln kann, damit ich wieder schöne chinesische Zeichen
habe? :(
BTW, was ist "TCHAR"? Ich habe im C++ Standard geguckt und
nichts passendes gefunden... Zumindest im Kontext dieser
Newsgroup meintest Du vermutlich 'wchar_t', welches allerdings
auf einigen Plattformen (etwa Windows) nicht mit einer
sinnvollen Größe dargestellt wird: auf Windows hat 'wchar_t'
nur 16 Bit, Unicode-Zeichen allerdings 20 Bit, was dazu führt,
dass die meisten Programme davon ausgehen, dass UCS2 eine
geeignete Darstellung bei der Verarbeitung von Unicode-Zeichen
ist.
--
<mailto:***@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de