C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum
-
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:
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+00E4UNICODE 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
-
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:
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.
-
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).
-
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ä
, dasa
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ä
, dasa
oder das ◌̈).Oder hab ich dich nur falsch verstanden?
Eher das ich die beiden begriffe durcheinander geschmissen habe
-
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 ...
-
Wieso denn nicht so ... um das "if"-Geraffel zu vermeiden?
/** * Reads data from a file and writes the modified data to another file. * * @param filename The name of the file to read from. * * @return void * * @throws None */ void readFromAndWriteToFile(std::string filename) { std::unordered_map<char, char> replaceMap; for (auto &c : std::vector<char>{(char)228, (char)246, (char)252}) { replaceMap[c] = c - 32; } // replaceMap[228] = 228 - 32; // replaceMap[246] = 246 - 32; // replaceMap[252] = 252 - 32; std::ifstream infile(filename); std::ofstream outfile(filename + ".out"); std::string line; while (std::getline(infile, line)) { for (int i = 0; i < line.size(); i++) { if (replaceMap.find(line[i]) != replaceMap.end()) { line[i] = replaceMap[line[i]]; } } outfile << line << std::endl; } }
(Edit: Zum Teil AI-generiert ...)
-
@wpi sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:
Wieso denn nicht so ... um das "if"-Geraffel zu vermeiden?
2 Nachteile:
a) (fast irrelevant, aber aus Prinzip)map.find(x)
gefolgt vonmap[x]
ist doppelte Arbeit. Gleich das Ergebnis von find speichernauto it = map.find(x)
und beiit != end
direkt verwenden (*it
) spart 1 Lookup.
b) (wesentlich) das funktioniert nur unter der Annahme, dass alle Zeichen in 1 char passen. Was ist mit Unicode und verschiedenen Kodierungen? Bei UTF-8 müsstest du z.B. variabel viele chars ersetzen, je nach Länge des Zeichens. (um fair zu sein, das Problem hat der Ursprungscode auch)
-
Gefällt mir.
Ich lasse das mal refactoren. Codeium kann Funktionen auch vollautomatisch refactoren und mit Kommentaren versehen...
Aber erst später, denn bin gerade unterwegs und schreibe Handy.
Edith: Codeium ist free und gibt es als Erweiterung für viele IDEs... hätten wir doch damals nur diesen Luxus gehabt...
-
@wpi
Mein liebstes UTF 16 Zeichen ist Malayalam: ഊIn Hex Darstellung 0x0D0A. Es erinnert mich immer daran einzelne Zeichen immer abhängig von der aktuellen Kodierung zu interpretieren.
-
@Quiche-Lorraine sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:
Mein liebstes UTF 16 Zeichen ist Malayalam: ഊ
In Hex Darstellung 0x0D0A.Was ist ein UTF16-Zeichen? Ein Unicode-Zeichen in UTF16-Kodierung? Was ist "Hex-Darstellung" genau? Ich frage wegen BigEndian vs LittleEndian...
Eine Datei mit diesem Inhalt:
FF FE 0D 0A 0D 00 0A 00 0A 0D 0D 00 0A 00 ^^^^^ unbekant ^^^^^ dein Symbol
-
So besser? Ist man mit
char16_t
auf der sicheren Seite (Unicode)? Ich habe es nicht ausprobiert:/** * This function reads from a file specified by the filename parameter and writes to another file. * It replaces all characters 'ä', 'ö' and 'ü' with their corresponding uppercase version. * * @param filename The name of the file to read from. * * @return void * * @throws None */ void readFromAndWriteToFile(std::string filename) { std::unordered_set<char16_t> toReplace{(char16_t)'ä', (char16_t)'ö', (char16_t)'ü'}; std::ifstream infile(filename); std::ofstream outfile(filename + ".out"); std::string line; while (std::getline(infile, line)) { for (int i = 0; i < line.size(); i++) { if (toReplace.find(line[i]) != toReplace.end()) { char16_t before = line[i]; line[i] = toupper(line[i]); // describe what you did: std::cout << "replaced " << before << " with " << line[i] << " at index " << i << "\n"; } } outfile << line << std::endl; } }
Was ist eigentlich mit der Fehler-/Ausnahmebehandlung? Gerade bei Dateioperationen kann doch alles schiefgehen, was schiefgehen kann ...
-
@wpi sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:
Ist man mit char16_t auf der sicheren Seite (Unicode)?
Nein.
Unicode ist auch nicht gleich eine Kodierung von sich selbst. Und ein Unicode-Zeichen kann auch in UTF-16 aus 2 16-Bit-Werten bestehen.
-
@wob sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:
Nein.
Dann ist
@wpi sagte in C++ | If-Abfrage funktioniert nicht und ich weiß nicht warum:
{(char16_t)'ä', (char16_t)'ö', (char16_t)'ü'}
bestimmt auch Nonsense ...
-
Wenn Du auf der sicheren Seite sein willst, müsstest Du UTF-32 nutzen. Das Problem ist nur, dass man das eigentlich nur auf einem UNIX/Linux nutzt, und man da gleich wchar_t nutzen kann. Auf UNIX wurden die beiden Formate UTF-8 und UCS-4 genutzt. Da aber Windows UTF-16 nutzt, und das Format nicht der Lage ist alle Codes aus UTF-8 bzw. UCS-4 zu kodieren wurde der Zeichenbereich im RFC 3629 eingeschränkt und das UCS-4 Format in UTF-32 umbenannt.
Wenn Du Zeichenketten mit einem Code pro Zeichen willst, kannst Du unter UNIX/Linux wchar_t nutzen, unter Windows musst Du jedesmal von/zu einem uint32_t konvertieren oder Du musst Dein Code so anpassen, dass er die Kodierung UTF-16 beherrscht.