2017-02-09 10 views
3

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

Но когда вы вводите несколько символов, он повторяет те же самые cout заявления снова и снова. Например, если я набрал «qwerty», он будет выводить эти операторы cout` 6 раз, когда я хочу, чтобы он запускался один раз.

код ниже:

#include <iostream> 
using namespace std; 
int main(){ 
    // Declare the variables 
    int choice = 0; 
    bool valid = false; 

    while(!valid){ 

    valid = true; 
    //Ask the user for their choice 
    cout << "Which function would you like to use? \n"; 
    cout << "1) Average Function \n"; 
    cout << "2) Mean Absolute Deviation Function \n"; 
    cout << "3) Number Sorting Function \n"; 
    cout << "4) Median Function \n"; 
    cout << "5) All of the above \n"; 
    cout << "6) Calculator Function \n"; 
    cout << "Your choice: "; 
    cin >> choice; 

     if(cin.fail() || choice > 6 || choice < 1){ 
      cout << "ERROR, PLEASE ENTER ONLY VALID SYMBOLS \n"; 
      cout << "--------------------- \n"; 
      valid = false; 
      cin.clear(); 
      cin.ignore(); 
     } 

    } 
} 
+0

Что вы обнаружили при выполнении этого кода в отладчике? –

+0

Я не уверен, как использовать отладчик:/ – PeteMcGreete

+2

@PeteMcGreete при отсутствии навыков отладчика, просто приклеивая несколько «куттов», поможет вам понять поток управления и значения переменных на определенных этапах выполнения программ , Конечно, стоит научиться использовать отладчик, хотя и быстрее, и вам не нужно возвращаться через ваш код, вырывая инструкции 'cout'. –

ответ

2

зацикливание происходит потому, что у вас есть осталось символов в вашем cin буфере после извлечения одного. Поэтому, если вы наберете querty<enter>, после обработки q у него есть uerty\n для обработки. Затем он петли, потому что он не нашел входное значение, которое удовлетворяет вашему условию choice > 6 || choice < 1 и пытается выполнить другое извлечение символов. Он может делать это 6 раз, пока буфер не будет пуст, и будет установлен флаг cin.fail().

Альтернативный подход состоит в том, чтобы прочитать всю строку в виде строки и извлечь целое число из строки.

#include <iostream> 
#include <sstream> 
#include <string> 
using namespace std; 

int displayUserInstructions(){ 

    string line; 

    while(true){ 

     cout << "Which function would you like to use? \n"; 
     cout << "1) Average Function \n"; 
     cout << "2) Mean Absolute Deviation Function \n"; 
     cout << "3) Number Sorting Function \n"; 
     cout << "4) Median Function \n"; 
     cout << "5) All of the above \n"; 
     cout << "6) Calculator Function \n"; 
     cout << "Your choice: "; 

     if(getline(cin, line)){ 

      stringstream ss(line); 
      int choice; 

      if(ss >> choice && (choice >= 1 && choice <= 6)){ 

       return choice; 
      } 

      cout << "ERROR, PLEASE ENTER ONLY VALID SYMBOLS \n"; 
      cout << "--------------------- \n"; 
     } 
    } 
} 

int main() 
{ 
    int choice = displayUserInstructions(); 
    cout << "You made the valid choice of " << choice << '\n'; 
} 
2

Когда вы вводите «qwerty», это означает, что в буфере ввода есть шесть символов, ожидающих чтения. Ваш код пытается прочитать целое число с использованием cin >> choice, но считает, что оно не является допустимым целым числом и поэтому печатает ошибку, очищает состояние потока, отбрасывает один символ и перезапускает цикл. Затем он считывает следующий символ: 'w', который не является допустимым целым числом, поэтому он печатает ошибки и отбрасывает один символ и перезапускается.

Вы можете решить эту проблему путем отбрасывания все до следующего символа новой строки:

cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Это будет отбрасывать все символы до конца строки, вместо того, чтобы пытаться сохранить чтение целых чисел от плохого ввода ,

В качестве альтернативы, вы можете прочитать всю строку сразу и попытаться извлечь из нее целое число (как показано в ответе Павла Руни). Оба должны работать одинаково хорошо, хотя в зависимости от того, что вы хотите сделать дальше в программе, одно или другое решение может быть более гибким. Одно решение читает целую строку, затем пытается извлечь из нее целое число (и игнорирует остальную часть строки). Другое решение пытается извлечь целое число сначала и отбрасывает строку на ошибке (и если нет ошибки, остальная часть строки все еще доступна для чтения).