stenk2001
Anmeldungsdatum: 24. August 2013
Beiträge: Zähle...
|
Hallöchen ☺ Ich versuche Wörter aus einer Textdatei in ein bestimmtes Format zu bringen, dazu zählt das Umwandeln von Umlauten ä,ü,ö in ae,ue,oe. Ich habe die einzelnen Wörter der Textdatei in ein Array aus C++ Strings eingelesen und überprüfe nun Wort für Wort buchstabenweise ob ich etwas umwandeln muss. Mit den Umlauten komme ich allerdings nicht zurecht, weil diese keinem Standard-char entsprechen und ich daher nicht testen kann (if(mein_wort[i] == 'ä') funktioniert ebenfalls nicht). Ich habe etwas danach gegoogelt, allerdings sind es meistens Windowsuser, welche die selben Fragen haben und zudem dreht es sich immer um die Ausgabe von Umlauten, die bei mir problemlos funktioniert (string wort = "Ätsch!"; cout << wort; // Gibt ohne Fehler Ätsch aus), mich interessiert aber lediglich das Erkennen. Wie erkenne ich Umlaute in einem C++ - String? Das Programm muss nur auf meiner Kiste funktionieren, Auswartskompatibilität ist nicht gefragt ☺
Ich verwende G++ auf einer 64bit CPU. Vielen Dank im Voraus! Grüße,
stenk
|
Panke
Anmeldungsdatum: 14. Oktober 2010
Beiträge: 133
|
Das hängt davon ab, wie die Daten in deinem std::string kodiert sind. Angenommen du kodierst deine Eingaben nicht um, stellt sich somit direkt die Frage, wie deine Eingaben kodiert sind. Wahrscheinlich hast du UTF-8 oder sowas wie iso-latin-1 im std::string. Ein 'char' entspricht dann einer 'Codeunit'. Einfach entsprechend behandeln.
|
Dee
Anmeldungsdatum: 9. Februar 2006
Beiträge: 20095
Wohnort: Schwabenländle
|
Oder Du machst das komfortabler mit der Regex-Bibliothek von Boost: http://www.boost.org/doc/libs/1_48_0/libs/regex/doc/html/boost_regex/ref/regex_replace.html Dann musst Du die Zeilen nicht manuell Zeichen für Zeichen durchsuchen. Gruß Dee
|
stenk2001
(Themenstarter)
Anmeldungsdatum: 24. August 2013
Beiträge: 9
|
Danke für die Antworten. Ich würde gerne bei meinen Strings bleiben, ich möchte das ganze für mich übersichtlich halten. Ich habe mir das UTF-8 Coding angesehen, allerdings werde ich in Bezug auf mein Problem dadurch nicht schlauer. Wie erhalte ich denn die UTF-8 Darstellung eines bestimmten char nach Eingabe, sodass ich testen kann, ob eine Konvertierung nötig ist. Ich suche also etwas a la convert_to_UTF8('ä') = 11xxxxxx 10xxxxxx (die xxx entsprechend dem Zeichen). Oder bin ich völlig auf dem Holzweg? Grüße
|
Panke
Anmeldungsdatum: 14. Oktober 2010
Beiträge: 133
|
Ohne es jetzt nachgeschaut zu haben, denke ich, dass das Verhalten von nicht ASCII-Chars in char-Literalen undefinert ist. C++11 führt extra neue Literale ein. Der einfachste Weg wäre, die Kodierung von Umlauten in UTF-8 herauszusuchen und diese dann als Strings zu behandeln string oe = "\xab\xcd";
// suches und ersetzen mit oe
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6493
Wohnort: Hamburg
|
Ich bin leider nur ein C Programmierer der C++ nur in Ausnahmefällen nutzt und daher mit dessen Möglichkeiten nicht ganz vertraut ist. Bei C gibt es die Möglichkeit einige Standardfunktionen in ihrer MBC (Multibyte Character) oder auch WC (Wide Character) Version zu nutzen. Allerdings mache ich davon selten gebrauch, da mir der Aufwand oft zu hoch ist.
Ich habe mir das UTF-8 Coding angesehen, allerdings werde ich in Bezug auf mein Problem dadurch nicht schlauer. Wie erhalte ich denn die UTF-8 Darstellung eines bestimmten char nach Eingabe, sodass ich testen kann, ob eine Konvertierung nötig ist.
Ich kann die genauen Umstände der Herkunft der Zeichen jetzt nicht nachvollziehen, aber wenn es eine (Unix/Linux) Datei ist, kann man davon ausgehen, das jedes Zeichen mit gesetztem MSB zu einer UTF-8 Sequenz gehört. Mit C++ strings habe ich noch nicht wirklich gearbeitet, da ich auch hier oft noch mit char Arrays (im C Stil) arbeite. Jedenfalls passen UTF-8 Codierte Zeichen nicht in ein 8-Bit Character, ausser man verwendet einen Windows Zeichensatz. Die Unicode Codierung benötigt bei deutschen Umlauten immer 16 Bits. Geht es jetzt darum die wenigen deutschen Umlaute in eine 7-Bit ASCII Zeichensequenz umzuwandeln?
|
stenk2001
(Themenstarter)
Anmeldungsdatum: 24. August 2013
Beiträge: 9
|
Dakuan schrieb: Geht es jetzt darum die wenigen deutschen Umlaute in eine 7-Bit ASCII Zeichensequenz umzuwandeln?
Es geht nur darum zu verstehen wie ich Umlaute in einem String handhaben kann. Wenn eine Umwandlung das Problem löst, dann ist das absolut erwünscht ☺
Ich bin leider noch nicht dazu gekommen zu versuchen, was Panke mir geraten hat, ich werde mich melden sobald ich etwas mehr weiß. Ist es denn möglich (oder überhaupt sinnvoll) eine eigene Kodierung zu erstellen? Am liebsten würde ich einige ASCII-Zeichen rausschmeißen und durch meine Umlaute ersetzen. Wie gesagt, mein Programm muss nicht auswärtskompatibel sein. Beste Grüße,
Stenk
|
snafu1
Anmeldungsdatum: 5. September 2007
Beiträge: 2133
Wohnort: Gelsenkirchen
|
Wenn es nicht kompatibel zu anderen Systemen sein muss, dann könntest du vielleicht nach diesem Schema vorgehen:
1
2
3
4
5
6
7
8
9
10
11
12 | #include <iostream>
using namespace std;
int main() {
wstring wort = L"Ätsch!";
if (wort[0] == L'Ä')
cout << "Gefunden" << endl;
return 0;
}
|
Das gibt bei mir ein "Gefunden" in der Konsole aus. Ich bin allerdings kein C++-Experte und kann daher nicht abschätzen, ob man mit irgendwelchen Problemen rechnen muss.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6493
Wohnort: Hamburg
|
Ist es denn möglich (oder überhaupt sinnvoll) eine eigene Kodierung zu erstellen?
Ob es sinnvoll ist, kannst nur Du entscheiden. Also ich fasse mal zusammen, was ich bisher verstanden habe: Du hast eine UTF-8 codierte Textdatei und möchtest die üblichen deutschen Umlaute in Strings (Bigramme) umwandeln. Alle deutschen Umlaute können in UTF-8 Codierung mit 2 Bytes dargestellt werden. Leider habe ich in meiner Spickzettelsammlung nicht alle Codierungen griffbereit, aber vielleicht hilft folgende Zusammenstellung. Dabei gilt, das im zweiten Byte immer nur die unteren 6 Bits enthalten sind (die oberen 2 Bits enthalten die Codierung für Folgebyte).
ß U+00DF Ä U+00C4 Ö U+00D6 Ü U+00DC ä U+00E4 - 0xC3 0x24 → ae ö U+00F6 - 0xC3 0x36 → oe ü U+00FC - 0xC3 0x3C → ue
Das ist jetzt die Umcodierung, die ich in meinem Morsedecoder verwende (da arbeite ich nur mit Kleinbuchstaben). Die fehlenden Codierungen müsste ich erst bitmäßig zerlegen, und dafür ist es jetzt schon zu spät. Ich hoffe aber, das Du das Schema erkennst. p.s. Die Codierung für die Folgebytes muss ich nochmal überprüfen, möglicherweise enthalten meine Aufzeichnungen da einen Fehler. Es ist mir jetzt zu spät das zu überprüfen.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6493
Wohnort: Hamburg
|
Ich habe nochmal nachgesehen und festgestellt, das mein Programm fehlerhaft kommentiert ist. Die Markierung für die Folgebytes wurden vergessen (es muss immer 8 hinzuaddiert werden). Die richtige Codierung ist: ä U+00E4 - 0xC3 0xA4 → ae ö U+00F6 - 0xC3 0xB6 → oe ü U+00FC - 0xC3 0xBC → ue
Du kannst also die Bytefolge 0xc3 0xbc direkt durch die Buchstaben u und e ersetzen.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Unicode-Handling in C++ ist ***** 😉 (Einfach weil die Sprache intern keinen Datentypen für Unicode anbietet, sondern man explizit selber eine "neutrale" Codierung wählen muss, auf der man dann arbeitet. Das lösen anderen Sprachen (Python, Java, C#, ...) deutlich besser.) Ich würde Dir raten, zu boost.locale zu greifen (zur Not auch ICU - aber die API davon ist grausam!). Damit hast Du Werkzeuge zum Codieren und Decodieren, Vergleichen und Bearbeiten von beliebig codierten Strings in der Hand. Du musst Dich intern natürlich noch auf ein Encoding festlegen; ich würde da zu UTF-8 raten. Mit C++11 kannst Du dann Deine Literale auch gleich explizit dafür angeben (u8"" ) - natürlich musst Du den Code dann auch in UTF-8 speichern 😉 Für das generelle Verständnis von Unicode empfehle ich diesen Artikel. Wenn man mit externen Daten arbeitet, so *muss* man das Encoding dieser Daten wissen. Es gibt keine Möglichkeit, das Encoding zuverlässig zu raten! Zu wissen, was ein Encoding ist, was Unicode ist und wie die beiden Dinge zusammen hängen, ist imho essenziell für jeden Entwickler ☺
|
stenk2001
(Themenstarter)
Anmeldungsdatum: 24. August 2013
Beiträge: 9
|
Hi, also ich habe jetzt aller Vorschläge über vorhandene Bibliotheken zum Trozt versucht einfach Byte für Byte durchzuchecken ob eine der Bytefolgen einem Umlaut entspricht. Zu allererst wollte ich erstmal mit Dakuans Werten abgleichen, der mir ja die entsprechenden Daten für die Umlaute gegeben hat. Ich habe dazu eine kleine Routine geschrieben, die eine Adresse entgegen nimmt, und dann die Bits als String (z.B. 00100110) oder als den zugehörigen unsigned int (38 in diesem Falle) ausgibt. Wenn ich jetzt aber die Adresse eines C++ std::string übergebe, und anschließend die des Folgebytes (durch Zeigerarithmetik mit char*), dann erhalte ich für das Byte, das der Adresse des Strings folgt immer 40 (bzw. 00101000), unabhängig vom Inhalt und Länge des Strings. Das Folgebyte ergibt immer einen zufällig erscheinenden Wert zwischen (kleiner als 256). | string a = "ubuntuusers";
char* pchar = reinterpret_cast<char*>(&a);
cout << bitwise(pchar) << " " << bitwise(pchar+1); //Liefert "40 196" oder "40 244" bzw die entsprechenden Bitmuster der Bytes
|
Liege ich richtig in der Annahme, dass im String die chars nicht mit dem ersten Byte beginnen? Wie muss ich vorgehen? Darüberhinaus ist mir aufgefallen, dass integers nicht wie von mir angenommen die Binärdarstellung einer Zahl repräsentieren
(unsigned short int x = 10 ist nicht [00000000 00001010] sondern [0001010 ...], wobei ich nicht weiß ob das Folgebyte dazugehört). Wo kann man herausfinden, wie genau die Speicherverwaltung der einzelnen Datentypen funktioniert? Beste Grüße und vielen lieben Dank für eure Hilfe!
|
Panke
Anmeldungsdatum: 14. Oktober 2010
Beiträge: 133
|
Ich weiß nicht, womit du C++ lernst. Aber wirf es weg. string ist ein struct. Welches bitmuster dieses struct im Speicher hat, kannst du nicht wissen. Niemand weiß das. Außer vielleicht der Typ, der die Standardbib zu deinem Übersetzer geschrieben hat. Ziemlich sicher ist aber: Es ist nicht deine Zeichenkette. Ein Zeiger auf deine Zeichenkette sicherlich, aber deine Zeichenkette nicht. Das mit dem reinterpret_cast kannst du dir also abschminken, der ist sowieso in den meisten Fällen keine gute Idee. Versuch mal die Methode c_str. Die gibt dir einen Zeiger auf eine mit Null begrenzte Zeichenkette zurück, die dem string entpricht.
|
Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6493
Wohnort: Hamburg
|
Ich weiß nicht, womit du C++ lernst. Aber wirf es weg.
Na, wer wird denn gleich so radikal sein. Ich gebe zwar zu, das C++ auch nicht gerade mein bester Freund ist, aber man kommt nunmal nicht immer drann vorbei. Meine C++ erfahrungen sind allerdings nicht sehr dolle ind ich benutze es hauptsächlich um mit FLTK grafische Oberflächen zu erstellen, da mir dies als schmerzlosester Übergang erscheint. Da meine momentanen Anwendungen allerdings zeitkritisch sind, benutze ich auch unter C++ für Strings die herkömmlichen Character Arrays.
string ist ein struct. Welches bitmuster dieses struct im Speicher hat, kannst du nicht wissen. Niemand weiß das.
Ich habe das jetzt nicht überprüft (und ich bin auch zu faul dazu) aber das sollte sich aus den entsprechenden Header Dateien ermitteln lassen, wenn das nötig ist. Aber man kann auch in C++ die klassischen C Strings (Arrays) und dann auch die Wide-Character-I/O Fuktionen nutzen (die haben dann immer ein 'wc' oder 'mbc' im Namen). Ich mache bisher allerdings sehr wenig Gebrauch davon, da ich die wenigen damit verbundenen Probleme mit kurzen eigenen Programmzeilen schneller lösen konnte. Bei meinen Problemen geht es allerdings meist nur darum die Anzahl der Benötigten Bytes (Speicherplätze) oder die Anzahl der Zeichen (Display Ausgabe) zu ermitteln, was dann ein deutlich reduzierter Aufgabenbereich ist. @ stenk2001
Mit C++ Strings habe ich sogut wie keine Erfahrung. Aber wenn Du die Zeichen als traditionelle C Arrays implementierst, kannst du davon ausgehen, das alles was ein gesetztes Bit-7 hat (also negativ ist) eine gesonderte Behandlung benötigt. Aber da auch direkt in C++ geschriebene GUIs Unicode untestützung bieten, sollte es auch da einen direkten Weg geben, was ich allerdings noch nicht getestet habe.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Dakuan schrieb: Na, wer wird denn gleich so radikal sein. Ich gebe zwar zu, das C++ auch nicht gerade mein bester Freund ist, aber man kommt nunmal nicht immer drann vorbei.
Ist dem so? Also ich denke schon, dass man daran vorbei kommen kann 😉
Meine C++ erfahrungen sind allerdings nicht sehr dolle ind ich benutze es hauptsächlich um mit FLTK grafische Oberflächen zu erstellen, da mir dies als schmerzlosester Übergang erscheint.
Übergang? Wovon und wohin denn? Kapiere den Zusammenhang grad nicht...
Ich mache bisher allerdings sehr wenig Gebrauch davon, da ich die wenigen damit verbundenen Probleme mit kurzen eigenen Programmzeilen schneller lösen konnte.
Was sind denn die damit verbundenen Probleme? Und wie löst Du die dann selber mit kurzen eigenen Programmzeilen?
|