Satzzeichen, Tabs uns Umbrüche entfernene aus strings...



  • Guten Tag,
    ich such mir die finger wund und finde keine passende lösung,
    an sich denke ich mir das es ja nicht so schwer sein kann.
    doch es will mir nicht in meinen kopf hinein.

    istringstream iss(this->document);
        string word;
        while(iss >> word){    
           // hier 
            this->words_counted[word]++;
        }
    

    wie kann ich aus dem word die . , \t \n \r entfernen insofern sie überhaupt vorhanden sind??

    ich hab in einige foren einige lösungen gefunden die aber alle nicht funktioniert haben...
    bin mir nicht sicher ob es an isstringstream liegt oder woran auch immer...
    wie würdet ihr es machen ?

    danke für eure zeit und eucher verständnis.
    gruß Heppy



  • Es sind keine drin!

    Edit:
    Sorry, falsch gelesen ... '.' und ',' können drin sein, '\t', '\n' und '\r' nicht ...



  • remove_if: https://en.cppreference.com/w/cpp/algorithm/remove
    Da ist auch ein Beispiel dabei, ganz unten. Das kann man leicht auf das Entfernen von "." und "," anpassen.

    Kleiner Tip noch dazu: wenn der String nur aus "." und "," besteht, dann ist der nachher natürlich leer. Das wirst du dann vermutlich nicht als Wort zählen wollen - d.h. das solltest du berücksichtigen.



  • Wie wäre es mit ner RegEx?



  • @Tyrdal sagte in Satzzeichen, Tabs uns Umbrüche entfernene aus strings...:

    Wie wäre es mit ner RegEx?

    Nicht so gut 🙂
    (Klar, regex-replace geht -- wenn man auf Schmerzen und unnötig langsamen Code steht. Aber ist in dem Fall mMn. nicht die beste Lösung.)

    ps: Oder meinst du per Regex die Worte aus dem ganzen Text rausklauben - also ganz ohne Stream? Das ginge. Wäre vermutlich sogar besser, weil man damit auch Texte korrekt parsen kann wo Worte nur durch "," getrennt sind, ohne Whitespace dazwischen. (Meine ursprüngliche Antwort war darauf bezogen nur die Interpunktionszeichen aus einen String zu entfernen. Und dafür halte ich Regex für Overkill.)



  • @hustbaer Ja genau, aus dem ganzen Text regexen. Ich bin nicht so der stream Freund. Bei einzelnen kleinen Strings würde ich auch lieber was simpleres implementieren.



  • @hustbaer unter dem link ganz unten findet man den code wie man leerzeichen aus dem string entfernen kann das würde auch soweit funktionieren danke auf jeden fall dafür. Du sagtest auch man kann es ganz leicht umbauen damit, mit dem code dann auch punkte und kommas heraus geschnitten werden können. Leider denke ich total falsch befürchte ich und schreib nur mist zusammen 🙂

    Bin auch vor der Anfrage hier öffter auf remove und remove_if gestossen, jedoch habe ich es bisher nicht geschaft das er mit "." und "," und "\n" und "t" entfernt.

    word.erase(std::remove_if(word.begin(),
                                 word.end(),
                                 [](unsigned char x){return std::isspace(x);}), // hier
                                 word.end());
    

    wenn ich das richtig verstehe ist bei dem code oben die markierte stelle das was heraus genommen werden soll.
    und das x ist das zeichen des strings welches grade betratet wird oder?
    also müsste doch ein x == "." oder so anstelle von isspace(x) um die punkte zu entfernen.
    Aber so geht das nicht, wie gesagt ich denke wohl grade mal wieder falsch. xD



  • @Heppy sagte in Satzzeichen, Tabs uns Umbrüche entfernene aus strings...:

    wenn ich das richtig verstehe ist bei dem code oben die markierte stelle das was heraus genommen werden soll.
    und das x ist das zeichen des strings welches grade betratet wird oder?

    Ja.

    @Heppy sagte in Satzzeichen, Tabs uns Umbrüche entfernene aus strings...:

    also müsste doch ein x == "." oder so anstelle von isspace(x) um die punkte zu entfernen.

    Ja.

    return x == '.' || x == ',' || x == '\n' || x == '\t';
    

    oder irgendwas mit

    return std::ispunct(x) || x == '\n' || x == '\t';
    


  • @Swordfish danke für die antwort dann hab ich ja doch nicht so falsch gedacht xD
    mein fehler war das ich immer "." anstelle von '.' verwendet habe und das klapt dann halt nit.

    Ich hatte ja gesagt ich bin schon mal auf diesen remove befehlt getroffen und hab immer wieder alles möglich probiert,
    aber mal einfache anstelle von doppelten zu nehmen ist mir einfach nicht in den kopf gekommen.

        string doc = this->document;
        doc.erase(std::remove_if(doc.begin(),
                                 doc.end(),
                                 [](unsigned char x){return x == '.' || x == ',' || x == '\n' || x == '\r';}),
                                 doc.end());
    
        istringstream iss(doc);
        string word;
        while(iss >> word){    
            this->words_counted[word]++;
            cout << word << " ";
        }
    

    Ok also an sich macht es das was es soll vielen dank dafür, ich hab lediglich den erase befehl aus der schleife genommen
    und in den haupt string eingebaut. so muss er nur einmal durchlaufen und nicht für jedes anfallende wort. denke so ist es vernünftiger.

    ein dickes danke noch mal an alle.
    wünsche euch noch einen schönen abend und bleibt gesund.



  • @Heppy

    /* ... */
        string doc = this->document;
        doc.erase(std::remove_if(doc.begin(),
                                 doc.end(),
                                 [](unsigned char x){return x == '.' || x == ',' || x == '\n' || x == '\r';}),
                                 doc.end());
    /* ... */
    

    (...) ich hab lediglich den erase befehl aus der schleife genommen

    Ich würde das || x == '\n' || x == '\r' weglassen.
    Damit löscht du ja auch CR und LF Zeichen.
    Wenn doc z.B. das ist:

    Mein Text
    ist voll super.
    

    Dann wird daraus das:

    Mein Textist voll super
    

    Und das ist vermutlich nicht gewünscht.



  • Und nochwas: wenn der Text Punkte oder Komma enthält die weder davor noch dahinter ein Leerzeichen haben, dann macht dein Code auch nicht was er (vermutlich) soll -- die Worte vor und nach dem Punkt/Komma würden in so einem Fall auch zu einem Wort zusammengehängt.

    Das könntest du lösen, indem du statt alle Punkte und Komma zu entfernen diese einfach in Leerzeichen umwandelst. Vor der Schleife mit dem Stream. Der Stream ignoriert beim Einlesen ja alle Whitespaces, auch mehrere hintereinander, d.h. weitere Änderun sollte keine nötig sein.

    Dazu könntest du std::transform verwenden: https://en.cppreference.com/w/cpp/algorithm/transform
    Auch hier ist auf der Seite ein Beispiel das sich leicht modifizieren lässt.
    Du musst bloss statt return std::toupper(c); was passendes einsetzen 😉



  • @hustbaer
    danke für deine anmerkung mit dem CR und LF
    jedoch ist es in diesem fall sogar ausdrücklich so gewollt, im normalfall würde ich dir aber vollkommen zustimmen.

    das mit dem punkten ohne lehrzeichen klingt einleuchtend und werde ich mir notieren sowie anschauen ist aber
    in diesem fall auch noch nicht erforderlich.

    Ich muss mir scheinbar sowiso noch einiges erneut anschauen, das ich mir C++ mal halbwegs beigebracht hatte ist schon eine ewigkeit her und irgendwie scheint jetzt vieles anders zu sein als damals, was nicht schlecht ist aber mich wohl erneut zur suche nach guten einweisungen drängt xD

    Danke nochmals


Log in to reply