Я хочу, чтобы моя программа распознавала, когда пользователь нажимает «ввод», и продолжает цикл. Но я не могу понять, как заставить программу идентифицировать «ввод». Пробовал двумя способами:
string enter;
string ent = "\n";
dice d1;
cout << "To start - Press enter" << endl;
getline (cin, enter);
while (enter == ent)
{
d1.throw_dice();
d1.draw_dice();
cout << "Try again, press enter" << endl;
getline (cin, enter);
}
cout << "Thank you for playing"<< endl;
И этот:
string enter;
dice d1;
cout << "To start - Press any key and enter" << endl;
getline (cin, enter);
while (enter == "\n")
{
d1.throw_dice();
d1.draw_dice();
cout << "Try again, press enter" << endl;
getline (cin, enter);
}
cout << "Thank you for playing"<< endl;
Я знаю, что строка выбрасывает «\ n», но не могу найти способ обойти это.
PS:
Я нашел решение. Но я все еще чувствую, что должен быть лучший вариант.
while (cin.get() == '\n')
{
d1.throw_dice();
d1.draw_dice();
cout << "Try again, press enter! Or press any other key and enter" << endl;
if (cin.get() != '\n')
break;
}
cout << "Thank you for playing"<< endl;
return 0;
}
В первых двух случаях есть две проблемы с использованием getline
для ввода, если вы пытаетесь обнаружить нажатие ввода (хотя то, что вы на самом деле обнаруживаете, — это новая строка, и нажатие клавиши ввода не единственный способ, который может быть сгенерирован, хотя обычно он наиболее прост). Во-первых, как вы сказали, что угодно getline
использует в качестве разделителя, он будет исключен из входных данных, которые он читает, так что вы не сможете включить в него новые строки, используя их без усложнения. Второе, однако, это то, что любые символы, введенные до новой строки, также будут включены в строку getline
извлекается, поэтому просто сравнивать со строкой "\n"
не сказал бы, если новая строка была прочитана даже getline
сохранить разделитель, которого нет.
Другой проблемой, конечно же, является то, что в идеале вы хотите проверить, чтобы убедиться, что входной поток cin
не находится в состоянии ошибки, когда вы читаете из него. При условии, что это не так, getline
должен продолжаться только после того, как он получил новую строку ввода.
В принципе, это говорит о том, что (если вы не возражаете против способов ввода новой строки без ввода ключа, когда ввод принимается в качестве нажатия клавиши ввода), если вы выполняете надлежащую проверку ошибок, вам вообще не нужно проверять саму строку, чтобы узнать клавиша ввода была нажата — если getline
прекратил блокировку ввода и не столкнулся с ошибкой (я включаю конец файла в «error» здесь, как в флагах состояния потока), он прочитал разделитель, который в вашем случае является символом новой строки. Таким образом, вы можете использовать блокирующее поведение getline(cin, enter)
чтобы управлять потоком управления, хотя для выхода из цикла вам все равно необходимо проверить, не было ли введено что-то кроме символа новой строки (или был ли введен конец файла или произошла ошибка, проверив флаги состояния на cin
).
С cin.get()
метод, который вы используете в третьем случае, вы можете получить символы новой строки, в отличие от getline
— хотя предоставляемый вами код требует двух нажатий на ввод для каждой итерации цикла после первой, а не один (что, я сомневаюсь, было вашим намерением). Отдельная условная break
регистр не должен быть необходим, и условие цикла должно быть достаточным (в случае сбоя no-args std::istream::get()
возвращает EOF
значение, которое не будет равно \n
так что ваш цикл выходит в этом случае). Другими словами,
while (cin.get() == '\n') {
d1.throw_dice();
d1.draw_dice();
cout << "Try again, press enter! Or press any other key and enter" << endl;
}
Должен обеспечивать поведение нажатия enter после одной итерации цикла, ведущей непосредственно к следующей, вместо необходимости нажимать ее дважды.
У вас все еще остается немного неуклюжий синтаксис «введите какой-то другой символ, затем введите, чтобы выйти», но это частично является результатом ограничений ввода с буферизацией строки (например, типичного терминала командной строки). С помощью приведенного выше цикла вы также можете сразу выйти (без нажатия клавиши ввода), введя комбинацию клавиш вашей платформы для конца файла (различается, но в системах на основе UNIX обычно CTRL+D
), но если вы хотите продвинуться гораздо дальше, чем этот, к общему интерактивному вводу с клавиатуры (чтобы все происходило непосредственно при нажатии клавиш вместо ввода построчного текста) в среде командной строки, это может быть намного больше сложнее, чем кажется, что объем этой программы, и обычно требует внешних библиотек и / или поддержки конкретной платформы. Если вы хотите углубиться в это для C ++, вы можете взглянуть на некоторые ответы на этот вопрос.
Другими словами, в общем случае есть лучшие варианты для обнаружения нажатий клавиш для интерактивной программы командной строки, чем cin.get()
, но они могут стать значительно более вовлеченными, если вы хотите обнаружить нажатие клавиш, отличных от ввода, и получить немедленный ответ (вместо ожидания другого ввода). Есть и другие варианты обработки ввода, кроме cin.get()
а также getline()
доступны в базовом, независимом от платформы C ++, но, насколько мне известно, все они столкнутся с такой проблемой — фактом, что cin
не становится доступным во входном потоке до конца строки — без использования кода, специфичного для платформы (или внешних библиотек, содержащих код, специфичный для платформы), чтобы изменить этот факт или иным образом обойти его.
Других решений пока нет …