2014-12-17 3 views
0

Итак, я показываю меню, используя цикл do while, как показано ниже, и я хочу, чтобы пользователю было предложено меню, пока они не сделают действительный выбор ввод цифр 1, 2, 3 или 4. Затем я хочу использовать оператор case switch для идентификации пользователя и выполнения соответствующего блока кода. Однако, когда дело доходит до проверки ввода, как я могу объяснить, что пользователь вводит букву вместо числовой цифры? В приведенном ниже коде успешно продолжается следующая итерация, чтобы перепрограммировать пользователя при вводе буквы, за исключением того, что он входит в непрерывный цикл.Застрял в бесконечном цикле при проверке ввода пользователя как int

int selection; 

do{ 
    cout << "Which option would you like to select? (select 1, 2, or 3)"; 
    cout << "1: Option 1" << endl; 
    cout << "2: Option 2" << endl; 
    cout << "3: Option 2" << endl; 

    if(!(cin >> selection)){ 
     cout << "Please select an integer from 1-4." << endl; 
     cin.clear() 
    } 

}while(selection != (1) or (2) or (3) or (4)); 

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

string temp; 
cin >> temp; 
clearInputBuffer(); 
istringstream is(temp); 
is >> selection; 

ОБНОВЛЕНО КОД - по-прежнему получать бесконечную петлю (только тогда, когда пользователь вводит алфавитный
характер; целые числа behaveas ожидаемый)

int selection; 

do{ 
    cout << "Which option would you like to select? (select 1, 2, or 3)"; 
    cout << "1: Option 1" << endl; 
    cout << "2: Option 2" << endl; 
    cout << "3: Option 2" << endl; 

    if(std::cin >> selection){ 
     cout << "Enter the new price: "; 
    } 

    else if(!std::cin.eof()){ 
     cout << "Please select an integer from 1-4." << endl; 
     cin.clear(); 
    } 


    }while(selection != 1 && selection != 2 && selection != 3 && selection != 4); 
+5

Я уверен, вы не знаете, что 'выбор! = (1) или (2) или (3) или (4)' 'означает –

+0

что-нибудь или true' всегда' true'. – juanchopanza

ответ

1

Очевидный подход на самом деле проверить, что вход был успешным, и если это не так, дело с ошибкой, например, написать сообщение об ошибке, очистить поток, игнорировать символ или строку, и попробуйте еще раз:

if (std::cin >> selection) { 
    // do something with the good selection 
} 
else if (!std::cin.eof()) { 
    std::cin.clear(); 
    std::cout << "invalid character ('" << char(std::cin.get()) << "') ignored\n"; 
} 

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

Вы бы, если не продолжить и проверить диапазон. Ваш подход не совсем работает, так как логика или оператор оценивают каждый отдельный элемент. Один из способов проверить, если введенное значение является членом определенного rnage, например, с помощью

int const valid[] = { 1, 2, 3, 4 }; 
if (std::end() == std::find(std::begin(valid), std::end(valid), selection)) { 
    std::cout << "chosen invalid selection (" << selection << ")\n"; 
} 

альтернативы проверки каждого выбора по отдельности может быть жизнеспособными для небольшого количества выбора, но на самом деле не жизнеспособен, когда диапазон опций растет. Правда, как только у вас есть больший диапазон возможностей вы на самом деле положил ключ и работу вместе в любом случае:

std::unordered_map<int, std::function<void()>> actions; 
bool done = false; 

// set up different operations for the respective actions, e.g.: 
actions.insert(std::make_pair(1, [](){ std::cout << "hello, world\n"; })); 
actions.insert(std::make_pair(2, [&](){ done = true; std::cout << "goodbye\n"; })) 

int selection; 
if (std::cin >> selection) { 
    auto it = actions.find(selection); 
    if (it != actions.end()) { 
     (it->second)(); 
    } 
    else { 
     std::cout << "unknown action selection " << selection << '\n'; 
    } 
} 
5
while(selection != (1) or (2) or (3) or (4)); 

синтаксически действительна, хотя вы, скорее всего, захотите

while(selection != 1 && selection != 2 && selection != 3 && selection != 4); 

Ваше оригинальное выражение эквивалентно

while((selection != 1) || (2) || (3) || (4)) 

(2), (3) и (4) оцениваются истина, что делает ваш цикл бесконечен, потому что anything || true является true.

Если кто-то должен быть интересно, да, C++ позволяет писать and вместо && и or вместо || и not вместо ! и т.д. Вы должны «Отключить расширения языка», чтобы увидеть это на MSVC.

[обновление]

Другая проблема заключается в том, что в случае нецелых ввода, переменная выбора остается инициализирована. В клаве else дайте ему, например, значение -1.

+0

Ах да, спасибо @Armen Tsirunyan - эта ошибка выглядит невероятно очевидной сейчас, когда мне было указано. Я обновил свой код выше, чтобы отразить эти и некоторые другие изменения, однако я все еще застрял в бесконечном цикле, когда пользователь вводит алфавитный символ –

+0

@greavedoggy: обновлено. Помогло ли обновление? –

+0

Хорошо, что поведение по-прежнему остается таким же, как и до обновления, однако я вижу, как мое состояние было ошибочным, поэтому я уверен, что по крайней мере часть обновления поможет, хотя это не отражается на выходе кода как все же. –

0

Попробуйте это

while(selection != (1) and selection != (2) and selection != (3) and selection != (4)); 
0
selection != (1) or (2) or (3) or (4) 

ненулевые целые числа будут вычисляться true, так что это эквивалентно:

(selection != (1)) or true or true or true 

, который всегда будет вычисляться true.

Путь, чтобы исправить это сравнить каждый индивидуально

while(selection != 1 && selection != 2 && selection != 3 && selection != 4) 
0

(2), (3, (4) всегда верно, поэтому вы застряли в бесконечном такт.попробуйте:

while(selection != 1 && selection != 2 && selection != 3 and selection != 4); 
0

Сокращенный вариант:

while (selection <= 4 && selection >= 1) 
+0

Это неправильно, потому что выражение всегда верно. – Jesper

+0

Действительно. Я исправил выражение –

0

Я получил его на работу, обновление при условии в исходном сообщении отсутствовала одна дополнительная строка кода, которую я идентифицировал от просеивания по другим вопросам, касающимся проверки ввода в цикле while. Я думаю, @Dietmar Kühl попытался проиллюстрировать что-то подобное в своем предложении, однако моему компилятору не понравился код, и я не совсем понял его, поэтому не был уверен, как заставить его работать. Я буду играть с вашим предложением относительно проверки на диапазон, хотя Dietmar, так что спасибо за ваш вклад.

Спасибо также всем, кто внес свой вклад в эту тему, особенно 99% из вас, которые сделали это без звучания снисходительно :-) Там всегда один. Поток, из которого я идентифицировал мой отсутствующий оператор, можно найти here, а строка, добавленная в код, идентифицируется комментарием в коде ниже. Еще раз спасибо!

int selection; 

do{ 
    cout << "Which option would you like to select? (select 1, 2, or 3)"; 
    cout << "1: Option 1" << endl; 
    cout << "2: Option 2" << endl; 
    cout << "3: Option 2" << endl; 

    if(std::cin >> selection){ 
     cout << "Enter the new price: "; 
    } 

    else if(!std::cin.eof()){ 
     cout << "Please select an integer from 1-4." << endl; 
     cin.clear(); 
     cin.ignore(10000,'\n'); // this line eliminated the infinite loop issue 
    } 


}while(selection != 1 && selection != 2 && selection != 3 && selection != 4); 
Смежные вопросы