бесконечный цикл в c++


Я изучаю C++ и пишу небольшие программы по ходу дела. Ниже приводится одна из таких программ:

// This program is intended to take any integer and convert to the
// corresponding signed char.

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(true){
    std::cin >> n;
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

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

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

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

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

4 6

4 ответа:

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

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(std::cin >> n){
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

cin >> n вернет ссылку на cin, которую вы можете проверить на "доброкачественность" в условном выражении. Таким образом, в основном the "while(std::cin >> n) "говорит:" пока я все еще могу успешно читать из стандартного ввода, сделайте следующее "

EDIT: причина, по которой он повторно выводит последнее введенное хорошее значение, заключается в том, что это было последнее успешно прочитанное значение в n неудачные чтения не изменят значение n

EDIT: как было отмечено в комментарии, Вы можете очистить состояние ошибки и попробовать снова что-то вроде этого, вероятно, будет работать и просто игнорировать плохие числа:

#include <iostream>
#include <climits>

int main() {
    signed char sch = 0;
    int n = 0;
    while(true) {
        if(std::cin >> n) {
            sch = n;
            std::cout << n << " --> " << sch << std::endl;
        } else {
            std::cin.clear(); // clear error state
            std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
        }
    }
}

Да, Эван Теран уже указал на большинство вещей. Одна вещь, которую я хочу добавить (так как я не могу прокомментировать его комментарий:)), заключается в том, что вы должны поместить вызов istream::clear Перед вызовом istream::ignore. Причина в том, что istream::ignore подобным образом просто откажется что-либо делать, если поток все еще находится в состоянии fail.

Учитывая, что вы находитесь на 32-разрядной машине, 10000000000-слишком большое число, чтобы быть представленным int. Кроме того, преобразование int в char даст вам только от 0..255 или -128..127 в зависимости от компилятора.

Одна из проблем здесь заключается в том, что char имеет размер одного байта и, таким образом, может содержать только число между -127 и 128. С другой стороны, int обычно составляет 4 байта и может принимать гораздо бОльшие значения. Вторая проблема заключается в том, что вы вводите значение, которое слишком велико даже для int.