c ++ getline () не ждет ввода от консоли при многократном вызове - PullRequest
18 голосов
/ 17 октября 2011

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

#include <string>
#include <iostream>
using namespace std;

// ...

string inputString;
unsigned int inputUInt;
double inputDouble;

// ...

cout << "Title: "; 
getline(cin, inputString);
tempDVD.setTitle(inputString);

cout << "Category: "; 
getline(cin, inputString);
tempDVD.setCategory(inputString);

cout << "Duration (minutes): "; 
cin >> inputUInt; 
tempDVD.setDuration(inputUInt);

cout << "Year: "; 
cin >> inputUInt; 
tempDVD.setYear(inputUInt);

cout << "Price: $"; 
cin >> inputDouble; 
tempDVD.setPrice(inputDouble);

Однако при запуске программы вместо ожидания ввода первой строки inputString код не останавливается до второй строки getline () вызов.Таким образом, вывод консоли выглядит следующим образом:

Заголовок: Категория:

с курсором, появляющимся после категории.Если я введу сейчас, программа перейдет к вводу года, не позволяя мне ввести более одной строки.Что здесь происходит?

Ответы [ 6 ]

20 голосов
/ 17 октября 2011

Проблема в том, что вы смешиваете вызовы getline () с использованием оператора >>.

Помните, что оператор >> игнорировал начальные пробелы, поэтому будет корректно продолжаться через границы строк. Но останавливает чтение после того, как ввод был успешно извлечен и, следовательно, не будет глотать завершающие символы '\ n'. Таким образом, если вы используете getline () после >>, вы обычно ошибаетесь, если не будете осторожны (сначала удалите не прочитанный символ '\ n').

Хитрость заключается в том, чтобы не использовать оба типа ввода. Выберите подходящий и придерживайтесь его.

Если это все числа (или объекты, которые хорошо работают с оператором >>), тогда просто используйте оператор >> (примечание: строка является единственным фундаментальным типом, который не симметричен с вводом / выводом (т. Е. Не воспроизводится красиво)).

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

std::getline(std::cin, line);
std::stringstream  linestream(line);

int  value;
linestream >> value;

// Or if you have boost:
std::getline(std::cin, line);
int  value = boost::lexical_cast<int>(line);
12 голосов
/ 17 октября 2011

Вам необходимо очистить входной буфер.Это можно сделать с помощью cin.clear(); cin.sync();.

8 голосов
/ 25 августа 2013

Вы можете использовать

cin.ignore();

или как упомянутое @kernald использование

cin.clear();
cin.sync();

перед использованием getline ()

3 голосов
/ 17 октября 2011

Используйте cin.clear(), как указано и , используйте правильную обработку ошибок:

    cin.clear();
    cin.sync();

    cout << "Title: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setTitle(inputString);

    cout << "Category: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setCategory(inputString);

    cout << "Duration (minutes): "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setDuration(inputUInt);

    cout << "Year: "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setYear(inputUInt);

    cout << "Price: $"; 
    if (!(cin >> inputDouble)) exit 255; 
    tempDVD.setPrice(inputDouble);
0 голосов
/ 30 июля 2018

cin.sync (); используйте это вместо cin.ignore ( работает лучше всего.

0 голосов
/ 01 апреля 2013

Смешивать getline () с входными потоками, как правило, плохо. Теоретически возможно вручную обработать грязные буферы, оставленные с помощью потоков, но это ненужная боль, которую определенно следует избегать.

Вам лучше использовать консольную библиотеку для захвата ввода, так что грязная работа может быть для вас абстрагирована.

Взгляните на TinyCon. Вы можете просто использовать статический метод tinyConsole :: getLine () вместо ваших вызовов getline и stream и использовать его столько раз, сколько захотите.

Вы можете найти информацию здесь: https://sourceforge.net/projects/tinycon/

...