2010-01-11 4 views
2

Я пытаюсь собрать вход пользователя в строковой переменной, которая принимает пробелы за определенное количество времени.std :: getline не работает внутри цикла for

С обычным cin >> str не принимает пробельные, так что я бы с станд :: GetLine из < строки >

Вот мой код:

#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; 
} 

Любая идея?

+6

Очень редко все происходит без какой-либо причины. – GManNickG

+0

попробуйте следующее перед циклом: std :: cout << "n:" << n << std :: endl; –

+0

Да. n было правильно прочитано. Я ввел 2 для n, и он печатает «n: 2» –

ответ

10

Вы можете понять, почему это происходит сбой, если вы выводите, что вы сохранили в local (который является плохим именем переменной, кстати: 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; 
} 

Вы увидите, что он печатает newline после > сразу после ввода вашего номера. Затем он переходит к вводу остальных.

Это потому, что getline дает вам пустую строку слева от ввода вашего номера. (Он читает число, но, видимо, не снимает \n, так что вы остаетесь с пустой строкой.) Вы должны избавиться от остатков пробельных первый:

#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; 
} 

этого произведения, как и ожидалось.

Отключить тему, возможно, это было только для фрагмента под рукой, но код имеет тенденцию быть Подробнее читаемый, если у вас нет using namespace std;. Он побеждает цель пространства имен. Я подозреваю, что это было только для публикации здесь.

+3

Я, как правило, явно использую префикс std :: namespace, но нет ничего плохого в использовании объявления в файле cpp (not h). –

+1

Возможно, на таком простом примере. Тем не менее, есть * много вещей в пространстве имен 'std'. Функциональный уровень является самым глобальным, я буду использовать директивы 'using'. – GManNickG

1

Вы нападаете на вход? Если не получить строку, она ничего не вернет, так как она ждет конца строки ...

0
  • Правильно ли инициализировано n из ввода?
  • Вы, кажется, ничего не делаете с getline. Это то, что вы хотите?
  • getline возвращает ссылку istream. Означает ли тот факт, что вы бросаете его на землю?
+0

Да. Я попытался напечатать его, и 'n' инициализируется правильно. --- Я отключил коды после getline. –

1

Я предполагаю, что вы не читаете n правильно, поэтому он преобразуется как ноль. Поскольку 0 не меньше 0, цикл никогда не выполняется.

Я хотел бы добавить немного приборов:

int n; 
cin >> n; 
std::cerr << "n was read as: " << n << "\n"; // <- added instrumentation 
for // ... 
+0

№. Цикл выполняется. Я использую VC++ 2008, поэтому я мог бы отлаживать, отслеживая код за строкой. –

0

На какой компилятор вы попробовать это? Я пробовал на VC2008 и отлично работал. Если я скомпилировал тот же код в g ++ (GCC) 3.4.2. Это не сработало. Ниже приведены версии, работающие в обоих компиляторах. У меня не будет последнего компилятора g ++ в моей среде.

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; 
} 
0

Важным вопросом является «что вы делаете со строкой, которая дает вам представление о том, что вход был пропущен?» Или, точнее, «почему вы считаете, что вход был пропущен?»

Если вы переходите через отладчик, вы скомпилировали его с оптимизацией (которой разрешено изменять порядок инструкций)?Я не думаю, что это твоя проблема, но это возможность.

Я думаю, что более вероятно, что строка заполнена, но она не обрабатывается правильно. Например, если вы хотите передать входные данные старым функциям C (например, atoi()), вам нужно будет извлечь строку стиля C (local.c_str()).

1

Объявить персонаж получить в карете возвращение после того, как вы набрали номер. char ws;int n;cin>>n;ws=cin.get(); Это решит проблему.

Использование cin>>ws вместо ws=cin.get(), сделает первый символ вашей строки, чтобы быть в переменной ws, вместо того, чтобы просто очищая '\n'.

0

Вы можете непосредственно использовать GetLine функции в строке, используя разделитель следующим образом:

#include <iostream> 
using namespace std; 
int main() 
{ 
    string str; 
    getline(cin,str,'#'); 
    getline(cin,str,'#'); 
} 

вы можете ввести Обл столько раз, сколько вы хотите, но одно условие применяется здесь вам нужно передать «#» (3-й аргумент) в качестве разделителя, т. Е. Строка будет принимать ввод до тех пор, пока '#' не будет нажата независимо от символа новой строки.