Я пытаюсь использовать перегруженный ">>" для сканирования ввода из файла.
Проблема в том, что я понятия не имею, как бороться с концом файла. В этом случае мой файл состоит из числа, за которым следуют несколько символов.
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, если символ не был буквенно-цифровым.
Ответ 1 · рейтинг 2 · Greg Bacon
Вернуть 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 только после успешного извлечения.
Ответ 2 · рейтинг 2 · Chris de Vries
Вы можете установить флаги потока в такое состояние, как 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;