Это потому, что метод Scanner.nextInt
не использует символ последней новой строки вашего ввода и, следовательно, newline потребляется в следующий вызов Scanner.nextLine
.
Вы столкнетесь с аналогичным поведением, когда вы используете Scanner.nextLine
после Scanner.next()
или любого метода Scanner.nextFoo
(кроме самого nextLine
).
Обход проблемы:
Scanner.nextLine
вызов после Scanner.nextInt
или Scanner.nextFoo
, чтобы потреблять остальную часть этой линии, включая newline int option = input.nextInt();
input.nextLine(); // Consume newline left-over
String str1 = input.nextLine();
Scanner.nextLine
и преобразуете свой ввод в нужный формат. Например, к целому числу с использованием метода Integer.parseInt(String)
. int option = 0;
try {
option = Integer.parseInt(input.nextLine());
} catch (NumberFormatException e) {
e.printStackTrace();
}
String str1 = input.nextLine();
cout << "Enter the number: ";
int number;
if (cin >> number)
{
// throw away the rest of the line
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
cout << "Enter names: ";
string name;
// keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
while (getline(cin, name))
...use name...
}
else
{
std::cerr << "ERROR reading number\n";
exit(EXIT_FAILURE);
}
В приведенном выше коде этот бит ...
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
... проверяет остальную строку ввода после того, как номер содержит только пробелы.
Это довольно многословно, поэтому использование ignore
в потоке после >> x
является часто рекомендуемым альтернативным способом отбрасывания контента до следующей новой строки, но он рискует выбросить не-whitespace и при этом игнорируя поврежденные данные в файле. Вам может или не все равно, в зависимости от того, доверено ли содержимое файла, насколько важно избегать обработки поврежденных данных и т. Д.
Таким образом, std::cin.clear()
(и std::cin.igore()
) для этого не требуется, но полезно для удаления состояния ошибки. Например, если вы хотите дать пользователю много шансов ввести действительный номер.
int x;
while (std::cout << "Enter a number: " &&
!(std::cin >> x))
{
if (std::cin.eof())
{
std::cerr << "ERROR unexpected EOF\n";
exit(EXIT_FAILURE);
}
std::cin.clear(); // clear bad/fail/eof flags
// have to ignore non-numeric character that caused cin >> x to
// fail or there's no chance of it working next time; for "cin" it's
// common to remove the entire suspect line and re-prompt the user for
// input.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
Еще одна простая, но наполовину испеченная альтернатива ignore
для вашего первоначального требования использует std::skipws
, чтобы пропустить любое количество пробелов перед чтением строк ...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
... но если он вводится как «1E6» (например, какой-то ученый пытается ввести 1 000 000, но C ++ поддерживает эту нотацию для чисел с плавающей запятой ) не согласятся с этим, вы получите number
, установленный на 1
, и E6
считанные как первое значение name
. Отдельно, если у вас есть действительное число, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться молча.
Я только использовал
getline(cin >> ws,lard.i_npute);
со стандартным заголовком
#include <iostream>
в случаях, когда у меня возникали проблемы с возвратом каретки и работал с манипулятором ws. Я, вероятно, начну встраивать функции цикла в классы и использовать вызовы конструктора и деструктора atleast.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);//works on the \n left behind
getline(cin, names);//continues and rewrites names
его довольно самообучающийся, в потоке, который используется cin >> number
, есть\n, который присваивается именам при первом использовании. Повторное использование getline теперь записывает правильное значение.
cout << "Enter the number: ";
int number;
cin >> number;
cin.ignore(256, '\n'); // remaining input characters up to the next newline character
// are ignored
cout << "Enter names: ";
string names;
getline(cin, names);
Другой способ сделать это - поставить
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
после того, как ваш cin>>number;
полностью очистит входной буфер (отклонение всех дополнительных символов до тех пор, пока не будет найдена новая строка). Вы должны #include <limits>
получить метод max()
.
вы хотите использовать cin.ignore () после своих операторов cin, потому что вы хотите игнорировать «\n» слева в буфере после принятия переменной int cin.
У меня есть аналогичная программа я использовал с аналогичной проблемой:
#include <iostream>
#include <iomanip>
#include <limits>
using namespace std;
int main() {
int i = 4;
double d = 4.0;
string s = "HackerRank ";
// Declare second integer, double, and String variables.
int n;
double d2;
string str;
// Read and save an integer, double, and String to your variables.
cin >> n;
cin >> d2;
cin.ignore();
getline(cin, str);
// Print the sum of both integer variables on a new line.
cout << i + n << endl;
// Print the sum of the double variables on a new line.
cout << d + d2 << endl;
// Concatenate and print the String variables on a new line
cout << s << str << endl;
// The 's' variable above should be printed first.
return 0;
}
Попробуйте:
int number;
cin >> number;
char firstCharacterOfNames;
cin >> firstCharacterOfNames; // This will discard all leading white space.
// including new-line if there happen to be any.
cin.unget(); // Put back the first character of the name.
std::string names;
std::getline(cin, names); // Read the names;
Альтернативно. Если вы знаете, что число и имена всегда будут на разных строках.
cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(cin, names);
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
// USE peek() TO SOLVE IT! ;)
if (cin.peek() == '\n') {
cin.ignore(1 /*numeric_limits<streamsize>::max()*/, '\n');
}
getline(cin, names);
return 0;
}
Просто загляните вперед, используя cin.peek()
, и посмотрите, остается ли '\n'
во внутреннем буфере cin
. Если да: проигнорируйте его (в основном пропустите его)
Концептуально, я думаю, вы хотите, чтобы каждый ответ был аккуратно одной строкой. Итак, почему бы вам не попробовать это?
cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);
cout << "Enter names: ";
string names;
getline(cin, names);
Код правильно использует первый символ новой строки, дает номер, если строка верна или выбрасывает исключение, если это не так. Все бесплатно!
Или вы можете очистить входной буфер, чтобы прочитать строку
fflush (stdin)
blockquote>, она определена в заголовке stdio.h .
Этот код работает ..
cout << "Enter the number: "; int number; cin >> number; cout << "Enter names: "; string names; fflush(stdin); //FLUSHING STDIN getline(cin, names);
Вы можете использовать std :: ws для извлечения любых пробельных символов во входном буфере перед использованием getline. Заголовок для std :: ws является sstream.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
Вы можете найти ответ, который вы хотите найти в cppreference .
При использовании сразу после ввода с разделителями-пробелами, например. после
blockquote>int n; std::cin >> n;
, getline потребляет символ конца, оставленный на входном потоке оператором >>, и немедленно возвращается. Общее решение состоит в том, чтобы игнорировать все оставшиеся символы в строке ввода сcin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
перед переключением на линейно-ориентированный вход.