2009-06-17 20 views
7

Un problema internacional común es la conversión de valores dobles representados en cadenas. Este material se encuentra en muchas áreas.conversión de cadena doble y configuración regional

A partir de archivos CSV que se llaman ya sea

comma separated 

o

character separated 

porque a veces se almacenan como

1.2,3.4 
5.6,6.4 

en regiones inglesas o

1,2;3,4 
5,6;6,4 

en, por ejemplo, regiones alemanas.

De este fondo, de alguna manera es necesario saber que la mayoría de los métodos std :: dependen de la configuración regional. Entonces en Alemania, leerán "1,2" como 1.2 y lo escribirán de nuevo como "1,2", pero con un sistema operativo en inglés leerá "1,2" como 1 y lo escribirá de nuevo como "1".

Dado que la configuración regional es un estado global de la aplicación, no es una buena idea cambiarla a una configuración diferente; y aquí estamos con algunos problemas cuando tengo que leer un archivo CSV alemán en una máquina en inglés o viceversa.

También es difícil escribir código que se comporte igual en todas las máquinas. La secuencia de C++ permite una configuración regional por secuencia.

class Punctation : public numpunct<wchar_t> 
{ 
public: 

    typedef wchar_t char_type; 
    typedef std::wstring string_type; 

    explicit Punctation(const wchar_t& decimalPoint, std::size_t r = 0) : 
    decimalPoint_(decimalPoint), numpunct<wchar_t>(r) 
    { 
    } 

    Punctation(const Punctation& rhs) : 
    decimalPoint_(rhs.decimalPoint_) 
    { 
    } 

protected: 

    virtual ~Punctation() 
    { 
    }; 

    virtual wchar_t do_decimal_point() const 
    { 
    return decimalPoint_; 
    } 

private: 

    Punctation& operator=(const Punctation& rhs); 

    const wchar_t decimalPoint_; 
}; 

... 

std::locale newloc(std::locale::classic(), new Punctation(L',')); 
stream.imbue(newloc); 

le permitirá inicializar una secuencia con comportamiento std :: C y solo reemplazar el punto decimal. Esto me da la capacidad de ignorar el separador de miles, que también puede entrar en efecto. alemán 1000.12 puede convertirse en "1,000,12"; o en inglés "1,000.12" terminará en completa confusión. Incluso reemplazando "," por "." no ayudará en esta situación.

Si tengo que trabajar con atof y amigos que puedo utilizar

const char decimal_point = *(localeconv()->decimal_point); 

para chulo mi comportamiento.

Así que hay una cantidad horrible de cosas solo para el doble comportamiento internacional. Incluso mi Visual Studio tiene problemas porque la versión alemana quiere escribir 8,0 como versión en el archivo vcproj, mientras que una versión en inglés quiere cambiarlo a 8.0, lo que definitivamente ocurrió por incidente porque en XML se define como 8.0 en todo países del mundo.

Así que solo quería describir el problema un poco para preguntar por los aspectos que pude haber ignorado. cosas que sé:

  • pinta decimal Depende de la localización
  • separador de miles Depende de la localización
  • exponente Depende de la localización

//     German  English  Also known 
// decimal point  ,   .    
// exponent   e/E   e/E   d/D 
// thousand sep  .   , 

Qué país utiliza qué configuración?Quizás puedas agregarme algunos ejemplos interesantes que no tenía hasta ahora.

+0

http://en.wikipedia.org/wiki/Decimal_point#Examples_of_use – Pod

Respuesta

2

No utilice atof (s). Es un atajo sucio & rápido para strtod (s, 0) sin el informe de errores. (Lo mismo para atoi() y strtol()).

Si una función de ser objeto de publicidad para devolver un código de error en caso de dificultades, tú cheque serás para ese código, sí, a pesar de los controles triple del tamaño de tu código y producir dolores en tus dedos que tipean, porque si piensas que 'no puede pasar a yo', los dioses seguramente te castigarán por tu arrogancia.

(Henry Spencer, "Diez Mandamientos para el programador C", Mandamiento # 6)

Cuestiones relacionadas