Вырваться из перегруженного оператора извлечения? (С++)

Я пытаюсь использовать перегруженный ">>" для сканирования ввода из файла.

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

Ex:

9rl

8d

6ff

istream &operator>>(istream &is, Move &move)
{
  char c;
  int i = 0;

  c = is.get();

  if (!isalnum(c))
      return;

  move.setNum(c); // I convert the char to an int, but I'l edit it out

  while ( (c = is.get()) != '\n')
  {
    move.setDirection(i, c); //sets character c into in array at index i
    i++;

  } // while chars are not newline

  return is;
} // operator >>

Тест на то, что символ является буквенно-цифровым, работал, когда у меня это было как обычная функция, но не работает здесь, так как ожидает возврата входного потока. Я также пытался вернуть NULL. Предложения?

РЕДАКТИРОВАТЬ: это вызывается в цикле while, поэтому я пытаюсь найти способ, чтобы этот триггер запускал какой-то флаг, чтобы я мог выйти из цикла. В моей предыдущей функции эта функция возвращала логическое значение, возвращая true в случае успеха или false, если символ не был буквенно-цифровым.


person kevin    schedule 10.02.2010    source источник


Ответы (2)


Вернуть is. Вызывающие должны проверять поток на наличие ошибок.

Обязательно установите соответствующие биты ошибок:

std::istream &operator>>(std::istream &is, Move &move)
{
  char c;
  int i = 0;

  c = is.get();
  if (is.eof())
    return is;
  else if (c < '0' || c > '9') {
    is.setstate(std::ios::badbit);
    return is;
  }
  else
    move.setNum(c-'0');

  while ( (c = is.get()) != '\n' && is)
    move.setDirection(i++, c);

  if (c != '\n')
    is.setstate(std::ios::badbit);
  return is;
}

Используйте его, как показано ниже:

int main(int argc, char **argv)
{
  std::stringstream s;

  s << "9rl\n"
    << "8d\n"
    << "6ff\n";
  s.seekg(0);

  Move m;
  while (s >> m)
    std::cout << m;

  if (s.bad())
    std::cerr << argv[0] << ": extraction failed\n";

  return 0;
}

Обратите внимание, что код использует экземпляр m только после успешного извлечения.

person Greg Bacon    schedule 10.02.2010
comment
И здесь «ошибки» будут означать переход к нулю или какое-то недопустимое состояние. - person Tanzelax; 10.02.2010
comment
Спасибо вам обоим. возвращение и пометка движения - это то, что я в итоге сделал - person kevin; 10.02.2010

Вы можете установить флаги потока в такое состояние, как ios::bad или ios::fail с помощью ios::setstate. Это позволит вызывающему объекту протестировать поток или, в случае, если для потока включены исключения, будет возбуждено исключение.

Вы также не можете проверить состояние вашего потока. Облегченный FAQ по C++ содержит отличный раздел, объясняющий это. Чтобы прояснить это, я добавил фрагмент кода ниже.

c = is.get();
// the stream has not been tested to see if it read into c correctly
if (!isalnum(c))
    return;
person Chris de Vries    schedule 10.02.2010