C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum



  • Hallo.
    In der convert_file Datei habe ich Übereinander geschriebene Wörter die auch Umlaute enthalten.
    Kann mir vielleicht jemand sagen warum die If-Abfrage (Mit Fettschrift markiert) in meinem Code nicht funktioniert ?
    In die for()-Schleife, in der die "if" enthalten ist, geht der Thread rein, das habe ich getestet. Aber die If-Abfrage erkennt keine Umlaute und ich finde den Fehler nicht. Würde mich sehr über Hilfe freuen 🙂

    	ifstream read{convert_file};
    	ofstream write{ "Output.txt" };
    	string buffer;
    
    	if (!read)
    	{
    		cout << "\n\nDATEI NICHT GEFUNDEN !\n\n\n";
    		Sleep(3000);
    		return false;
    	}
    	else
    	{
    		while (!read.eof())
    		{	
    			read >> buffer;
    			for (int i = 0; i < buffer.length(); i++)
    			{
    				**if ((int)buffer[i] == 228 || (int)buffer[i] == 246 || (int)buffer[i] == 252)
    				{
    					cout << "! ";   // Zum Testen, ob If-Bedingung "true" war
    					buffer[i] = ((int)buffer[i] - 32);
    				}**
    			}
    			transform(buffer.begin(), buffer.end(), buffer.begin(), ::toupper);
    			write << buffer << "\n";
    		}		
    		return true;
    	}
    	read.close();
    	write.close();
    
    


  • Warum gibst du nicht einfach mal alle Codes des buffers aus?

    Code wie if ((int)buffer[i] == 228) ... ist ziemlich unlesbar. Warum gerade 228?

    In welchem Encoding liegt denn deine Datei vor? Bist du sicher, dass es Windows-1252 ist (da ist 228 ein ä)? Oder liest du ggf. utf8? Enthält dein std::string eigentlich unsigned chars?



  • Danke für die Antwort ...

    Nein, es sind nur Wörter in der Datei vorhanden. Wörter die auch Umlaute enthalten. Ja, ich bin sicher das Windows 1252 Codepage aktiv ist. Hab ich in der main() mit system("chcp 1252") angewiesen.
    Ist genau richtig mit 228 = 'ä' , denn das Programm soll klein geschriebene Umlaute in Großbuchstaben umwandeln, da es mit der transform() nicht funktioniert. Wandelt alles in Großbuchstaben um, nur Umlaute halt nicht.

    Grüße



  • @Mullins182 sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    Ja, ich bin sicher das Windows 1252 Codepage aktiv ist.

    Das war nicht meine Frage. Meine Frage war, in welcher Kodierung die Datei gespeichert ist.

    Wie gesagt, mit einem Debugger oder einem std::cout << buffer[i] << " - code: " << ((int)(buffer[i])) << '\n'; sollte sich das Problem doch schnell rausfinden lassen.

    Würde dennoch davon abraten, 228 direkt so ins Programm zu schreiben.



  • @Mullins182 sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    (int)buffer[i] == 228
    

    Das wird so nix werden. char ist üblicherweise signed. D.h. als char ist der Wert für CP 1252 ä nicht 228 sondern -28.



  • @wob

    Ach so. Hatte ich missverstanden. Die Datei mit der Wortliste die in Großbuchstaben umgewandelt werden soll ist mit UTF-8 kodiert, hab ich gerade gesehen. Ich hoffe man kann irgendwie mit 'ofstream' die Kodierung angeben in welcher die Datei erstellt wird .... Hab noch nicht so viel Erfahrung bisher.

    Hier ist ein Wort aus der Datei welches 'ä' enthält und mit Deinem Code aus 'buffer' ausgelesen wurde :

    G - code: 71
    a - code: 97
    l - code: 108
    g - code: 103
    e - code: 101
    n - code: 110
    m - code: 109
    Ã - code: -61
    ¤ - code: -92
    n - code: 110
    n - code: 110
    c - code: 99
    h - code: 104
    e - code: 101
    n - code: 110
    


  • Hallo,
    da hast du dir als C++ Anfänger gleich eines der schwierigsten Themen ausgesucht (nämlich das Encoding).
    Für Linux würde man "all is UTF-8" verwenden, unter WIndows ist das (sehr viel) komplexer: Unicode part 2: UTF-8 stream mode (ich hoffe, du kannst ein wenig englisch?).
    Mit char und std::string funktioniert es nicht, da damit nur (erweitertes) ASCII möglich ist, so daß für Unicode die 'wide'-Datentypen und Funktionen benötigt werden.
    Einfacher wäre es daher für dich, wenn du die Datei als "ANSI" (d.h. erweitertes ASCII) speicherst, so daß du deinen Code dann so lassen kannst.

    PS: Ist es so gewollt von dir, daß du die Formatierung der Datei änderst, nämlich mit read >> buffer nur Wörter (ohne Leerzeichen) einliest und diese dann jeweils zeilenweise wieder zurückschreibst?
    Besser wäre sonst einfach zeichenweise einzulesen.



  • @Th69

    Hallo zurück.
    Ja, das ist so gewollt. Ich habe ein Galgenraten Spiel geschrieben und das Programm braucht eine Wortliste aus Großbuchstaben welche alle untereinander geschrieben sind. Ja, ich kann auch englisch ^^
    Die Wörter in der Quelldatei sind auch untereinander geschrieben.
    Das Programm aus dem der Code ist welchen ich gepostet habe, wandelt alle Wörter der Quelldatei in Großbuchstaben um, nur Umlaute halt nicht. Kennst Du vielleicht eine einfache Methode um Umlaute von Wörtern aus einer Datei (UTF-8 codiert) in Großbuchstaben umzuwandeln und diese dann in die Zieldatei zu schreiben ?



  • Was erhoffst du dir wenn du "ofstream" sagst welche kodierung vewendet werden soll?
    ofstream verwendet char als datentyp für ein einzelnes "Zeichen" wobei das nur für single byte kodierungen wie ASCII/ANSI gilt. AFAIK macht ofstream hier keine Konvertierung.

    UTF-8 ist eine Kodierung wo ein Zeichen aus bis zu 4 bytes bestehen kann.

    Da ist es besser, wenn deine Einleselogik mit UTF-8 klar kommt statt die Kodierung der Ausgabe zu verändern.



  • @firefly

    Richtig ... war auch ein Irrtum meinerseits. Natürlich soll ifstream mit UTF-8 klar kommen.



  • @Mullins182 sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    @Th69

    Hallo zurück.
    Ja, das ist so gewollt. Ich habe ein Galgenraten Spiel geschrieben und das Programm braucht eine Wortliste aus Großbuchstaben welche alle untereinander geschrieben sind. Ja, ich kann auch englisch ^^
    Die Wörter in der Quelldatei sind auch untereinander geschrieben.
    Das Programm aus dem der Code ist welchen ich gepostet habe, wandelt alle Wörter der Quelldatei in Großbuchstaben um, nur Umlaute halt nicht. Kennst Du vielleicht eine einfache Methode um Umlaute von Wörtern aus einer Datei (UTF-8 codiert) in Großbuchstaben umzuwandeln und diese dann in die Zieldatei zu schreiben ?

    Eine "standard" C library für unicode ist ICU (https://unicode-org.github.io/icu-docs/#/icu4c/)
    Für einen "C++ " Wrapper kannst du Boost.Locale verwenden.

    Du hast nicht nur ein Problem mit dem "mache alle Buchstaben zu Großbuchstaben" auch in deinem eigentlichen Spiel wirst du auch Probleme mit nonascii zeichen haben (wie die Umlaute).
    Denn, wie schon gesagt, gilt bei UTF8 nicht mehr das ein byte (codepoint) = ein Zeichen ist.
    Denn scheinbar gehst du davon aus das "ein byte (codepoint)" = "ein Zeichen" ist.

    Selbst für UTF-16, was windows für seine Unicode API (wide char) nutzt, gilt das nicht, wenn man alle UNICODE zeichen mit in die Betrachtung einbezieht.
    Erst mit UTF-32 kann man aktuell sagen, dass ein codepoint = ein Zeichen gilt.
    Wobei das auch nur die halbe Wahrheit ist.
    In Unicode gibt es auch die Möglichkeit ein Zeichen aus mehreren unicode Zeichen zusammen zu setzen (https://unicode.org/faq/char_combmark.html)

    Ein Beispiel. Der Buchstabe "ä" kann einmal als "ä" (UNICODE: U+00E4) dargestellt werden oder als "a" + "<zwei punkte oberhalb>" (UNICODE: a (U+0061) - ◌̈ (U+0308))
    https://www.compart.com/en/unicode/U+00E4

    UNICODE ist ein komplexes thema um das ganze korrekt selbst umzusetzen.

    Die Frage ist für welche Sprachen möchtest du in deinem Spiel unterstützen?
    Wenn das jetzt nur deutsch und englisch ist, dann könnte man auch überlegen dass intern UTF-16 genutzt wird, da für diese beiden Sprachen das ein UTF-16 codepoint = ein Zeichen gilt.

    Und eine Konvertierung zwischen den verschiedenen UTF kodierungen ist sehr einfach. Und AFAIK seit C++11(?) gibt es in der c++ standard library funktionen für diese Konvertierung.

    In den meisten Text-Editoren werden die Deutschen Umlaute auch nicht in ihrer "Decomposition" form gespeichert (wenn man den text z.b. als UTF-8 speichert, wodurch man diesen spezialfall hier auch ignorieren kann.

    Oder du verzichtest komplett auf umlaute und bleibst im ASCII bereich.
    Ein 'ä' würde dann als 'a''e' Dargestellt werden



  • @firefly

    Okay, danke für die Info`s ... Ich glaube ich werde lieber auf Umlaute verzichten in dem Programm 😵



  • @Mullins182 sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    @firefly

    Okay, danke für die Info`s ... Ich glaube ich werde lieber auf Umlaute verzichten in dem Programm 😵

    Wenn es dir darum geht c++ zu lernen ist das eine gute alternative diese Problematik erst mal zu vermeiden.
    Wenn es dir aber eher darum geht das Spiel umzusetzen und die verwendete Programmiersprache eher nebensächlich ist, dann wäre die Nutzung einer Sprache besser geeignet, welche für String schon einfacher nutzbaren Support für UNICODE hat.
    z.b. C#/Java oder Python.
    C# z.b. nutzt intern UTF-16 für Strings.



  • @firefly

    Auch gut zu wissen, dass C# UTF-16 nutzt ... Ich mache eine Umschulung in einer Computerschule und wir haben gerade die Grundlagen von C++ gelernt. Mit C# fangen wir demnächst an ... ich warte dann wohl noch bis ich das Spiel in C# programmieren kann bevor ich Wortlisten mit Umlauten nutze. Aber das Spiel ist schon fertig. Die Wortliste enthält aber im Moment nur 50 Wörter und die stocke ich dann jetzt mit umlautlosen Wörtern auf, bis ich das Programm mit C# neu geschrieben habe.

    Vielen Dank für die Hilfe und ein schönes Wochenende weiterhin ^^



  • Ich wiederhole mich einfach mal:
    @Th69 sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    Einfacher wäre es daher für dich, wenn du die Datei als "ANSI" (d.h. erweitertes ASCII) speicherst, so daß du deinen Code dann so lassen kannst.

    Einfach die Datei mit Notepad laden und dann mit "Speichern unter..." als Codierung "ANSI" wählen (d.h. das entspricht dann der Code Page Windows-1252).



  • @Th69

    Okay, vielen Dank ... Das werde ich ausprobieren ...



  • Sobald du mit C# anfängst, kannst du dann ja mal ein bißchen mit der Encoding-Klasse herumspielen.



  • @firefly sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    Denn, wie schon gesagt, gilt bei UTF8 nicht mehr das ein byte (codepoint) = ein Zeichen ist.
    Denn scheinbar gehst du davon aus das "ein byte (codepoint)" = "ein Zeichen" ist.

    Selbst für UTF-16, was windows für seine Unicode API (wide char) nutzt, gilt das nicht, wenn man alle UNICODE zeichen mit in die Betrachtung einbezieht.
    Erst mit UTF-32 kann man aktuell sagen, dass ein codepoint = ein Zeichen gilt.

    Darf ich ein bisschen korinthenkacken? Das Byte oder den char16_/char32_t nennt man Code Unit. Eines oder mehrere davon kodieren einen Code Point im Unicode (z.B. das ä, das a oder das ◌̈).

    Oder hab ich dich nur falsch verstanden? 😉



  • @Finnegan sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    @firefly sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:

    Denn, wie schon gesagt, gilt bei UTF8 nicht mehr das ein byte (codepoint) = ein Zeichen ist.
    Denn scheinbar gehst du davon aus das "ein byte (codepoint)" = "ein Zeichen" ist.

    Selbst für UTF-16, was windows für seine Unicode API (wide char) nutzt, gilt das nicht, wenn man alle UNICODE zeichen mit in die Betrachtung einbezieht.
    Erst mit UTF-32 kann man aktuell sagen, dass ein codepoint = ein Zeichen gilt.

    Darf ich ein bisschen korinthenkacken? Das Byte oder den char16_/char32_t nennt man Code Unit. Eines oder mehrere davon kodieren einen Code Point im Unicode (z.B. das ä, das a oder das ◌̈).

    Oder hab ich dich nur falsch verstanden? 😉

    Eher das ich die beiden begriffe durcheinander geschmissen habe



  • @Th69

    Werd ich machen 😁

    Vielen Dank für den Tipp die Source-Datei in ANSI umzuwandeln. Nun musste ich nur noch die Bedingung der If-Abfrage anpassen und habe jetzt großgeschriebene Umlaute in meiner Wortliste .... 🤩

    Schönen Feiertag morgen ...


Anmelden zum Antworten