Исключения в плохом потоке - PullRequest
1 голос
/ 07 мая 2011

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

cin.clear() and cin.ignore()

Но я так и не смог понять, почему это происходит.Символ представлен целым числом от 0 до 255. И каждого числа 32-битного достаточно, чтобы целочисленная переменная могла обработать ... так почему же тогда происходит сбой потока?

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

Ответы [ 4 ]

1 голос
/ 08 мая 2011

Почему они работают так:

Хорошо, операторы потока >> и << предназначены для чтения текста (или читаемых человеком потоков (или файлов)). Таким образом, при использовании вы ожидаете определенный тип ввода, который имеет определенную форму: </p>

int a;
stream >> a; // I expect the stream to contain an integer in human readable form.

MyClass x;
stream >> x; // I expect the class to contain a serialize version of x;

Если бы символ был автоматически преобразован в целое число, поток не работал бы так, как большинство людей ожидает, что операторы потока будут работать (то есть читают читаемые человеком формы). то есть вы знаете, что ASCII-значение 'z' должно быть? Знаете ли вы, если ваша платформа представляет символы в виде ASCII? и т. д. Есть много вопросов, о которых известно только наполовину, если мы выбрали этот путь.

Теперь, если вы хотите обработать ваш файл как двоичное значение. Вы можете прочитать один байт и считать его целым числом.

char y;
stream.read(&y, 1); // Read a single byte into y

int  x = y;         // now convert the byte to an integer.

Переход к исключениям:

Исключения хороши, когда вы обрабатываете ошибки отдельно от обработки. Это нормально, когда у вас огромные файлы, а ошибка при вводе файла обычно означает повреждение, и вам следует прекратить обработку. Тогда исключения являются идеальным решением.

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

std::cout << "Enter a number\n";
int number;
while(!(std::cin >> number))
{
    std::cout << "That was not a number\n";
    std::cin.clear();
    std::cin.ignore();
}


// With exceptions:

  // That's too much work.

Но если я обрабатываю индекс Google:

// If the read fails get out of here with an exception.
while(data >> x >> y >> z >> j >> q >> p >> src >> dst)
{
    doWork();
}
ExapndAndGrok();


// Handling the errors:

while(data >> x >> y >> z >> j >> q >> p >> src >> dst)
{
    doWork();
}
if (testDataStreamForSomeError(data)) // EOF is not an error.
{
    throw someException("The input failed");
}
ExapndAndGrok();
1 голос
/ 07 мая 2011

Да, вы можете указать любому потоку выдать исключение (вместо установки битов сбоя), используя ios :: exception .

cin.exceptions(istream::failbit | istream::badbit);

try
{
    int a;
    cin >> a;
}
catch(istream::failure& e)
{
    cerr << "Error : " << e.what() << endl;
}
0 голосов
/ 07 мая 2011

Но я не смог понять, почему это происходит. Символ представлен целым числом от 0 до 255. И каждого числа 32-битного достаточно, чтобы целочисленная переменная могла обработать ... так почему же тогда происходит сбой потока?

Хорошо, спецификация говорит, что когда вы используете оператор >> для int, он должен анализировать входные данные как текстовое представление целого числа (в соответствии с текущей набранной локалью, хотя в случае int это, вероятно, не имеет большое значение). Это означает, что, если вы также не используете манипулятор io для принятия неосновных оснований (например, ios::hex), буквенно-цифровые символы по определению запрещены.

Если вы хотите принять любой символ и рассматривать его как двоичное представление «короткого короткого целого», вы можете

 unsigned char uch;
 signed char   sch;

 std::cin >> uch;
 std::cin >> sch;

Как и следовало ожидать, это никогда не завершится по причинам синтаксического анализа (только eof (), отказано в разрешении, нехватка памяти или какой-либо другой технический сбой ...).

Надеюсь, что это объясняет

0 голосов
/ 07 мая 2011

Вы можете написать цикл как:

int var;
while ( std::cin >> var )
{
     //do whatever you want to do with var
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...