Möglichkeit, strings mit mehreren wörtern zu teilen?



  • Hi,
    ich bin zurzeit an einer aufgabe dran, bei der das programm 5 strings einlesen soll. Ausgegeben werden, soll dann jedes wort in einer Zeile.
    Bsp:
    ( string1 ) ==> Die Kuh macht muh
    ( string2 ) ==> Die Katze macht Miau
    ( string3 ] ==> Der Hund macht wau
    ......

    Ausgabe:
    die
    Kuh
    macht
    muh
    die
    katze
    macht
    .....

    Das Problem hierbei ist, dass ein string alle Zeichenkette als Ganzes nimmt. Gibt es eine Möglichkeit den String nach jedem Wort zu teilen?
    Mein Ansatz wäre, dass man jeden string einmal durchgeht und dann mithilfe einer char variable in einer inneren schleife jede string Position durchgeht. Den wert der Läufervariable bis kleiner string laufen lässt und immer ein weitere char variabe ausgeben lässt. Dann eine If Bedingung einsetzt, welche zu einem zeilenumbruch führt, wenn die char variable ein leerzeichen ist. Aber zum einen geht der Compiler gar nicht auf das Leerzeichen ein und zum Anderen kommt die Benachrichtung ( Zugriffsverletzung beim Lesen an der Position ...) die Nachricht steht in zeile 32. Ich verstehe aber nicht ganz weshalb. Seht ihr den Fehler?

    *** Hab gerade im Debugger bemerkt, dass str[l] leider auch den gesamten string erfasst.. aber verstehe nicht weshalb? ich bin noch index=0 von von dem ersten string oder nicht? Da macht es natürlich sinn, dass weder die if bedingung funktioniert und der wert von str[l] bereits über der länge des strings geht...

    const int text = 2;
    string str[text] = { "" };
    char letter = ' ';
    
    for (int i = 0; i < text; i++)
    {
    	cout << "Texteingabe: " << endl;
    	getline(cin, str[i]);
    
    	if (str[i] == "")
    	{
    		break;
    	}
    }
    
    
    int l = 0;
    int str_pos = 0;
    
    for (int str_pos = 0; str_pos < text; str_pos++)// gehe jeden string durch
    {
    	for (; l < str[str_pos].length(); ) // gehe jedes Zeichen des jeweiligen strings durch
    	{
    		if (str[l] == " ") // wenn leerzeichen, dann zeilenende
    		{
    			cout << endl;
    		}
    		else
    		{
    			//letter = str[l]; 
    			//cout << letter;  oder cout << letter.at(l)  letter wird aber als falsch angezeigt
    			cout << str[l];
    		}
    		l++;
    	}
    	l = 0;
    	
    }


  • Schalte mal Warnungen bei dir im Compiler an. Du hast z. B. zwei mal die Variable str_pos definiert. Mit unterschiedlichen Gültigkeitsbereichen und Sichtbarkeiten.

    Du könntest dir auch mal die Doku von std::string anschauen, da gibt es Funktionen, wie find und substr, die für dich interessant sein könnten.



  • @Schlangenmensch stimm haste recht .. aber das ist auch nicht das problem gewesen...
    ich darf solche funktionen leider nicht verwenden.



  • Str[0] ist immer der erste String, egal ob du mit l oder str_pos darauf zugreifst. Str[0][0] ist das erste Zeichen des ersten Strings.



  • @Schlangenmensch str_pos steht ja sozusagen für den ersten string. also wenn ich <str[str_pos].length() als bedingung setze müsste doch l auf index 0 von str_pos hochgezählt werden oder nicht?
    bzw wie könnte ich sonst darauf zugreifen?



  • @mmm_1482_
    if (str[l] == " ")greift nicht auf ein Zeichen zu.



  • Wenn du, statt mit getline(cin, str[i]) eine ganze Zeile einzulesen, mittels cin >> word (wobei word dann als std::stringdeklariert ist) jeweils wortweise einliest, dann kannst du diese in einer Schleife nacheinander verarbeiten.

    Wenn die Aufgabe jedoch eher im Splitten eines Strings besteht, dann beachte den Hinweis von @Schlangenmensch bzgl. str[0][0] (die erste 0 ist der Index im String-Array, die zweite 0 ist der Index im String).
    Darfst du denn eigene Funktionen für die Aufgabe definieren? Dann wäre

    void ShowSplittedWords(string text)
    

    hier sinnvoll (dann kämst du auch nicht so mit dem Zugriff auf das String-Array durcheinander).

    PS: Du hast ja immer noch die eigenartig benannte Konstante text hier drin?!

    Außerdem machst du es dir selber schwer, wenn du die innere for-Schleife eher wie eine while-Schleife schreibst, statt

    for (int l = 0; l < str[str_pos].length(); ++l) // gehe jedes Zeichen des jeweiligen strings durch
    


  • @Schlangenmensch wie kann ich denn auf die einzelnen zeichenketten des string zugreifen?
    ich hab im internet noch das gefunden:
    char d = s.at(5);
    aber bei mir wird das als fehler markiert



  • @Th69 es wird zwar nicht explizit gesagt, was der sinn der aufgabe ist, aber ich denke es geht um das splitten eines strings.
    ist mit str[0][0] ein mehrdimensionaler array gemeint?

    ich hab mich schon an das wort text gewöhnt 😃



  • @mmm_1482_ sagte in Möglichkeit, strings mit mehreren wörtern zu teilen?:

    ist mit str[0][0] ein mehrdimensionaler array gemeint?

    Nur indirekt, da du nicht selber alle Dimensionen angegeben hast, da string implizit ein char-Array kapselt (und den Zugriff mittels [x] (bzw. at(x)) anbietet).
    Man spricht hier also nicht direkt von einem "mehrdimensionalen Array", obwohl der Zugriff genauso erfolgt (wegen der Möglichkeit der Operator-Überladung in C++).



  • @mmm_1482_ Du hast ein Array von Strings.

    Bei einem char-Array (auch C-String genannt) musst du die maximale Länge bei der Definition mit angeben.

    Bei std::string von C++ musst du das nicht.

    Da du aber ein Array von string hast, musst du einen Index benutzen, der aber den ganzen String bezeichnet.

    Also s[1].at(5) ist das 6. Zeichen vom 2. string.



  • @Th69 oh man ich muss das jetzt alles mal richtig überdenken... das kann was dauern 😃 danke



  • @mmm_1482_
    Erster Schritt: Funktionen schreiben statt Spaghetticode.
    Zweiter Schritt: STL verwenden.



  • @DirkB ach cool danke für die info! 🙂



  • @mmm_1482_ Der Trick ist jetzt, eine Funktion zu schreiben, die einen string zerlegt.

    Diese Funktion kannst du mehrmals aufrufen.



  • dub di dub.

    #include <cctype>
    #include <string>
    #include <iostream>
    
    template<typename T>
    void print_wordwise(T begin, T end, std::ostream& os, typename T::value_type separator = ' ')
    {
    	for (; begin != end; begin = std::find_if(begin, end, [](auto ch) { return !std::isspace(ch); })) {
    		while(begin != end && !std::isspace(*begin))  // fuer eine sehr einfache definition von "wort"
    			os.put(*begin++);
    		os.put(separator);
    	}
    }
    
    int main()
    {
    	std::string foo[]{
    		"Die Kuh macht muh",
    		"Die Katze macht miau",
    		"Der Hund macht wau",
    	};
    	
    
    	for (auto &bar : foo) {
    		print_wordwise(bar.begin(), bar.end(), std::cout, '\n');
    		std::cout.put('\n');
    	}
    }
    


  • @Swordfish sagte in Möglichkeit, strings mit mehreren wörtern zu teilen?:

    dub di dub.

    Das ging ja schnell 😆



  • @DirkB sagte in Möglichkeit, strings mit mehreren wörtern zu teilen?:

    Das ging ja schnell 😆

    Scherzkeks. Wie oft schreibt man sowas?

    Für
    @Swordfish sagte in Möglichkeit, strings mit mehreren wörtern zu teilen?:

    std::ostream&

    will man wahrscheinlich auch einen Template-Parameter.



  • Dieser Beitrag wurde gelöscht!


  • @Swordfish 😃 das ist echt lieb von dir, aber ich darf solche extras wie auto ostream& usw... gar nicht verwenden.. wenn ich ehrlich bin kann ich es auch gar nicht richtig lesen, obwohl es bestimmt ein besserer lösungsweg ist..
    wir dürfe nur array, string und schleifen verwenden. (Auch wenn es für die Aufgabe nicht vorgeschrieben ist, kann ich eine eigene funktion schreiben, aber vieles aus deiner funktion darf ich gar nicht verwenden) 😞
    und vieles davon kenne ich gar nicht
    zb
    ostream ( & ist ne referenz das sehe ich)
    diese ganzen doppelpunkte sind wegen der funktionsüberladung da bin mir da aber auch nicht sicher
    isspace kenne ich auch nicht..
    auto..
    wir dürfen keine pointer verwenden...
    also ich bin halt echt etwas eingeschränkt

    #include <cctype> das dürfen wir gar nicht inkludieren


Anmelden zum Antworten