std :: getline funktioniert nicht in einer for-Schleife
Frage
Ich versuche zu collect Benutzereingabe in einer String-Variablen, die Whitespaces für eine bestimmte Menge an Zeit akzeptiert.
Da die üblichen cin >> str
nicht Leerzeichen akzeptieren, so dass ich mit std :: getline gehen würde von
Hier ist mein Code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local); // This simply does not work. Just skipped without a reason.
//............................
}
//............................
return 0;
}
Jede Idee?
Lösung
Sie können sehen, warum dies fehlschlägt, wenn Sie die Ausgabe, was Sie in local
gespeichert (das ist eine schlechte Variablennamen, nebenbei gesagt: P):
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
}
//............................
return 0;
}
Sie werden sehen, es druckt eine neue Zeile nach >
unmittelbar nach Ihrer Nummer eingeben. Anschließend bewegt sich auf den Rest eingeben.
Das ist, weil getline
wird Ihr die leere Zeile über links geben von Ihrer Nummer eingeben. (Er liest die Nummer, aber offenbar nicht die \n
nicht entfernt, so dass Sie mit einer leeren Zeile sind links.) Sie müssen zunächst alle verbleibenden Leerzeichen loszuwerden:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
cin >> ws; // stream out any whitespace
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
}
//............................
return 0;
}
Das ist das funktioniert wie erwartet.
Aus Thema, vielleicht war es nur für die Schnipsel bei der Hand, aber Code neigt dazu, zu sein mehr lesbar, wenn Sie nicht using namespace std;
haben. Es Niederlagen der Zweck der Namensräume. Ich vermute, es war nur hier, um Beiträge, though.
Andere Tipps
Deklarieren Sie ein Zeichen zu erhalten in dem Wagen zurück, nachdem Sie in der number.char ws;int n;cin>>n;ws=cin.get();
eingegeben haben
Dadurch wird das Problem lösen.
Mit
cin>>ws
stattws=cin.get()
werden erste Zeichen der Zeichenfolge machen in Variablews
zu sein, statt nur Clearing'\n'
.
schlägst du eingeben? Wenn dies nicht der Linie erhalten wird nichts zurückgeben, da es für Zeilenende wartet ...
Meine Vermutung ist, dass Sie gerade lesen n
nicht richtig, so dass er als Null Umwandlung ist. Da 0 ist nicht weniger als 0, wird die Schleife nie ausgeführt wird.
würde ich ein wenig Instrumentierung hinzuzufügen:
int n;
cin >> n;
std::cerr << "n was read as: " << n << "\n"; // <- added instrumentation
for // ...
- Ist n richtig vom Eingang initialisiert?
- Sie scheinen nichts zu tun mit getline werden. Ist das, was Sie wollen?
- getline gibt eine istream Referenz. Bedeutet die Tatsache, dass Sie es auf dem Boden Materie sind fallen?
Auf dem Compiler haben Sie versucht das? Ich habe versucht, auf VC2008 und hat gut funktioniert. Wenn ich den gleichen Code auf g ++ (GCC) 3.4.2 zusammengestellt. Es funktionierte nicht richtig. Im Folgenden finden Sie die in beiden Compilern gearbeitet Versionen. Ich dont't die neuesten g ++ Compiler in meiner Umgebung haben.
int n;
cin >> n;
string local;
getline(cin, local); // don't need this on VC2008. But need it on g++ 3.4.2.
for (int i = 0; i < n; i++)
{
getline(cin, local);
cout << local;
}
Die wichtige Frage lautet: „Was Sie mit der Zeichenfolge tun, dass Sie die Idee gibt, dass der Eingang übersprungen wurde?“ Oder, genauer gesagt, „warum der Eingang übersprungen wurde?“
Wenn Sie sich Schritt durch den Debugger, haben Sie mit Optimierung kompilieren (die Neuordnungs Anweisungen erlaubt ist)? Ich glaube nicht, das ist Ihr Problem, aber es ist eine Möglichkeit.
Ich denke, es ist wahrscheinlich, dass die Zeichenfolge bevölkert wird, aber es ist nicht richtig gehandhabt wird. Zum Beispiel, wenn Sie die Eingabe in alten C-Funktionen übergeben werden sollen (z. B. atoi()
), müssen Sie den C-Stil-String (local.c_str()
) extrahieren.
Sie können direkt getline Funktion in Zeichenfolge mit Trennzeichen wie folgt:
#include <iostream>
using namespace std;
int main()
{
string str;
getline(cin,str,'#');
getline(cin,str,'#');
}
Sie können Eingangs str so oft wie Sie wollen, aber eine Bedingung gilt auch hier, was Sie brauchen, um passieren ‚#‘ (3. Argument) als Begrenzer dh String Eingabe akzeptieren, bis ‚#‘ unabhängig von Newline-Zeichen gedrückt wurde.