2011-10-06 8 views
7

Quiero leer enteros sin signo en la representación de base-10 (decimal) desde un iostream de C++ con al menos una detección de error rudimentaria. En mi opinión, los signos menos serían claramente un error en este caso, porque los enteros sin signo no tienen signo. Sin embargo, el CCG es de otra opinión:¿Cómo detectar números negativos como errores de análisis al leer enteros sin signo?

#include <iostream> 
#include <sstream> 

int main() { 
    std::stringstream a("5"), b("-0"), c("-4"); 
    unsigned int i; 
    a >> i; if (a) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    b >> i; if (b) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    c >> i; if (c) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    return 0; 
} 

me da una salida de

4294967292 

para la última línea, como si un entero con signo -4 había sido leído y convertido a unsigned int.

Appearently, the GCC people see this as a feature. ¿Hay algún estándar que ordene este comportamiento, y hay alguna forma de escribir un analizador propio para salir de él, es decir, detectar "-4" (y tal vez "-0") como errores de conversión?

+0

¿Has publicado el informe de error correcto? Ese está marcado como "fijo" sin ninguna resistencia. – spraff

+0

@spraff: Parece que sí, este menciona el comportamiento del número negativo. – thiton

Respuesta

4

Consulting C++ 03, 22.2.2.1.2/11, los formatos se heredan de scanf y amigos, que a su vez todos dicen que la secuencia de caracteres convertidos está "opcionalmente firmada", incluso para aquellos con salida sin firmar . strtoul es lo mismo.

Entonces, supongo que se podría decir que el estándar que ordena el comportamiento es C89 para C++ 03, C99 para C++ 11.

Desde el - pasa a ser permitido sólo como el primer carácter, supongo que la solución consiste en comprobar con peek antes de usar operator>>.

-1

¿Sería realmente diferente si hubieras hecho esto?

int i; 
unsigned int u; 
c >> i; 
u = i; 
std :: cout << u; 

No importa tanto que operator>> tolera la coincidencia de signo porque las reglas subyacentes C permitirán una conversión silenciosa en cualquier caso. No está agregando ninguna seguridad fundamentalmente "fortaleciendo" al operador de entrada.

Dicho esto, mi gcc (4.3.5 en Solaris) dice que es un error de conversión.

+2

Sería muy diferente al compilar con -Wconversion -Wsign-conversion -Werror. Puedo desactivar las conversiones silenciosas, pero no el manejo de los signos de iostream. – thiton

+0

Probablemente decidió manejarlo de la misma manera que se manejan los literales, pero no sé lo que dice el estándar al respecto. –

+0

El error de conversión es algo bueno, y parece ser porque usa una versión anterior de gcc (pre 4.4.1, según el error), lo que me deja todavía preguntándome por qué la gente de gcc intentó arreglar algo. – thiton

0

Si leo 22.2.2.1.2/tabla 5 muestra correctamente que la extracción en un signo es equivalente a scanf con %u que parece también hacen lo negativo -> conversión positiva.

Cuestiones relacionadas