El extractor de Date
mostrado antes
activa el bit de error de un stream
bajo
ciertas condiciones. ¿Como sabe un usuario que este error ha
ocurrido? Puede detectar errores del
stream
llamando a ciertas funciones
miembro del stream para ver si tenemos un estado de error, o si
a usted no le preocupa qué tipo de error ha pasado, puede
evaluar el stream
en un contexto
Booleano. Ambas técnicas derivan del estado del bit de error de
un stream
.
La clase ios_base
, desde la que
ios
deriva,[12]define cuatro banderas
que puede usar para comprobar el estado de un
stream
:
Bandera
Significado
badbit
Algún error fatal (quizás físico) ha ocurrido. El
stream
debe considerarse no usable.
eofbit
Ha ocurrido un final de entrada (ya sea por haber encontrado un final físico de un stream
de fichero o por que el usuario ha terminado el stream
de consola, (usando un Ctrl-Z o Ctrl-D).
failbit
Una operación de E/S ha fallado, casi seguro que por datos inválidos (p.e. encontrar
letras cuando se intentaba leer un número). El stream
todavía se
puede usar. El failbit
también se activa cuando ocurre un final de entrada.
goodbit
Todo va bien; no hay errores. La final de la entrada todavía no ha ocurrido.
Puede comprobar si alguna de estas condiciones ha ocurrido
llamando a la función miembro correspondiente que retorna un
valor Booleano indicando cual de estas ha sido activada. La
función miembro de stream
good()
retorna cierto si ninguno de los
otros tres bits se han activado. La función
eof()
retorna cierto si eofbit
está activado, que ocurre con un intento de leer de un
stream
que ya no tiene datos
(generalmente un fichero). Como el final de una entrada ocurre
en C++ cuando tratamos de leer pasado el final del medio físico,
failbit
también se activa para indicar que los
datos esperados no han sido correctamente leídos. La función
fail()
retorna cierto si
failbit
o badbit
están activados, y
bad()
retorna cierto solo si
badbit
está activado.
Una vez alguno de los bit de error de un stream
se activa,
permanece activo, cosa que no siempre es lo que se quiere. Cuando leemos un fichero,
usted puede querer colocarse en una posición anterior en el fichero antes de su final.
Simplemenete moviendo el puntero del fichero no se desactiva el eofbit
o
el failbit
; debe hacerlo usted mismo con la función clear()
,
haciendo algo así:
myStream.clear(); // Clears all error bits
Después de llamar a clear()
,
good()
retornará cierto si es llamada
inmediatamente. Como vió en el extractor de
Date
antes, la función
setstate()
activa los bits que usted le
pasa.¿Eso significa que setstate no afecta a los otros bits? Si
ya esta activo, permanece activo. Si usted quiere activar
ciertos bits pero en el mismo momento, desactivar el resto,
usted puede llamar una versión sobrecargada de
clear()
, pasandole una expresion binaria
representando los bits que quiere que se activen, así:
myStream.clear(ios::failbit | ios::eofbit);
La mayoría del tiempo usted no estará interesado en comprobar los bits de estado
del stream
individualmente. Generalmente usted simplemente
quiere conocer si todo va bien. Ese es el caso cuando quiere leer un fichero del
principio al final; usted quiere saber simplemente cuando la entrada de datos se
ha agotado. Puede usar una conversion de la función definida para void*
que es automáticamente llamada cuando un stream
esta en una
expresión booleana. Leer un stream
hasta el final de la entrada
usando este idioma se parece a lo siguiente:
int i; while(myStream >> i) cout << i << endl;
Recuerde que operator>>()
retorna su
argumento stream
, así que la sentencia
while
anterior comprueba el
stream
como una expresión booleana. Este
ejemplo particular asume que el stream
de
entrada myStream contiene enteros separados por un espacio en
blanco. La función ios_base::operator
void*()
simplemente llama a
good()
en su stream
y retorna el resultado.[13] Como la mayoría de operaciones de
stream
retornan su
stream
, usar ese idioma es conveniente.
[12] Por esa
razón usted puede escribir ios::failbit
en lugar de ios_base::failbit
para
ahorrar pulsaciones.
[13] Es común el uso de
operator void*()
en vez de
operator bool()
porque las conversiones
implícitas de booleano a entero pueden causar sorpresas; pueden
emplazarle incorrectamente un stream en un contexto donde una
conversion a integer puede ser aplicada. La función
operator void*()
solo será llamada
implícitamente en el cuerpo de una expresión
booleana.