Stringoperationen für Anfänger - Mögliche Hilfe ?



  • Guten Tag!
    Da ich noch nicht lange mit C++ programmiere und langsam an einem Programm verzweifle, habe ich mir gedacht, dass ich euch mal frage..
    Es handelt sich, um ein Programm, welches eine Textdatei einlesen soll und diese aus dem Plattdeutschen in keddelklopperspookisch umwandeln soll. Hierzu ein Beispiel zur Verdeutlichung: Das Wort "Kried" soll in die Kleinschrift zu "iedkri" geschrieben werden. Das Wort wird also bis zu dem ersten Vokal untersucht und der Teil vor dem Vokal an das Ende des Wortes gepushed. Anschließend soll ein i hinten rangehängt werden.
    Hier also zum Code:

    
    ```#include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    using namespace std;
    int main()
    {
       /* string name;
        vector <string> zeile;
        cout << " Datei: ";
        cin >> name;
        ifstream input(name);
        if (!input){
                cerr << " Datei beim Oeffnen der Datei " << name << "\n";
                return 1;}
            string line;
            while ( getline(input,line)){
                    cout << line << "\n" ;}
            return 0; */
        int j=0; // Groß in Kleinbuchstaben
        char c;
        ```cpp
    
    ```string str = "Please, replAce The vOwels in this sentence by asterisks.  \n" ;
        while (str[j])
        {
            c=str[j];
            putchar (tolower(c));
            j++;
        }
        string str1 ;
        unsigned counterr = 0;
            size_t found = str.find_first_of(" aeiou "); // Filter für Vokale
            while (found != string::npos)  // Posititonsausgabe des Vokales
            {
                cout << " Vokal " << str[found];
                cout << " Position " << found << '\n'; //Positionen passen alle
                if (found==0)
                {
                    for( int i = 0; i < str[found]; i++){
                    str1.push_back( str.at(i) );
                    }
                    str1.push_back('i');
                    str1.insert(str.begin(), str[found]);
                    counterr++;
                }
                else
                {
                    for( unsigned int l = 0; l < found ; l++ )  // Umdrehen des Strings bis zum erst auftretenden Vokal
                    {
                        str1.push_back(str.at(l));
                    }
                    str1.push_back('i');
                    counterr++;
                }
                found=str.find_first_of("aeiou",found+1);
            }
    
         return 0;
    }


  • Der counterr soll noch einen Bezug zu der neuen Länge aufgrund des angehangenen i's haben



  • Du stellst keine Frage.

    Mit CLI/.NET hat es wohl eher nichts zu tun.



  • @c-beginnerw bitte benutze Code-Tags.
    Heht auch nachträglich.
    Beitrag bearbeiten, Code mit der Maus markieren und auf das </> Symbol klicken.

    danke



  • @manni66 Wo kann ich diese Frage denn reinschreiben?



  • @c-beginnerw sagte in Programmieranfänger findet seinen Fehler nicht:

    @manni66 Wo kann ich diese Frage denn reinschreiben?

    Hier. Eine Frage hat am Ende ein ?
    Ein Moderator wird das dann nach C++ oder ein anderes passendes Unterforum verschieben.



  • Ich würde versuchen, das Problem zu zerlegen. Einmal musst du einen Satz in Wörter aufteilen und einmal das jeweilige Wort ändern.

    Für ein einzelnes Wort könnte man sowas machen:

    string keddelklopperspookischWord(string in) {
       for (auto &c : in) c = tolower(c);
       size_t pos = in.find_first_of("aeiou");
       if (pos == string::npos) return in; // Kein Vokal drin, was nun? Wort in klein, ansonsten unveraendert zurueck?
       rotate(begin(in), begin(in) + pos, end(in)); // Yeah! Rotate! Zu Ehren von Sean Parent ;-)
       return in + "i";
    }
    

    Nun musst du nur noch deinen Satz in Wörter aufteilen und obige Funktion für jedes Wort aufrufen.



  • @wob Vielen Dank für die zeitnahe Antwort !
    Was macht dieses (auto &c ..) in der zweiten Zeile? In der vorletzten Zeile müsste auch pos-1 stehen, da der Vokal vorne im Wort stehen bleibt, richtig? Bei keinem Vokal wird hinten ein 'i' angehangen 🙂
    Das Aufteilen des Satzes in die Bestandteile wird mit dem Befehl "strtok" ausgeführt, jedoch sollen wir diesen Befehl noch nicht verwenden. Gibt es dazu auch noch eine leichtere Lösung?



  • @c-beginnerw sagte in Stringoperationen für Anfänger - Mögliche Hilfe ?:

    Was macht dieses (auto &c ..) in der zweiten Zeile?

    Für jedes Element c aus in: wandle in lowercase.
    auto = Typ automatisch ermitteln (hätte hier auch char schreiben können), siehe https://en.cppreference.com/w/cpp/language/auto
    & = Referenz, d.h. keine Kopie, sondern Zeichen direkt in in ändern; siehe https://en.cppreference.com/w/cpp/language/reference

    In der vorletzten Zeile müsste auch pos-1 stehen, da der Vokal vorne im Wort stehen bleibt, richtig?

    Nein, ist richtig ohne die -1

    Die letzten 2 Zeilen ensprechen ohne rotate:
    return in.substr(pos) + in.substr(0, pos) + "i";
    Nirgends ein -1 zu sehen.

    Bei keinem Vokal wird hinten ein 'i' angehangen 🙂

    Ok, dann muss das anders. Dann überspringt man nur das rotate (siehe https://en.cppreference.com/w/cpp/algorithm/rotate), wenn pos == npos ist. Wenn man statt der string::find_first_of-Funktionen std::find_first_of verwendet, kann man sich den Check auf npos auch ganz sparen.

    Das Aufteilen des Satzes in die Bestandteile wird mit dem Befehl "strtok" ausgeführt, jedoch sollen wir diesen Befehl noch nicht verwenden. Gibt es dazu auch noch eine leichtere Lösung?

    boost::split? absl::StrSplit? Aber vermutlich sollt ihr es manuell machen und nach einem nicht-Buchstaben suchen.



  • @wob Achso, vielen Dank für die Erklärung.
    Ich habe das jetzt probiert zu Implementieren und hier ist mein Ergebnis:

    #include <iostream>
    #include <vector>
    #include <string>
    #include "keddelklopperspook.h"
    using namespace std;
     
    string extract ( string ex, const char&c ) // c legt das Trennungszeichen fest
    {
        string buff{""}; // Wörtertrennung
        for ( auto n:zeile )
        {
            if ( n != c ) //error : no match for 'operator!='
                buff+=n;
            else if (n==c && buff != "")
            {
                ex.push_back(buff);
                buff = "";
            }
        }
        if (buff != "")
            ex.push_back(buff);
        for ( unsigned int i = 0; i < zeile.at(i), i++ )
        {
            for ( auto &c : ex )
                c = tolower(c);
            size_t pos = ex.find_first_of("aeiou");
            if ( pos == string::npos )
                return ex + "i";
            rotate( begin(ex), begin(ex) + pos, end(ex));
            return ex + "i";
        }
    }
    


  • @c-beginnerw Vollständigen Code bitte.



  • Aha!

    Ich nehme an, du möchtest, daß sich jemand damit weiterbeschäftigt?
    Dann solltest du lernen, wie ein Forum funktioniert:

    • Nicht bloß Code posten und irgendwo dadrin Fehlermeldungen als Kommentar hinterlassen, sondern explizit die Fehlermeldungen (am besten per C&P) hier posten.
    • Stelle eine konkrete Frage!

    Daher nun als Gegenfragen:

    • Was ist zeile für eine Variable?
    • Möchtest du nicht eher den Parameter ex benutzen (und dir bessere Bezeichnernamen einfallen lassen)?


  • Mein uebersetzt soll den übersetzen Satz beinhalten und die Variable wort beinhaltet das einzelne Wort, welches danach in uebersetzt hineingepushed wird. Da ich den Inhalt aus dem Programm nicht kopieren kann, habe ich die Fehlermeldung nicht ausgeschrieben, jedoch steht dort jetzt :Line:21 error: no matching function for call to 'std::__cxx11::basic_string<char>::push_back(std::__cxx11::string&)'. Ich habe die Zeile 21 vorne mit einem Sternchen versehen. Meine konkrete Fragen sind nun, ob das Programm so ohne den Fehler funktionieren würde und wie man diese beheben kann.

    #include <iostream>
    #include <vector>
    #include <string>
    #include "keddelklopperspook.h"
    using namespace std;
     
    string extract ( string wort, const char&c ) // c legt das Trennungszeichen fest
    {
        string uebersetzt;
        string buff{""}; // Wörtertrennung
        for ( auto n:zeile )
        {
            if ( n != c ) 
                buff+=n;
            else if (n==c && buff != "")
            {
    *            wort.push_back(buff);
                buff = "";
            }
        }
        if (buff != "")
            wort.push_back(buff);
        for ( unsigned int i = 0; i < wort.at(i), i++ )
        {
            for ( auto &c : ex )
                c = tolower(c);
            size_t pos = wort.find_first_of("aeiou");
            if ( pos == string::npos )
                uebersetzt.push_back(wort+"i");
            rotate( begin(wort), begin(wort) + pos, end(wort));
            uebersetzt.push_back(wort+"i");
        }
    }
    


  • Die Funktion push_back gibt es nur bei einem std::vector, nicht bei einem std::string. Und es bleiben die Frage von @Th69 noch.



  • @wob sagte in Stringoperationen für Anfänger - Mögliche Hilfe ?:

    Die Funktion push_back gibt es nur bei einem std::vector, nicht bei einem std::string.

    Auch string hat push_back, aber nur für einzelne Zeichen (char). strings kann man mit append anhängen.

    https://en.cppreference.com/w/cpp/string/basic_string/append



  • @manni66 uups, tatsächlich. Ich habe push_back bei strings noch nie benutzt! Irgendwie erscheint mir bei strings += natürlicher (oder append).
    Liegt daran, dass ich bei strings eher an eine Zeichenkette als an eine Sammlung von einzelnen Buchstaben denke, vermute ich.

    (und natürlich gibt es push_back auch noch bei anderen Typen, z.B. deque)



  • @wob Ein String ist doch aber auch ein Vector oder irre ich mich da? Sonst lässt sich das wort.push_back(buff) durch ein wort.append(buff) ersetzen richtig?

    Die Gegenfragen von Th69 habe ich in dem oberen Text mit sinnvolleren Variablen geklärt



  • hunde und katzen sind auch beides säugetiere, aber ansonsten völlig verschieden. 😉



  • Solange nicht Wurstsemmel von Wurst und Supermarkt erbt ist alles in Butter ...



  • Gut, vielen Dank euch ! Das Thema kann geschlossen werden.


Anmelden zum Antworten