Stringoperationen für Anfänger - Mögliche Hilfe ?
-
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 auchchar
schreiben können), siehe https://en.cppreference.com/w/cpp/language/auto
& = Referenz, d.h. keine Kopie, sondern Zeichen direkt inin
ändern; siehe https://en.cppreference.com/w/cpp/language/referenceIn 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 derstring::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 (oderappend
).
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.
-
Guten Abend!
Beim Vervollständigen des Programmes ist mir aufgefallen, dass ich noch Probleme mit den Referenzen in den Funktionen habe.
Meine Main.cpp:
#include <iostream> #include <string> #include <vector> #include <fstream> #include "keddelklopperspook.h" using namespace std; int main() { string name; string zeile;// = zB"Diu pliusterst diek op ase en Pfau."; cout << " Datei: "; cin.ignore(); getline(cin,name); if( !(read(name,zeile)) ) cout<<" Datei konnte nicht eingelesen werden"; else{ if(write(extract(zeile),name)) cout<<"Ausgabe: " +name+ "lsg.txt \n"; else cout<<"Datei konnte nicht ausgegeben werden"; return 0; }
Meine keddelklopperspook.cpp:
string extract ( string& zeile , const char& c ) // Trennungszeichen { string wort = zeile; string uebersetzt; string buff{""}; // Wörtertrennung for ( auto n:wort ) { if ( n != c ) buff+=n; else if (n==c && buff != "") { wort.append(buff); buff = ""; } } if (buff != ""){ wort.append(buff);} for ( auto &b : wort ) b = tolower(b); size_t pos = wort.find_first_of("aeiou"); if ( pos == string::npos ) uebersetzt.append( wort + "i" ) ; else { rotate( begin(wort), begin(wort) + pos, end(wort)); uebersetzt.append( wort + "i" ) ; } return uebersetzt; } /*bool write(const string& name) { ofstream tdat( "Z:\\Programmieren 2\\Aufgabe 02\\bsp\\"+name+"lsg.txt" ); if ( tdat.good() ) return true; else return false; } */
und die dazugrhörige Header Datei:
#ifndef KEDDELKLOPPERSPOOK_H_INCLUDED #define KEDDELKLOPPERSPOOK_H_INCLUDED #include <vector> #include <string> using namespace std; bool read ( const string& name, string& zeile ); string extract ( string& zeile, const char&c ); void write ( const string& name ); #endif // KEDDELKLOPPERSPOOK_H_INCLUDED
In der keedelklopperspook.cpp stimmt irgendetwas mit der Aufteilung der Worte noch nicht, da beim ersten Wort bis zum ersten Vokal das Wort richtig abgetrennt wird, dieses jedoch ans Ende von dem gesamten String gepackt wird und die Methode mit der ersten Abtrennung auch aufhört. Habe ich in der For-Schleife einen Fehler und sind die Referenzen in den drei Methoden richtig?
-
Dann debugge doch mal diese Funktion (und schau dir dabei besonders Zeile 12 an).