44 votos

¿Por qué stringstream >> el valor de cambio de destino en caso de error?

De Stroustrup del TC++PL, 3ª Edición, Sección 21.3.3:

Si tratamos de leer en una variable v y la operación falla, el valor de v debe ser invariable (es invariable en si v es uno de los tipos manejado por istream o ostream funciones miembro).

En el ejemplo siguiente se parece contradecir la cita anterior. Basándose en la cita de arriba, yo estaba esperando que el valor de v se mantendrá sin cambios, pero se pone en cero. ¿Cuál es la explicación para esta 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 obtengo mediante x86_64-w64-mingw32-g++.exe (rubenvb-4.7.2-release) 4.7.2 es:

Before: 123
After: 0
state: failbit

Gracias.

48voto

Joachim Pileborg Puntos 121221

A partir de esta referencia:

Si la extracción de falla (por ejemplo, si una carta en la que fue introducido en donde un dígito se espera), el valor se deja sin modificar y failbit se establece (hasta C++11)

Si la extracción de falla, cero está escrito de valor y failbit se establece. Si la extracción de los resultados en el valor es demasiado grande o demasiado pequeño para caber en valor, std::numeric_limits::max() o std::numeric_limits::min() está escrito y failbit bandera. (debido a que C++11)

Parece que su compilador es compilar en C++11 modo, que cambia el comportamiento.


El operador de entrada se utiliza la configuración regional faceta std::num_get cuyas get función invoca do_get. Para C++11 está especificado el uso de std::strtoll et. al. tipo de funciones. Antes de C++11, al parecer, utilizó std::scanf estilo de análisis (que van por la referencia, no tengo acceso a el C++03 especificación) para extraer los números. El cambio en el comportamiento es debido a este cambio en el análisis de la entrada.

4voto

Loki Astari Puntos 116129

El operador >> es un formato de entrada del operador.
Como tal depende de la configuración regional para la forma de entrada es de lectura de la secuencia:

[istream.con formato.aritmética]

Como en el caso de la insertor, estos extractores dependen de la configuración regional del num_get<> (22.4.2.1) objeto de realizar el análisis de la secuencia de entrada de datos. Estos extractores se comportan como formato de entrada de funciones (como se describe en 27.7.2.2.1). Después de un centinela objeto se construye, se produce la conversión como si se realiza por la 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 por encima del valor es en realidad por la numget faceta de la configuración regional imbuded en la secuencia.

num_get funciones virtuales [faceta.num.obtener.virtuals]

Etapa 3:

El valor numérico para ser almacenado puede ser uno de:

  • cero, si la función de conversión no se puede convertir todo el campo. ios_base::failbit se asigna a errar.
  • lo más positivo representable valor, si el campo representa un valor muy positivo grande para ser representado en val. ios_base::failbit se asigna a errar.
  • la parte más negativa representable valor de cero o un entero de tipo entero, si el campo represen - sents un valor muy negativo grande para ser representado en val. ios_base::failbit se asigna a errar.

La definición de la fase 3 modificado drásticamente entre n2723 -> n2798

Donde puedo encontrar la corriente de C o C++ estándar de documentos?

num_get funciones virtuales [faceta.num.obtener.virtuals]

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

  • Una secuencia de caracteres que se ha acumulado en la etapa 2, que se convierte (de acuerdo a las reglas de scanf) a un valor del tipo de val . Este valor se almacena en el val y ios_base::goodbit se almacena en err .
  • La secuencia de caracteres acumulado en la etapa 2, habría causado scanf para informar de una entrada de error. ios_base::failbit se asigna a errar.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X