Einzelne Wörter jeweils bis zum nächsten Trennzeichen lesen
-
Hallo,
es geht um eine Übungsklausur, bei der ich nicht weiter komme.
Und zwar sollen wir aus einer Datei bestimmte Worttypen herausfilternZum einen die Nomen, die mind. 4 Zeichen lang sind, mit einem Großbuchtaben beginnen und nur aus Buchstaben bestehen.
zum anderen die Akronyme, welche ausschließlich aus Buchstaben bestehen, von denen mind. 2 Großbuchstaben sind.
Der Text ist folgendermaßen aufgebaut:
Der Erlrouter
Wer routet so spät durch Nacht und Wind?
Es ist der Router, er routet geschwind!
Bald routet er hier, bald routet er dort
Jedoch die Pakete, sie kommen nicht fort.Sie sammeln und drängeln sich, warten recht lange
in einer zu niedrig priorisierten Schlange.
Die Schlangen sind voll, der Router im Streß,
da meldet sich vorlaut der Routingprozeß
und ruft: "All Ihr Päckchen, Ihr sorgt Euch zu viel,
nicht der IP-Host, nein, der Weg ist das Ziel!"
...Mein Problem besteht jetzt beim herausfiltern einzelner Wörter. Momentan mache ich das so:
char dummy=' '; std::string strTmp=" "; while(dummy!='\n') { if(is.peek()=='"') dummy=is.get(); getline(is, strTmp, ' '); ... }
Damit kann ich zwar anfangs gut einlesen, bekomme aber beim letzten Wort Probleme, da logischerweise in die nächste Zeile bis zum nächsten Leerzeichen gesprungen wird.
Lese ich nun so ein
getline(is, strTmp, '\n');
bekomme ich ja die ganze Zeile geliefert und müsste die Wörter umständlich aus einem String herausfiltern.
Deswegen meine Frage: Gibt es eine möglichkeit Wort pro Wort bis zum Nächsten Trennzeichen (' ';'\n') einzulesen?
MfG
-
Ja. Operator >>
std::string wort; is >> wort;
-
Danke dir, hat funktioniert, hab's dann aber doch anders gelöst, aufgrund anderer Zeichen die ich ignorieren muss.
Hab jetzt aber ein anderes Problem. Und zwar komme ich aus dem einlesen nicht mehr raus:
void Manager::fromFile() { std::string fname = "Erlrouter.txt"; std::fstream f; f.open(fname.c_str(), std::ios::in); f.seekg(0); int counter=1; if(f.is_open()) { while(true) { //Word word; word.fromStream(f, counter); ++counter; if(f.eof()) break; } } }
void Word::fromStream(std::istream& is, int zeile) { int count=0; std::locale loc; bool test; char dummy='?'; std::string tmp; while(dummy != '\n') { tmp.clear(); if(is.peek()=='"') dummy=is.get(); while(true) { dummy = is.get(); if(dummy==' ' || dummy=='\n' || dummy=='.' || dummy=='?' || dummy=='!' || dummy==',') break; tmp.push_back(dummy); } for(unsigned i=0; i<tmp.size();i++) { if(tolower(tmp[i],loc) != tmp[i]) ++count;; test = isalpha(tmp[i],loc); if(test==false) break; if(i==tmp.size()-1 && tolower(tmp[0],loc) != tmp[0] &&tmp.size()>=4 && count<2) this->listWord.push_back(new Word(zeile, 'N', tmp)); else if(i==tmp.size()-1 && count >= 2) this->listWord.push_back(new Word(zeile, 'A', tmp)); } count = 0; } }
Das Dateiende sieht so aus:
...
Finster der Tunnel, die Bandbreite knapp,
wie schön war die Backplane im eigenen Hub.
Am Ende des Tunnels: Das Päckchen ist weg,
vernichtet vom Cyclic Redundancy Check.Habe leider das Problem, dass am Dateiende kein "\n" mehr auftacht und hänge deswegen in einer Endlosschleife. Jemand eine Idee wie ich das Disaster da oben am Besten aufräumen könnte?
MfG
-
Lass doch mal dieses dumme
while(true)
. In C++ liest man in der Regeln mitwhile(einleseaktion)
ein. Die Einleseaktion gibt dabei wieder den Stream zurück. Und wenn man so eine Einleseaktion schreibt dann wird man intern sicherlich auch noch andere Einleseaktionen benutzen, die das auch so machen und die man daher genauso in eine Schleife packen kann. Und wenn bei einer eigenen Einleseaktion was schiefgeht, dann setzt man das fail-flag des Streams. Und wenn man dann den Stream zurückgibt, wird dieser zu 0 ausgewertet und die Schleife bricht ab.Wenn du dich immer da dran hältst, dann sehen alle deine Leseschleifen gleich aus und du machst automatisch nie etwas falsch.
Und jetzt verstehst du auch, was da bei dir schiefläuft. Du prüfst nie die Rückgabe den Streamstatus nach is.get() und daher merkst du nie, wenn du am Dateiende bist.
Dummerweise ist istream::get() ausgerechnet die eine Lesefunktion, die als einzige nicht den Stream selbst zurückgibt. Didaktisch gerade ein bisschen unnütz . Du kannst aber immerhin da drauf prüfen, ob der Rückgabewert EOF ist oder du kannst den Kommaoperator benutzen, um nach dem Lesen den Stream auszuwerten.
-
Also besser while Schleife so abändern?
while(f.eof()) { //Word word; word.fromStream(f, counter); ++counter; }
Wie siehts dann aber in der fromStream() aus?
Hänge momentan nämlich in dieser Schleife:void Word::fromStream(std::istream& is, int zeile) { //... while(dummy != '\n') { tmp.clear(); if(is.peek()=='"') dummy=is.get(); while(true) { dummy = is.get(); if(dummy==' ' || dummy=='\n' || dummy=='.' || dummy=='?' || dummy=='!' || dummy==',') break; tmp.push_back(dummy); } //...
Am Dateiende wird hier leider kein \n zurückgegeben, daher ist mein while(dummy != '\n') hier wohl falsch. Nur mir fällt spontan keine andere Möglichkeit ein mich Zeile pro Zeile vorzuarbeiten..
-
Was soll denn while(f.eof())? Das heißt auf Deutsch: Führe die folgende Schleife aus, solange f sich im Fehlerzustand eof befindet (der übrigens erreicht wird, nachdem eine Leseaktion über das Ende geht)
Und wenn du an deiner Lesefunktion nichts änderst, wird's auch nicht von alleine richtig.
-
oh, sollte heißen while(!f.eof())
edit:
habs jetzt hinbekommen, indem ich in der fromStream() noch auf is.fail() geprüft hab.. dank dir für deine Hilfe
-
while(f)