Передайте символ в int при использовании std :: cin в C ++ - PullRequest
0 голосов
/ 23 июня 2018

У меня проблема с упражнением, которое требует от меня получить два целых числа и напечатать их. Но программа заканчивается, когда пользователь вводит запись '|'. Тем не менее, я проверяю это, и программа входит в бесконечный цикл. В чем проблема?

#include <iostream>
using namespace std;

int main ()
{
  int i1 = 0, i2 = 0;

  cin >> i1;
  cin >> i2;
  while (i1 != int('|') && i2 != int('|'))
  {
     cout << i1 << endl;
     cout << i2 << endl;

     cin >> i1 >> i2; 
  } 

  return 0;
}

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

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

std::cin >> i1;
std::cin >> i2;

на этот код:

std::cin >> i1 >> i2;

Результатом этого выражения снова будет исходный istream, и при использовании влогический контекст, возвращает false, если поток находится в состоянии «сбой».Таким образом, мы можем прочитать два целых числа и проверить, было ли это успешно в одной простой конструкции:

if( std::cin >> i1 >> i2 ) {
    std::cout << i1 << "\n" << i2 << "\n";
} else {

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

} else {
    std::cin.clear();    // reset the fail state
    if (std::cin.peek() == '|') {
        std::cout << "Found end of input marker (|)\n";
    } else {
        std::cout << "Invalid input!";
    }

После определения, был ли это вертикальный канал или нет, целесообразно очистить все символы в потоке до концастрока ввода.

    // skip all characters in the stream up to the end of the current line.
    std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}

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

while ( !std::cin.eof() ) {
    if( std::cin >> i1 >> i2 ) {
        std::cout << i1 << "\n" << i2 << "\n";
    } else {
        std::cin.clear();    // reset the fail state
        if (std::cin.peek() == '|') {
            std::cout << "Found end of input marker (|)\n";
            break;
        } else {
            std::cout << "Invalid input!";
        }
        // skip all characters in the stream up to the end of the current line.
        std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
    }
}
0 голосов
/ 23 июня 2018

Когда вы std::cin нецелочисленный тип (charector '|') внутри цикла, происходит сбой.Используйте std::cin.fail(), проверьте это.

Например, запустите следующее, и вы поймете, почему это произошло:

while (i1 != int('|') && i2 != int('|'))
{
    std::cout << i1 << endl;
    std::cout << i2 << endl;

    std::cin >> i1 ;  // std::cin fails here, in the the case of '|'
    if(std::cin.fail()) { std::cout << "Failed"; break;}

    std::cin >> i2;  // std::cin fails here, in the the case of '|'
    if(std::cin.fail()) { std::cout << "Failed"; break;}
}

Выше исправит код,Однако вы также можете написать код для любого случая сбоя std::cin, проверив с помощью std::cin::fail().

while ( std::cin >> i1 && !std::cin.fail()   // check wether i1 failed, if not continue
     && std::cin >> i2 && !std::cin.fail() ) // check wether i2 failed, if not continue
{
   std::cout << i1 << "\n" << i2 << std::endl;
}

Обновление : как указал @AJNeufeld, while (i1 != int('|') && i2 != int('|')) будетне удается прочитать 124, даже входные данные являются целыми числами (что соответствует коду ASCII символа вертикальной черты).

Возможное решение - прочитать оба значения в виде строк, проверить наличие символа '|', если он отсутствует, преобразовать строки в целые, или сообщить об ошибках или прервать цикл.(Кредиты @AJNeufeld)

...