Если утверждения в цикле do while с да или нет

Я новичок в кодировании, и я пытаюсь сделать цикл do while 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 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, но потом я не знал, как это сделать. Любая помощь будет оценена по достоинству. Я потратил много и много часов, пытаясь понять это.

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

EDIT: Спасибо всем за ответы! Что касается дублирующего вопроса, я еще не изучил cin.ignore, поэтому я не знал, что это имеет отношение к моей проблеме. Спасибо всем, что учил меня!

Ответ 1

С

cin >> answer;

вы читаете ровно один символ. Проблема заключается в том, что вы ввели по крайней мере два символа при написании ответа. Фактические 'y' или 'n' плюс клавиша Enter, которая добавляется как новая строка во входном буфере.

Эта новая строка затем считывается следующим вызовом getline как пустая строка.

Существует несколько решений этой проблемы, например, ignore после чтения в answer. Или, если вам нужны только однословные входы, вы можете использовать форматированный вход, используя >> для sodaChoice, так как он по умолчанию пропускает ведущее белое пространство (например, строки новой строки).

Ответ 2

Существующие ответы правильны в случае хорошего поведения пользователя и ввода только "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

Ответ 3

Я собираюсь предложить что-то совершенно противоположное другим ответам. Вместо использования cin.ignore для пропуска любых дополнительных символов после того, как вы читаете, я думаю, что лучше всего делать все ваши чтения с помощью getline() и полностью забыть о cin >> somevar.

Есть две причины:

  1. cin >> somevar вход, который вы получаете с помощью cin >> somevar игнорирует ведущие пробелы, включая символы новой строки. Если пользователь нажимает Enter на пустой строке, программа ничего не делает, но все же ожидает дальнейшего ввода. Это не то, что ожидает пользователь программы CLI! Обычное ожидание состоит в том, что Enter завершает ввод, а пустой ввод должен либо заставлять программу использовать значение по умолчанию, либо жаловаться на недопустимый ввод. С cin >> somevar вы тоже не можете.

  2. Отформатированный вход оставляет любой несогласованный вход в буфер. В вашем примере чтение одного символа оставляет по крайней мере следующую новую строку, но то же самое происходит с другими видами ввода. Чтение числа (с 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(), которая дает те же параметры, но имеет дело с буферизацией строк. m не слишком знакомы с C++, поэтому я не могу сказать, как иметь точный эквивалент cin >> somevar с полной строкой, читаемой getline().)

Ответ 4

Так как вы берете ввод от пользователя типа char но каждый раз нажимаете Enter, он назначает новую строку (\n) answer переменной.

Вы можете проигнорировать это, добавив строку сразу после строки ввода

cin.ignore();

Вы можете прочитать это для более подробной информации.