Использование getline (cin, s) после cin
Мне нужна следующая программа, чтобы взять всю строку ввода пользователя и поместить ее в имена строк:
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);
Если команда cin >> number
перед командой getline()
(что я предполагаю, это проблема), она не позволит мне вводить имена. Почему?
Я слышал что-то о команде cin.clear()
, но я понятия не имею, как это работает или почему это даже необходимо.
Ответы
Ответ 1
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?
Это довольно многословно, поэтому использование ignore
в потоке после >> x
является часто рекомендуемым альтернативным способом отбрасывания содержимого до следующей новой строки, но он рискует выбросить не-пробельный контент и при этом игнорировать поврежденные данные в файле. Вы можете или не должны заботиться, в зависимости от того, доверено ли содержимое файла, насколько важно избегать обработки поврежденных данных и т.д.
Итак, когда вы будете использовать clear и игнорировать?
Итак, 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 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());
}
Не может быть проще с skipws или схожим?
Другая простая, но наполовину испеченная альтернатива ignore
для вашего первоначального требования - использовать std::skipws
, чтобы пропустить любое количество пробелов перед чтением строк...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
... но если он вводится как "1E6" (например, какой-то ученый пытается ввести 1 000 000, но С++ поддерживает только эту нотацию для чисел с плавающей запятой) не согласится с тем, что вы закончите с помощью number
set до 1
и E6
считать первым значением name
. Отдельно, если у вас есть действительное число, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться.
Ответ 2
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);
Ответ 3
Другой способ сделать это - поставить
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
после вашего cin>>number;
полностью очистить входной буфер (отклонение всех дополнительных символов до тех пор, пока не будет найдена новая строка). Вам нужно #include <limits>
получить метод max()
.
Ответ 4
Try:
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);
Ответ 5
Вы можете использовать std:: ws для извлечения любых пробельных символов во входном буфере перед использованием getline. Заголовок для std:: ws является sstream.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
Ответ 6
Или вы можете очистить входной буфер, чтобы прочитать строку
fflush (STDIN)
он определен в заголовке stdio.h.
Этот код работает.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
fflush(stdin); //FLUSHING STDIN
getline(cin, names);
Ответ 7
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
его довольно самообучающийся, есть \n, оставленный в потоке, который использует cin >> number
, который присваивается именам в первый раз, когда он используется. Повторное использование getline теперь записывает правильное значение.
Ответ 8
Вы можете найти ответ, который вы хотите в cppreference.
При использовании сразу после ввода с пробелом, например, после int n; std::cin >> n;
, getline потребляет символ конца строки слева от входного потока оператором → и немедленно возвращается. Общим решением является игнорирование всех оставшихся символов на линии ввода с помощью cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
перед переключением на линейно-ориентированный ввод.
Ответ 9
вы хотите использовать 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;
}
Ответ 10
Я просто использовал
getline(cin >> ws,lard.i_npute);
со стандартным
#include <iostream>
в тех случаях, когда у меня возникли проблемы с возвратом каретки и работал ws-манипулятор. Я, вероятно, начну встраивать циклические функции в классы и использовать вызовы конструктора и деструктора atleast.
Ответ 11
Концептуально, я думаю, вы хотите, чтобы каждый ответ был аккуратно одной строкой. Так почему бы вам не попробовать это?
cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);
cout << "Enter names: ";
string names;
getline(cin, names);
Код правильно потребляет первый символ новой строки, дает номер, если строка верна или выбрасывает исключение, если это не так. Все бесплатно!
Ответ 12
#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
внутреннем буфере. Если это так: игнорировать его (в основном пропустить)