2009-06-17 13 views
7

Typowym problemem międzynarodowym jest konwersja podwójnych wartości reprezentowanych w ciągach. Te rzeczy można znaleźć w wielu dziedzinach.konwersja z podwójnym ciągiem znaków i lokalizacja

Począwszy plików csv, które są albo zwanych

comma separated 

lub

character separated 

ponieważ czasami są one przechowywane jak

1.2,3.4 
5.6,6.4 

w angielskich regionów lub

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

na przykład w regionach niemieckich.

Z tego tła wynika, że ​​większość metod std :: zależy od lokalizacji. Tak więc w Niemczech będą oni czytać "1,2" jako 1,2, a następnie zapisać je jako "1,2", ale z angielskim systemem operacyjnym będzie to "1,2" jako 1 i zapisywać go ponownie jako "1".

Ponieważ ustawienia regionalne są stanem globalnym aplikacji, nie jest dobrym pomysłem przełączenie go na inne ustawienie; i tutaj mamy pewne problemy, kiedy muszę przeczytać niemiecki plik CSV na maszynie angielskiej lub odwrotnie.

Trudno jest również napisać kod, który zachowuje się tak samo na wszystkich komputerach. Strumień C++ umożliwia ustawienie ustawień regionalnych dla każdego strumienia.

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); 

pozwoli ci zainicjować strumień z zachowaniem std :: C i zastąpi tylko kropkę dziesiętną. Daje mi to możliwość zignorowania tysiąca separatorów, które mogą również wpływać. Niemiecki 1000.12 może stać się "1.000,12"; lub po angielsku "1,000.12" skończy się kompletnym pomyłką. Nawet zastępując "," przez "." nie pomoże w tej sytuacji.

Jeśli mam pracować z atof i przyjaciół mogę używać

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

pimp moje zachowanie.

Tak więc istnieje wiele rzeczy, które można zastosować tylko w przypadku podwójnego zachowania na poziomie międzynarodowym. Nawet moje Visual Studio boryka się z problemami, ponieważ niemiecka wersja chce zapisać 8,0 jako wersję do pliku vcproj, podczas gdy angielska wersja chce zmienić ją na 8.0, co definitywnie stało się incydentem, ponieważ w XML jest zdefiniowana jako 8.0 we wszystkich Kraje Świata.

Po prostu chciałem trochę opisać problem, by zapytać o aspekty, które mogłem zignorować. miejsca, które znam:

  • kufel dziesiętny jest locale zależne
  • 000 separator jest locale zależne
  • wykładnik jest locale zależne

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

Który kraj wykorzystuje które ustawienie?Może możesz dodać kilka ciekawych przykładów, których nie miałem do tej pory.

+0

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

Odpowiedz

2

Nigdy nie używaj atof (s). Jest to szybki, brudny skrót do strtod (s, 0) bez zgłaszania błędów. (To samo dotyczy atoi() i strtol()).

Jeśli funkcja być reklamowany, aby powrócić kod błędu w przypadku trudności, ty będziesz wyboru dla tego kodu, tak, mimo kontroli potrójnej wielkości z twojego kodu i wywołuj ból w palcach, jeśli myślisz, że "to nie może się zdarzyć mi", bogowie na pewno ukarzą cię za twoją arogancję.

(Henry Spencer, "Dziesięć przykazań dla programista C" Przykazanie nr 6)