Если операторы в цикле do while с окончанием да или нет
Я новичок в кодировании, и я пытаюсь сделать длинный do while
цикл с вложенным if
заявления, но у меня есть проблемы с получением моего цикла на самом деле цикл.
Вместо того, чтобы получать помощь непосредственно в моем проекте, который имеет очень длинный код, я сделал простую версию, похожую на эту. Это также не зацикливается. Он доберется до конца и спросит пользователя, не хотят ли они повторить попытку, но когда введено "y", он игнорирует операторы if.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string sodaChoice;
char answer = 'n';
do
{
cout << "Please choose your favorite soda from the following: Rootbeer, Diet Coke, Coke, Sprite" << "\n";
getline(cin, sodaChoice);
if (sodaChoice == "Rootbeer")
{
cout << "Me too!" << "\n";
}
else if (sodaChoice == "Diet")
{
cout << "Not me :(" << "\n";
}
else if (sodaChoice == "Coke")
{
cout << "It's alright" << "\n";
}
else if (sodaChoice == "Sprite")
{
cout << "only if I'm sick" << "\n";
}
else
{
cout << "That was not on the list";
}
cout << "would you like to try again?";
cin >> answer;
} while (answer == 'y'|| answer == 'Y');
return 0;
}
Я подумал, что, возможно, мне нужен цикл do в цикле do вокруг операторов if, но тогда я не знал, как это сделать. Любая помощь будет оценена. Я потратил много-много часов, пытаясь понять это.
Я пытался спросить своего учителя, но мой колледж преподает из некоторой общей учебной программы, которую их декан написал на основе ее книги. Он не очень любит помогать или учить.
РЕДАКТИРОВАТЬ: Спасибо всем за ответы! Что касается дублирующего вопроса, я еще не изучил cin.ignore, поэтому я не знал, что он имеет отношение к моей проблеме. Спасибо всем за то, что научили меня!
4 ответа
С
cin >> answer;
вы читаете ровно один символ Проблема в том, что при вводе ответа вы ввели как минимум два символа. Настоящий 'y'
или же 'n'
плюс клавиша Enter, которая добавляется в качестве новой строки в буфере ввода.
Эта новая строка затем читается следующим getline
позвонить как пустая строка.
Есть несколько решений этой проблемы, например, с помощью ignore
после прочтения в answer
, Или, если вы хотите вводить только одним словом, вы можете использовать форматированный ввод, используя >>
за sodaChoice
также, так как по умолчанию он пропускает начальные пробелы (как переводы строк).
Существующие ответы верны в том случае, если пользователь ведет себя хорошо и вводит только "y" или "n", а затем перевод строки.
Мы можем добавить немного безопасности с модификацией к вызову.ignore(), попросив его игнорировать все символы вплоть до следующего символа новой строки:
Вам нужно будет добавить этот заголовок в верхней части вашего блока перевода:
#include <limits>
И вам нужно будет добавить эту строку, прежде чем cin >> answer
:
// consumes and ignores as many characters as necessary until a newline.
// The newline is also consumed.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Полная программа с тестовыми входами здесь:
http://coliru.stacked-crooked.com/a/996e77559590ad6d
К сожалению, учителя информатики нередко ничего не знают о компьютерных науках. Не беспокойтесь об этом и не позволяйте этому научиться писать программы - это всего лишь признак того, что хорошим программистам платят намного больше, чем хорошим учителям.
Вот несколько полезных справочных материалов: https://en.cppreference.com/w/cpp/io/basic_istream/ignore
Я собираюсь предложить что-то совершенно противоположное другим ответам. Вместо того, чтобы использовать cin.ignore
чтобы пропустить лишние символы после того, который вы прочитали, я думаю, что лучше читать все с getline()
и забыть о cin >> somevar
полностью.
Есть две причины:
Форматированный ввод, который вы получаете с
cin >> somevar
игнорирует начальные пробелы, включая переводы строки. Если пользователь нажимает Enter в пустой строке, программа ничего не делает, но все же ожидает дальнейшего ввода. Это не то, что ожидает пользователь программы CLI! Обычное ожидание состоит в том, что ввод завершает ввод, и пустой ввод должен либо заставить программу использовать значение по умолчанию, либо жаловаться на неверный ввод. Сcin >> somevar
Вы тоже не можете.Форматированный ввод оставляет любые несогласованные входные данные в буфере. В вашем примере чтение одного символа оставляет по крайней мере следующую новую строку, но то же самое происходит с другими видами ввода. Чтение числа (с
int i; cin >> i;
) оставляет после числа число, ожидающее следующей операции ввода, поэтому ввод123 abc
вернусь123
иabc
появится на следующей операции ввода.Основная причина этого заключается в том, что по умолчанию терминал командной строки находится в режиме строки. Программа или библиотечные функции не видят никакой информации от операционной системы до тех пор, пока не будет введена полная строка. (
cin.ignore()
может конечно помочь вам разобраться с этим, но не с первого пункта.)
С помощью getline()
точно соответствует основной механике, позволяет работать с пустыми входами (а также сообщать разницу между нулем и не числом при чтении в int
) и автоматически обрабатывает завершающий мусор. Вы должны будете преобразовать прочитанную строку вручную в то, что вам нужно.
В вашем случае вы можете тривиально изменить условие цикла на что-то вроде этого:
string answer;
...
getline(cin, answer);
} while (answer == "y" || answer == "Y");
Если вам нужен номер, вы можете использовать, например, int num = std::stoi(str)
,
(В C то же самое происходит при использовании scanf()
для пользовательского ввода, и аналогично, лучше использовать fgets()
а затем проанализировать строку с sscanf()
, который дает те же параметры, но имеет дело с буферизацией строки. Я не слишком знаком с C++, поэтому я не могу сказать, как получить точный эквивалент cin >> somevar
с полной строкой, прочитанной getline()
.)
Поскольку вы принимаете ввод от пользователя типа char
но каждый Enter
нажатие клавиши, назначает новую строку (\n
) к переменной answer
,
Вы можете игнорировать это, добавив строку сразу после строки ввода
cin.ignore();
Вы можете прочитать это для более подробной информации.