Probleme mit cin und while
-
Hallo,
vorweg gesagt: Ich bin ein totaler Anfänger und versuche mir C++ mit dem Buch "C++ Primer" beizubringen.
Nun wollte ich ein kleines Programm schreiben, dass eine unbekannte Anzahl an Zeichenfolgen (durch Leerzeichen getrennt) über die Standardeingabe (cin) einließt und sie mir zu einem langen String zusammensetzt (ohne Leerzeichen) und anschließend - ganz am Programmende - den resultierenden String ausgibt.
Hier mein kleines Programm:
#include <iostream> #include <string> using namespace std; int main() { cout << "Bitte eine Reihe Zeichenfolgen eingeben." << endl; string st; string result; while(cin >> st) { result += st; } cout << result << endl; return 0; }Eine Fehlermeldung gibt mir der Compiler nicht aus und ich kann das Programm auch soweit ausführen, doch wird mir niemals "result" am Ende ausgegeben. Ich habe irgendwie die Befürchtung, dass er kein EOF-Signal bekommt, weitere Eingaben erwartet und somit die while-Schleife nicht verlässt.
Ein Ähnliches Problem hatte ich Gestern bei einem anderen kleinen Programm mit einer ähnlichen While-Schleife. Der Code, der nach dieser While-Schleife kommt, wird nicht mehr beachtet.
Wenn ich die While-Schleife etwas abändere und die Ausgabe von "result" in die Schleife hinein verlege, läuft es einwandfrei durch.
Übersehe ich irgendwo einen kleinen Fehler, den der Compiler (GCC) ignoriert?
Grüße,
Bohne
-
Dein Programm wartet so lange auf eine Eingabe, bis die Eingabe geschlossen wird (oder ein Fehler auftritt). Und genau das steht auch im Quelltext, von daher hat der GCC schon alles richtig gemacht

Verstehe ich richtig: Du willst eine Zeile einlesen und aus dieser dann die einzelnen Wörter heraustrennen? Das könntest Du (z.B.) machen, indem Du auch nur eine Zeile einliest, und über diese dann mit einem Stringstream liest, bis die Eingabe geschlossen wird (was am Ende des Strings der Fall sein wird).
cout << "Bitte eine Reihe Zeichenfolgen eingeben." << endl; string zeile; getline(cin, zeile); istringstream s(zeile); string wort; string result; while (s >> wort) { result += st; } cout << result << endl; return 0; }
-
Oder Buchstabe für Buchstabe:
#include <iostream> #include <string> using namespace std; int main() { cout << "Bitte eine Reihe Zeichenfolgen eingeben." << endl; char ch; string result; while((ch = cin.get()) != '\n') { result += ch; } cout << result << endl; return 0; }
-
Vielen Dank! Ich denke, ersterer Vorschlag (wortweise) ist effektiver und schneller, da weniger Durchläufe der While-Schleife nötig sind. Oder?
Das Programm funktioniert und ich bin glücklich. *jeaha*
Bin aber dennoch etwas verwirrt, denn irgendwie muss das auch ohne den Funktionen/Typen "get()" und "istringstream" gehen. Diese werden erst viel später im Buch erwähnt. 
Nun egal. Das Problem ist gelöst, ich bin schlauer. Ein guter Tag:

Grüße,
Bohne
-
LordJaxom schrieb:
Dein Programm wartet so lange auf eine Eingabe, bis die Eingabe geschlossen wird (oder ein Fehler auftritt). Und genau das steht auch im Quelltext, von daher hat der GCC schon alles richtig gemacht

