Zerteilen von Strings mit zB Umlauten und weiteres



  • Hallo,

    Ich schreibe ein Programm, das Konsolen-Kolonnen-Ausgaben in eine GUI-Tabelle umwandelt. Dabei kann man den Delimiter als reguläre Expression angeben. Ich mache das alles mit Qt. Und zum Zerteilen benutze ich boost::sregex_token_iterator. Alles funktioniert, nur mache ich mir Gedanken um die Zeichenkodierung. Da weiß ich herzlich wenig von. Um beispielsweise Umlaute zu unterstützen, zerteile ich die einzelnen Worte erst mit rohen std::string's und danach mache ich QString::fromLocal8Bit(). Nur bin ich mir unsicher ob das bei allen Zeichen immer funktionieren wird? Man stelle sich ein Wide Character vor, wo beispielsweise innerhalb diesem ein \0 vorkommen wird? Oder ein Space-Zeichen? Können solche Zeichen-Konstrukte das Programm nicht kaputt machen?

    Liebe Grüße.



  • std::wsregex_token_iterator benutzen wäre eine Idee.



  • @Luks-Nuke sagte in Zerteilen von Strings mit zB Umlauten und weiteres:

    Man stelle sich ein Wide Character vor, wo beispielsweise innerhalb diesem ein \0 vorkommen wird? Oder ein Space-Zeichen? Können solche Zeichen-Konstrukte das Programm nicht kaputt machen?

    Bei der UTF-8 Kodierung ist da nicht möglich, dass wenn für die Kodierung eines Zeichen mehr als ein byte benötigt wird (z.b. die deutschen umlaute). Dann hat keines dieser bytes einen wert, welche dem '\0' (dezimal 0) entspricht.
    Und auch sonst enthält keines dieser bytes einen Wert der dem "Space-Zeichen" entspricht. (Ausgenommen es handelt sich wirklich um das "Space-Zeichen". Aber dann ist das Zeichen in UTF-8 in einem byte kodiert.)

    Nur wenn die Zeichen in UTF-16/UTF-32 kodiert wären dann könnte das von dir beschriebene Problem entstehen. Nur sollte man solche Codierungen nicht in ein std::string speichern.
    Falls das notwendig sein sollte, dann sollte man den text von UTF-16/32 nach UTF-8 konvertieren bevor man da in einen std::string abspeichert.
    Und dann für die Konvertierung in einen QString nimmt man dann QString::fromUtf8()

    Wenn du eh Qt verwendest wieso nimmst du dann nicht QString + QRegex für den split

    https://stackoverflow.com/questions/8582138/how-can-i-split-a-string-according-to-delimiters-in-qt

    Falls du statt Qt5 Qt6 verwendest gibt es auch das hier:
    https://doc-snapshots.qt.io/qt6-dev/qstringtokenizer.html



  • Danke für die Erklärung.

    Ich lese zeilenweise von der Standardeingabe und forme dabei eine Tabelle.

    Darum komme ich glaub ich nicht um std::string herum.



  • @Luks-Nuke sagte in Zerteilen von Strings mit zB Umlauten und weiteres:

    Danke für die Erklärung.

    Ich lese zeilenweise von der Standardeingabe und forme dabei eine Tabelle.

    Darum komme ich glaub ich nicht um std::string herum.

    Da du von stdin/std::cin einliest dann ist der string je nach os/locale entweder in utf-8 oder in einer ansi codepage. (z.b. unter Linux ist es meistens utf-8)

    Und da hast du das problem mit einem widechar überhaupt nicht. Denn in einem byte stream von stdin/std::cin wird es keine widechars geben.
    Und ansonsten kannst du einen std::string auch in einen QString vorher konvertieren (via QString::fromLocal8Bit)



  • @firefly, Ok dann bin ich ja richtig.

    Momentan zerlege ich den String mit boost::sregex_token_iterator und transformiere jedes Teil mit QString::toLocal8Bit() in eine Zeile (QStringList).

    Der Code hierzu sieht wie folgt aus:

    QStringList tokenize(const std::string& s, const boost::regex& pattern){
        boost::sregex_token_iterator it(s.begin(), s.end(), pattern, -1), end_it;
        QStringList results;
    
        results.reserve(static_cast<int>(std::distance(it, end_it)));
    
        std::transform(it, end_it, std::back_inserter(results), [](const std::string& match){
            return QString::fromLocal8Bit(match.c_str());
        });
    
        return results;
    }
    

    Vielleicht fehlt in der main() noch ein std::cin.imbue(std::locale{""}), damit ich stdin mit der systemweiten Locale auslesen kann, weil sonst wird immer die C Locale benutzt. Ist doch so, oder?

    Und dann, ja, weil ich Qt6 benutze könnte ich auch direkt Anwendung für QStringTokenizer finden. Was aber nun schneller ist, entweder Boost oder Qt, das müsste ich dann testen, aber ich glaube das käme hier nicht mehr zur Relevanz.

    Danke jedenfalls für die Hilfe.


Log in to reply