while(true)
{
unsigned int option;
cout<<"1 - Display the list\n";
cout<<"2 - Add a game title to the list\n";
cout<<"3 - Remove a game title from the list\n";
cout<<"4 - Exit\n";
cin>>option;
if(option == 1)
{
if(gameTitles.empty())
{
cout<<"\nThere are no games to be displayed. Please try again after adding some games to the list.\n";
}
else
{
for(iter = gameTitles.begin(); iter != gameTitles.end(); ++iter)
{
cout<<*iter<<endl;
}
}
}
else if(option == 2)
{
cout<<"\nEnter the game title:\n";
cin>>newGame;
gameTitles.push_back("newGame");
}
else if(option == 3)
{
cout<<"\nEnter a game to be removed:\n";
cin>>removeGame;
theIterator = find(gameTitles.begin(),gameTitles.end(),removeGame);
theIterator = gameTitles.erase(theIterator);
}
else if(option == 4)
{
break;
}
else
{
cout<<"\nThe option is illegal. Please try again.\n";
}
}
Когда я выбираю какой-либо 1, 3, 4 или незаконный вариант, цикл возвращает меня к вершине, и у меня есть возможность снова выбрать. Проблема возникает, когда я пытаюсь использовать второй вариант. Я просто вхожу в бесконечный цикл. Но я хочу ввести название игры и после того, как он будет добавлен в мой вектор (я объявил его ранее), а затем у вас есть возможность снова выбрать вариант.
Вы не показываете тип newGame
но я бы предположил, что он имеет тип std::string
и вы вводите заголовок двумя словами: поток читает первое слово и перестает читать. Следующее, что вы делаете, - это прочитать int
который терпит неудачу и оставляет значение option
неизменным. С этого момента поток ничего не сделает и просто продолжает читать.
Ключевая ошибка не проверяет, что попытка чтения была успешной, прежде чем использовать результат: вам всегда нужно проверить, что ваш ввод был успешным после прочтения и перед использованием результата. Когда операция ввода не работает, поток переходит в режим сбоя, т. std::ios_base::failbit
получает значение, и он преобразуется в false
вместо true
(ну, фактически, он преобразуется в нулевой указатель против ненулевого указателя, но что деталь не имеет отношения к этому обсуждению). Когда-то в состоянии сбоя поток ничего не сделает, пока не будет clear()
ed. Вам, вероятно, также необходимо ignore()
нарушающие символы.
То есть, вы, безусловно, должны использовать что-то вроде
if (std::cin >> option) {
// do something with the option
}
else {
std::cout << "expected an integer: ignoring the line\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Чтобы прочитать заголовок, вы, вероятно, должны прочитать целую строку. Так как форматированный вход для option
оставит символ новой строки в потоке, вам сначала нужно будет пропустить этот символ. То есть вход для нового заголовка будет выглядеть примерно так:
if (std::getline(std::cin >> std::ws, newGame)) {
// ...
}
Манипулятор std::ws
пропускает все ведущие пробелы. Это, вероятно, хорошо для ваших нужд. Если прочитанная строка может иметь ведущие символы пробела, потребуется другое.
Перед тем, как попытаться снова newgame
на ту же переменную newgame
, cin.ignore()
. Если я правильно помню, первый раз, когда вы ссылаетесь на строку (я предполагаю, что newgame - это строка), она оставляет конечную \n
поэтому она будет просто автоматически вводиться в последующих приглашениях.
gameTitles.push_back("newGame")
switch
?