Nochmal hierzu zurück.
Ich habe jetzt etwas weiter rumprobiert und mich an einer weiteren Aufgabe in meinem Buch versucht. Dort soll nun eine Reihe von Integerzahlen in einen Vektor eingelesen und anschließend einige Berechnungen mit den einzelnen Elementen des Vektors durchgeführt werden.
Soweit so gut. Das Abspeichern der einzelnen Integerzahlen realisierte ich wieder mit einer while-Schleife, so wie es in anderen Beispielen im Buch vorgegeben ist.
#include <iostream> #include <vector> using namespace std; int main() { cout << "Bitte eine Reihe Zahlen eingeben." << endl; vector<int> vec; int i = 0; unsigned x = 0; while(cin >> i) { vec.push_back(i); ++x; } for(vector<int>::size_type ix = 0; ix <= x; ++ix) { cout << "Das " << ix+1 << ". Element in vec ist " << vec[ix] << "." << endl; } return 0; }Nachdem man eine Reihe Integerzahlen eingegeben und mit Enter abgeschlossen hat, erwartet das Programm, wie ich jetzt weiß, weitere Eingaben, da noch kein EOF oder Fehler aufgetreten ist. Wenn ich nun z.B. einen Buchstaben eingebe, ist es ein Fehler und die for-Schleife wird durchlaufen.
Gebe ich nun beispielsweise die Reihe "3 4 5 6 d" ein, so besteht der Vektor aus den Elementen 0->3, 1->4, 2->5, 3->6, 4->0. Das fehlerhafte "d" hat er in eine 0 umgewandelt (wohl, weil ich i mit 0 initialisiert habe).
Was muss ich eingeben bzw. wie muss ich mein kleines Programm umändern, so dass das eingegebene "Enter" als Eingabeende anerkannt wird? Ist es hilfreich wieder über getline() zu arbeiten und dann "wortweise" die Zahlen in den Vektor einzulesen? Das letzte Element des Vektors ist aber wieder null, wie oben.
#include <iostream> #include <vector> #include <sstream> using namespace std; int main() { cout << "Bitte eine Reihe Zahlen eingeben." << endl; string zeile; getline(cin, zeile); vector<int> vec; istringstream s(zeile); int i = 0; unsigned x = 0; while(s >> i) { vec.push_back(i); ++x; } // for-Schleife wie oben return 0; }Dann bleibt aber noch die Frage, warum bei den Beispielen im Buch nicht auf dieses Problem mit dem fehlenden Eingabeende hingewiesen wird.
Leider habe ich noch nirgends Musterlösungen zu den Aufgaben gefunden. 
Grüße,
BohnePS: Sry, für den Doppelpost

-
Der erste Fehler ist das du ix <= x prüfst. Müsste ix < x sein. Oder besser noch ix < vec.size()
-
Der Orginalcode des Threaderstellers funktioniert wunderbar. Man muss eben die Eingabe mit EOF beenden, wie das geht hängt von der Shell ab, normal mit STRG+D. Das guter Stil und kann ruhig so bleiben.
-
Danke, Fellhuhn. Mit diesen Vergleichen stehe ich immer auf Kriegsfuß :-| Funktioniert nun einwandfrei.
Berichtiger schrieb:
Der Orginalcode des Threaderstellers funktioniert wunderbar. Man muss eben die Eingabe mit EOF beenden, wie das geht hängt von der Shell ab, normal mit STRG+D.
Und woher weiß das der 0815-Standard-DAU? (wie ich es bin
) Kann man das nicht irgendwie durch das Programm erzwingen? Zum Beispiel maximal eine Zeile Eingabe und ein "Enter" schließt die Eingabe ab und erzwingt EOF?Grüße,
BohnePS: "Das guter Stil und kann ruhig so bleiben." <-- Wenn da ein "ist" fehlt: Danke für das Kompliment!

-
Der DAU verwendet keine Konsolenanwendungen. Bei Konsolenanwendungen ist das verwenden von einer EOF-Escape-Sequenz üblich, siehe alle gängigen Unix-Tools.
-
Darauf wollte ich mit "Dein Programm wartet so lange auf eine Eingabe, bis die Eingabe geschlossen wird" hinaus, ich wollte den Anfänger aber nicht mit Begriffen wie EOF und Unix-Shell langweilen. Zumal er ja mit nicht geringer Wahrscheinlichkeit auch Windows nutzen könnte, und da funktioniert das mit dem EOF-Signal IMO nicht so besonders gut.
Außerdem wäre nach einem EOF die Standardeingabe bis zum Ende des Programmlaufs nicht mehr ansprechbar, das kann es doch auch nicht sein. Deshalb lern lieber erstmal, mit zeilenweiser Eingabe umzugehen (gängiges Konzept aller Konsolen, egal ob Windows, Unix oder sonstwas :D), da hat Dein Programm länger was von.
-
Ah! *klick* Danke für die Erklärung!
Werde mir das mal zu Herzen nehmen und mich wieder in die nächsten Kapitel vertiefen. 
Grüße,
Bohne