Probleme mit Umlauten



  • Hallo, Ich habe Probleme mit den Umlauten. Ich kann sie nicht ausgeben, Ich möchte, dass z.B bei einem String Übung, ich durch String loope und gucke ob der entsprechende Buchstabe ein Umlaut ist. Aber bei mir nicht nur, dass das nicht geht, sondern kann ich sie überhaupt nicht ausgeben.

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("input.txt", "r", stdin);
    	freopen("output.txt", "w", stdout);
    #endif
    	ios_base::sync_with_stdio(false); 
    
    	const unsigned char AE = static_cast<unsigned char>(142);
    	const unsigned char ae = static_cast<unsigned char>(132);
    	const unsigned char OE = static_cast<unsigned char>(153);
    	const unsigned char oe = static_cast<unsigned char>(148);
    	const unsigned char UE = static_cast<unsigned char>(154);
    	const unsigned char ue = static_cast<unsigned char>(129);
    
    	string s = "Übung";
    	if (s[0] == UE){
    		cout << "LALA";
    	}
    
    	cout << AE << " " << OE << " " << UE << " " << ae << " " << oe << " " << ue;
    
    	
    }
    

    Das ist mein output: ? ? ? ? ?
    Wieso kann mein Programm die Umlaute überhaupt nicht erkennen?



  • @germanveryhard sagte in Probleme mit Umlauten:

    #include <bits/stdc++.h>

    Das ist ein interner Header der libstdc++. Du bist auf Linux unterwegs?

    Warum nimmst du an, dass 142 ein Ä ist?



  • @manni66 Ich habe das so im Internet gelesen... Ich weiss nicht sonst, was ich nach #include schreiben soll... Ich bin nit auf Linux.



  • @germanveryhard sagte in Probleme mit Umlauten:

    Ich weiss nicht sonst, was ich nach #include schreiben soll...

    Das ist doof, wenn man in C++ programmieren möchte.



  • @germanveryhard sagte in Probleme mit Umlauten:

    @manni66 Ich habe das so im Internet gelesen...

    Du machst Annahmen über die Zeichenkodierung, die nicht überall verfüllt sind Stichworte: EBCDIC, ASCII, ISO-Latin-1, UTF-8.



  • @john-0 Interessant, was soll ich jetzt machen, damit das funkioniert, mir ist nicht ganz klar...



  • @germanveryhard Da dein System (Betriebssystem/Compiler) ein großes Geheimnis ist, ist genaue Hilfe schwierig.

    Auf Windows hat die Konsole (dat schwarze Fenster) eine andere Zeichenkodierung als der Rest vom System.

    Man kann den Compiler die Übersetzung der Zeichen machen lassen. Irgendwo gibt es dafür Einstellungen.

    Die einfachste Lösung ist aber: Verzichte auf Umlaute für die Lernprogramme.



  • @DirkB Mein Betriebssystem ist Windows und mein Compiler ist gcc 8.2.0.



  • @germanveryhard
    Dann änder die ersten Zeilen mal so ab:

    #include <iostream>
    using namespace std;
    
    int main(){
    	const unsigned char AE = static_cast<unsigned char>(142);
    // ... Rest wie gehabt
    


  • @Belli Das hat nichts geaendert... Immer noch nur Fragezeichen...



  • Das Thema Encoding, Unicode, UTF usw. ist schon etwas verwirrend manchmal... ich verstehe das bis heute nicht 100%, weil es mir einfach zu blöd ist 😃

    Das Problem grundsätzlich bei

    if (s[0] == 'Ü')
    

    ist, dass Du davon ausgehst, dass 'Ü' als ein einziges Byte im String repräsentiert wird. Das muss aber nicht zwingend für jedes Zeichen der Fall sein, irgendwelche wilden Zeichen könnten z. B. in Wirklichkeit zwei Bytes im std::string belegen. Beispiel UTF-8 Kodierung, schau mal das Beispiel an:

    string s = u8"Übung";
    std::cout << "Length: " << s.size() << '\n';
    

    Man würde hier meinen, dass Länge von s == 5 ist, aber das ist es hier eben nicht, weil manche Zeichen (einzelne Unicode Code-points) mit mehr als nur einem Byte kodiert sein können. Bei ASCII ist zwar UTF-8 "backwards compatible", d.h., es ist garantiert, dass jedes ASCII Zeichen nur ein einziges Byte in UTF-8 benötigt. Bei Ü ist dies aber eben nicht garantiert. Deshalb ist es auch schwierig, nur anhand von s[0] ein Zeichen im String zu Vergleichen.

    Das würde also z. B. funktionieren:

    string s = u8"Übung";
    if (s.find(u8"Ü") == 0) {
    	cout << "LALA";
    }
    

    Oder

    	string s = "Übung";
    	if (s[0] == '\u00DC') {
    		cout << "LALA";
    	}
    

    Wobei ich hier keine Ahnung habe, welche Kodierung "Übung" hat und warum genau das funktioniert.
    Ich empfehle auf Englisch umzusteigen, und bei ASCII zu bleiben...

    Evtl. nützliche Links:



  • @germanveryhard
    gibst Du das denn auch in der Konsole aus? Also nicht in der IDE auf Run klicken, oder den Debugger ausführen, sondern eine Konsole öffnen, ins Programmverzeichnis wechseln, und dort dann die *.exe starten!

    Wie DirkB oben schon schrieb: die Konsole hat eine andere Zeichencodierung als der Rest vom Windows-System!



  • @HarteWare sagte in Probleme mit Umlauten:

    Das Problem grundsätzlich bei

    if (s[0] == 'Ü')
    

    Das hat er ja gar nicht gemacht, ich wette, DAS würde funktionieren! Er vergleicht aber s[0] nicht mit dem 'Ü', das seine IDE zur Verfügung stellt, sondern mit dem 'Ü', wie es die Konsole codiert.



  • @HarteWare Ok die erste Methode funkioniert, aber die erste nicht, aber egal, danke! Ich würde auf Englisch umsteigen, aber die Aufgabe, die ich lösen muss, ist einfach so, dass ich das brauche...



  • This post is deleted!


  • @Belli Oh stimmt, jetzt funktioniert das bei mir auch... Habe ich wohl davor irgendwas falsch gemacht.
    Naja wie gesagt, ich habe das Thema selbst nicht 100% durchschaut, daher sind meine Aussagen alle mit äußerster Vorsicht zu genießen...



  • @germanveryhard sagte in Probleme mit Umlauten:

    ig

    Wie kommst du eigentlich auf die Zahlen 142, 132, 153,...?

    #include <iostream>
    
    using namespace std;
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("input.txt", "r", stdin);
    	freopen("output.txt", "w", stdout);
    #endif
    	ios_base::sync_with_stdio(false);
    
    	const unsigned char AE = static_cast<unsigned char>(142);	// Wie kommst du auf diese Zahlen?
    	const unsigned char ae = static_cast<unsigned char>(132);
    	const unsigned char OE = static_cast<unsigned char>(153);
    	const unsigned char oe = static_cast<unsigned char>(148);
    	const unsigned char UE = static_cast<unsigned char>(154);
    	const unsigned char ue = static_cast<unsigned char>(129);
    	string s = "Übung";
    
    	if (s[0] == UE){
    		cout << "LALA";
    	}
    	cout << "Tüpfelhyäneöhrchenstraße\n";
    	printf("Coding of Ü: %i\n", static_cast<unsigned char>('Ü'));	
    	cout << "Coding of UE: " << static_cast<int>(UE) << "\n";
    	printf("Coding of s[0]: %i\n", s[0]);
    	printf("Coding of Ü (signed): %i\n", static_cast<char>('Ü'));
    
    	cout << AE << " " << OE << " " << UE << " " << ae << " " << oe << " " << ue;
    	return 0;
    }
    

    Wenn ich das Programm ausführe, so erhalte ich folgende Ausgabe:

    Tüpfelhyäneöhrchenstraße
    Coding of Ü: 220
    Coding of UE: 154
    Coding of s[0]: -36
    Coding of Ü (signed): -36
    Ž ™ š „ ” 
    

    Du codierst den Buchstaben Ü mit der Zahl 154, der Compiler möchte hier aber eine 220 sehen. DIes entspricht der Codierung mittels Codepage 1252. Dort ist das Zeichen hexdezimal mit 0xDC codiert. Wandele ich diese Zahl in dezimal um, so erhalte ich 220. Da bei mir char als signed interpretiert wird, läuft bei mir die Zahl 220 über, d.h. ich muss 256 = (2**8) abziehen: 220 - 256 = -36, uns siehe da, diese Zahl entspricht s[0].

    So sollte es funktionieren:

    #include <iostream>
    
    using namespace std;
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("input.txt", "r", stdin);
    	freopen("output.txt", "w", stdout);
    #endif
    	ios_base::sync_with_stdio(false);
    
    	const char AE = 'Ä';
    	const char ae = 'ä';
    	const char OE = 'Ö';
    	const char oe = 'ö';
    	const char UE = 'Ü';
    	const char ue = 'ü';
    	string s = "Übung";
    
    	if (s[0] == UE){
    		cout << "LALA";
    	}
    	/*cout << "Tüpfelhyäneöhrchenstraße\n";
    	printf("Coding of Ü: %i\n", static_cast<unsigned char>('Ü'));	
    	cout << "Coding of UE: " << static_cast<int>(UE) << "\n";
    	printf("Coding of s[0]: %i\n", s[0]);
    	printf("Coding of Ü (signed): %i\n", static_cast<char>('Ü'));*/
    
    	cout << AE << " " << OE << " " << UE << " " << ae << " " << oe << " " << ue;
    	return 0;
    }
    


  • In CP850 ist Ä als 142 dezimal kodiert.
    Und afaik ist/war CP850 lange zeit die default codepage für die windows cmd.exe console



  • Sorry @Quiche-Lorraine, aber du hast Codepages nicht verstanden.
    Es geht bei dem Programm von @germanveryhard ja um die Konsolenausgabe, nicht darum, welches Encoding beim Kompilieren verwendet wird (was ja von dem Encoding der ".cpp"-Quelldatei abhängig ist, zumindestens wenn man kein spezielles Encoding, so wie in dem Beispiel von @HarteWare, angibt).

    @germanveryhard: Gib mal mit chcp die aktuelle Codepage auf deiner Konsole aus. Standardmäßig sollte es unter Windows 10 immer noch, wie @firefly schon geschrieben hat, 850 (also "„Multilingual (DOS-Latin-1)“, westeuropäische Sprachen") sein, s.a. Codepages - und dann sollte es so mit deinem Code funktionieren. Oder benutzt du eine IDE und startest daraus dann eine Konsole (dann kann es schon sein, daß diese ein anderes Encoding eingestellt hat)?

    Du kannst aber auch über C++ das Encoding einstellen mit std::locale. Standardmäßig ist "C" (englisch ASCII) eingestellt, aber mittels std::locale::global(std::locale("")); kannst du auf das Encoding deiner Betriebssystem-Umgebung umstellen (dies sollte dann hier in Westeuropa 1252 "Westeuropäische Sprachen" sein), so daß du dann auf die DOS-Umlaute verzichten kannst.

    Einen detaillierten Beitrag dazu gibt es auch unter facet ändern.



  • @Th69 sagte in Probleme mit Umlauten:

    Es geht bei dem Programm von @germanveryhard ja um die Konsolenausgabe, nicht darum, welches Encoding beim Kompilieren verwendet wird

    Jaein, es geht mir auch um die folgende Stelle.

            const unsigned char UE = static_cast<unsigned char>(154);
            const unsigned char ue = static_cast<unsigned char>(129);
            
            string s = "Übung"; 
            if (s[0] == UE){
            	cout << "LALA";
            }
    

    Eigentlich müsste in der Ausgabedatei output.txt ?????????? oder ähnliches stehen und nicht ??????. Tut es aber nicht, da der Vergleich schon fehlschlägt. Warum?


Log in to reply