library example c++ state stringstream cin

c++ - example - ¿Por qué stringstream>> cambia el valor del objetivo cuando falla?



stringstream s (2)

De esta referencia :

Si la extracción falla (por ejemplo, si se ingresó una letra donde se espera un dígito), el valor se deja sin modificar y se establece el bit de falla ( hasta C ++ 11 )

Si la extracción falla, cero se escribe en valor y se establece failbit. Si la extracción da como resultado un valor demasiado grande o demasiado pequeño para caber en valor, std :: numeric_limits :: max () o std :: numeric_limits :: min () se escribe y se establece el indicador de failbit. ( desde C ++ 11 )

Parece que su compilador está compilando en modo C ++ 11, lo que cambia el comportamiento.

El operador de entrada utiliza la configuración regional std::num_get cuya función get invoca do_get . Para C ++ 11 está especificado para usar std::strtoll et. Alabama. tipo de funciones. Antes de C ++ 11, aparentemente utilizaba el análisis de estilo std::scanf (pasando por la referencia, no tengo acceso a la especificación C ++ 03) para extraer los números. El cambio de comportamiento se debe a este cambio en el análisis de la entrada.

Desde TC ++ PL de Stroustrup, 3ra Edición, Sección 21.3.3:

Si tratamos de leer en una variable v y la operación falla, el valor de v no se modificará (no se modifica si v es uno de los tipos manejados por istream o las funciones miembro de ostream).

El siguiente ejemplo parece contradecir la cita anterior. En base a la cita anterior, esperaba que el valor de v no se modificara, pero se pone a cero. ¿Cuál es la explicación de este aparente comportamiento contradictorio?

#include <iostream> #include <sstream> int main( ) { std::stringstream ss; ss << "The quick brown fox."; int v = 123; std::cout << "Before: " << v << "/n"; if( ss >> v ) { std::cout << "Strange -- was successful at reading a word into an int!/n"; } std::cout << "After: " << v << "/n"; if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit/n"; if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit/n"; if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit/n"; return 1; }

La salida que recibo usando x86_64-w64-mingw32-g ++. Exe (rubenvb-4.7.2-release) 4.7.2 es:

Before: 123 After: 0 state: failbit

Gracias.


El operador >> es un operador de entrada formateado.
Como tal, depende de la configuración regional de cómo se lee la entrada de la transmisión:

[istream.formatted.arithmetic]

Como en el caso de los insertadores, estos extractores dependen del objeto num_get <> (22.4.2.1) de la configuración regional para realizar el análisis de los datos de la corriente de entrada. Estos extractores se comportan como funciones de entrada formateadas (como se describe en 27.7.2.2.1). Después de construir un objeto centinela, la conversión se produce como si se realizara mediante el siguiente fragmento de código:

typedef num_get< charT,istreambuf_iterator<charT,traits> > numget; iostate err = iostate::goodbit; use_facet< numget >(loc).get(*this, 0, *this, err, val); setstate(err);

Como podemos ver arriba, el valor en realidad está establecido por la faceta de numget de la configuración regional incorporada en la secuencia.

num_get funciones virtuales [facet.num.get.virtuals]

Etapa 3:

El valor numérico que se almacenará puede ser uno de:

  • cero, si la función de conversión no puede convertir todo el campo. ios_base :: failbit está asignado a err.
  • el valor representable más positivo, si el campo representa un valor demasiado grande positivo para ser representado en val. ios_base :: failbit está asignado a err.
  • el valor representable más negativo o cero para un tipo entero sin signo, si el campo representa un valor demasiado grande negativo para ser representado en val. ios_base :: failbit está asignado a err.

La definición de la etapa 3 cambió drásticamente entre n2723 -> n2798

¿Dónde encuentro los documentos estándar actuales de C o C ++?

num_get funciones virtuales [facet.num.get.virtuals]

Etapa 3: El resultado del procesamiento de la etapa 2 puede ser uno de:

  • Se ha acumulado una secuencia de caracteres en la etapa 2 que se convierte (de acuerdo con las reglas de scanf) a un valor del tipo de val. Este valor se almacena en val y ios_base :: goodbit se almacena en err.
  • La secuencia de caracteres acumulados en la etapa 2 hubiera causado que scanf informara una falla de entrada. ios_base :: failbit está asignado a err.