2013-04-25 3 views
0
#include <iostream> 
using namespace std; 
int main() 
{ 
    int a; 
    do 
    { 
     /* First reset the flag and then clean the buffer*/ 
     cin.ignore(); 
     cin.clear(); 
     /* Input the number from the user*/ 
     cout << "Enter number\n"; 
     cin >> a; 
     /*Diplay appropiate error if the input was wrong*/ 
     if(cin.fail()) 
     { 
      cout << "invalid input \n"; 
     } 
     /*Display the number if the input was valid*/ 
     else 
     { 
      cout << "number entered is : " << a << endl; 
     } 
    } 
    while(cin.fail()); //repeat until the input is correct 
    return 0; 
} 

Каждый раз, когда я запускаю эту программу, я должен сначала ввести новую строку, а затем выполнить cout<<"Enter number\n";.Необходим дополнительный символ новой строки

Какова будет причина этого и каково возможное решение.

Примечание: Без cin.ignore() программа входит в бесконечный цикл

+0

Вы являетесь слишком щедро с вашим разбрызгиванием 'cin.ignore();'. –

ответ

0

Edited следующие комментарии:

cin.ignore() ожидает некоторый входной сигнал и просто игнорирует его. Вы должны перенести эту строку в оператор if после cout << "invalid input \n";.

+0

Без 'cin.ignore' код входит в цикл infinte – debal

+0

Потому что вы вызываете cin.fail() дважды! В инструкции else вы должны добавить «break» для выхода из цикла. –

+0

@BenoitThiery Это неверно. Вы можете вызывать 'cin.fail()' так часто, как вам нравится (и если нет промежуточного ввода, вы получите одинаковое значение). Это то, что он получил правильно. –

0
cin.ignore(); 
    cin.clear(); 
    /* Input the number from the user*/ 
    cout << "Enter number\n"; 
    cin >> a; 

в

/* Input the number from the user*/ 
    cout << "Enter number\n"; 

    cin.clear(); 
    cin.ignore(); 
    cin >> a; 
+0

Которая по-прежнему игнорирует хотя бы один символ, поэтому, если пользователь вводит «42», он отобразит «2». (И если пользователь вводит '' abc "', он будет циклироваться четыре раза, прежде чем принимать вход.) –

0

Есть несколько проблем, с тем, что вы делаете. Первый , так как Бенуа сказал: вы вызываете cin.ignore() слишком рано, перед тем, как вывести приглашение. cin.ignore() будет извлекать ровно один символ из входного потока (если поток не сработал, или он встречает конец файла).

Во-вторых, когда вы цикл (например, потому что пользователь имеет вошел "abc"), вы звоните cin.ignore()перед тем сбрасываете ошибку , так что это не-оп. Если пользователь вводит что-либо, кроме , номер, вы зацикливаетесь навсегда, потому что вы застряли на плохом вводе. Вероятно, вы должны поместить cin.clear() в ветвь if, которая обрабатывает ошибку. (Конечно, это означает, что вы будете нуждаться в какой-то флаг, чтобы проверить в do...while, так как ошибка была очищена от времени вы получаете там. Кроме того, вы можете поставить clear и ignore в верхней части цикла, но в if, так что вы только их, если cin.fail().)

в-третьих, вы игнорируете ровно один символ. Если пользователь входов "abc", это будет цикл четыре раза ("abc" плюс новая линия ), прежде чем ждать его ввода. Обычным решением является игнорировать через следующий символ новой строки:

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

Это должно быть сделано после того, как вы вводите int (вероятно, неудачу ли вы или нет, но так как вы выход, если вы не» t сбой, на самом деле это не имеет значения, если вы этого не сделаете).

Наконец, две точки по стилю: вездесущий способ interogating ли вход удалось или не лечить поток, как логическое значение:

if (!cin) { 
    // error... 
} else { 
    // OK... 
} 

// ... 
} while (!cin); 

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

И я бы отделить вход с подсказкой в ​​отдельную функцию, и написать что-то вроде:

template <typename T> 
std::istream& 
inputWithPrompt(std::istream& source, std::string const& prompt, T& dest) 
{ 
    std::cout << prompt; 
    source >> dest; 
    return source; 
} 

int 
main() 
{ 
    int a; 
    while (!inputWithPrompt(std::cin, "Enter a number:", a)) { 
     std::cin.clear(); 
     std::cin.ignore(std::numeric_limits<std::streamsize>::max, '\n'); 
     std::cout << "Invalid input" << std::endl; 
    } 
    std::cout << "Number entered is: " << a << std::endl; 
    return 0; 
} 

Это кажется намного ровнее мне: петли, пока не удастся, то сделать успешный выход после того, как вы покинете цикл. (Это может быть стоит положить код очистки, то clear и ignore в отдельную функции, а также. Если вы ввод с помощью >>, вам нужно это достаточно часто.)

Смежные вопросы