title: double string conversion and locale
body: <p>A common international issue is the conversion of double values represented in strings. This stuff is found in a lot of areas.</p>
  
  <p>Starting with csv files which are either called</p>
  
  <pre><code>comma separated
  </code></pre>
  
  <p>or</p>
  
  <pre><code>character separated
  </code></pre>
  
  <p>because sometimes they are stored like</p>
  
  <pre><code>1.2,3.4
  5.6,6.4
  </code></pre>
  
  <p>in English regions or</p>
  
  <pre><code>1,2;3,4
  5,6;6,4
  </code></pre>
  
  <p>in for example German regions.</p>
  
  <p>From this background, it is somehow necessary to know that most of the std:: methods are locale dependent. So in Germany, they will read "1,2" as 1.2 and write it back as "1,2" but with an English OS it will read "1,2" as 1 and write it back as "1".</p>
  
  <p>Because the locale is a global state of the application, it is not a good idea to switch it to a different setting; and here we are with some problems when I have to read a German CSV file on an English machine or vice versa.</p>
  
  <p>It's also hard to write code that behaves the same on all machines. The C++ stream allows a locale setting per stream.</p>
  
  <pre><code>class Punctation : public numpunct&lt;wchar_t&gt;
  {
  public:
  
    typedef wchar_t char_type;
    typedef std::wstring string_type;
  
    explicit Punctation(const wchar_t&amp; decimalPoint, std::size_t r = 0) : 
      decimalPoint_(decimalPoint), numpunct&lt;wchar_t&gt;(r)
    {
    }
  
    Punctation(const Punctation&amp; rhs) : 
      decimalPoint_(rhs.decimalPoint_) 
    {
    }
  
  protected:
  
    virtual ~Punctation() 
    {
    };
  
    virtual wchar_t do_decimal_point() const 
    { 
      return decimalPoint_; 
    }
  
  private:
  
    Punctation&amp; operator=(const Punctation&amp; rhs);
  
    const wchar_t decimalPoint_;
  };
  
  ...
  
  std::locale newloc(std::locale::classic(), new Punctation(L','));
  stream.imbue(newloc);
  </code></pre>
  
  <p>will allow you to initialize a stream with std:: C behavior and only replace the decimal point. This gives me the ability to ignore the thousand separator, which may come into affect too.
  German 1000.12 may become "1.000,12"; or in English "1,000.12" will end up in complete confusion. Even replacing "," by "." will not help in this situation.</p>
  
  <p>If I have to work with <code>atof</code> and friends I can use</p>
  
  <pre><code>const char decimal_point = *(localeconv()-&gt;decimal_point);
  </code></pre>
  
  <p>to pimp my behavior.</p>
  
  <p>So there is an awful amount of stuff just for international double behavior. Even my Visual Studio runs into problems because the German version wants to write 8,0 as version into the vcproj file while an English version wants to change it to 8.0, which definitively happened by incident because in XML it is defined to be 8.0 in all countries of the world.</p>
  
  <p>So I just wanted to describe the problem a bit to ask for aspects I may have ignored.
  Things that I know:</p>
  
  <ul>
  <li>decimal pint is locale dependent</li>
  <li>thousand separator is locale dependent</li>
  <li>exponent is locale dependent</li>
  </ul>
  
  <hr>
  
  <pre><code>//                  German       English     Also known
  // decimal point       ,            .            
  // exponent            e/E          e/E          d/D
  // thousand sep        .            ,
  </code></pre>
  
  <p>Which country uses which setting? Maybe you can add me some interesting examples that I didn't have till now.</p>