2012-12-29 82 views
0

這些貨幣操縱者似乎幾乎沒有文件。我試圖通過試驗和錯誤來弄清楚這一點。考慮示例程序:標準C++ MoneyPunct/put_money錯誤?

class CAccountingMoneyPunctFacet : public std::moneypunct<char> 
{ 
protected: 
    virtual string_type do_curr_symbol() const  {return ")";} 
    virtual char_type do_thousands_sep() const  {return ',';} 
    virtual char_type do_decimal_point() const  {return '.';} 
    virtual string_type do_positive_sign() const {return "";} 
    virtual string_type do_negative_sign() const {return "(";} 
    virtual string_type do_grouping() const   {return "\03";} 
    virtual int do_frac_digits() const    {return 2;} 

    virtual pattern do_pos_format() const 
    { 
     pattern p; 
     p.field[0] = value; 
     p.field[1] = none; 
     p.field[2] = none; 
     p.field[3] = none; 
     return p; 
    } 

    virtual pattern do_neg_format() const 
    { 
     pattern p; 
     p.field[0] = sign; 
     p.field[1] = value; 
     p.field[2] = symbol; // Very retarded C++ standard need to do this kind of a hack for negative numbers! 
     p.field[3] = none; 
     return p; 
    } 
}; 


int main(int argc,char* argv[]) 
{ 
    std::ostringstream oss; 
    oss.imbue(std::locale(std::locale(),new CAccountingMoneyPunctFacet)); 
    oss << std::put_money(1234567.23) << std::endl; 
//  << (-1234567) << " " << std::setiosflags(std::ios_base::showbase) << std::put_money(-12345678911.314159) << std::endl; 
    std::cerr << oss.str(); 
return 0; 
} 

此代碼的問題是它打印出12,345.67。這是非常糟糕的,因爲它不僅失去了小數,現在是關閉的100倍。我看MSVC++ STL實現,是相當困惑:

virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, 
    bool _Intl, ios_base& _Iosbase, _Elem _Fill, 
     long double _Val) const 
    { // put long double to _Dest 
    bool _Negative = false; 
    if (_Val < 0) 
     _Negative = true, _Val = -_Val; 

    size_t _Exp; 
    for (_Exp = 0; 1e35 <= _Val && _Exp < 5000; _Exp += 10) 
     _Val /= 1e10; // drop 10 zeros before decimal point 

    string_type _Val2; 
    char _Buf[40]; 

    **int _Count = _CSTD sprintf_s(_Buf, sizeof (_Buf), "%.0Lf",** 
     _Val); // convert to chars 

    for (int _Off = 0; _Off < _Count; ++_Off) 
     _Val2.append((typename string_type::size_type)1, 
      _MAKLOCCHR(_Elem, _Buf[_Off], _Cvt)); // convert chars 
    _Val2.append(_Exp, 
     _MAKLOCCHR(_Elem, '0', _Cvt)); // scale by trailing zeros 

    return (_Putmfld(_Dest, _Intl, _Iosbase, _Fill, _Negative, _Val2)); 
    } 

觀察這需要一個雙,但有一個功能sprintf將所有小數點刪除。在我再次重新開始之前,我想在這裏得到C++專家的意見。

+0

至於我可以說沒有有史以來看到它提到,'put_money'的參數是在美分。 – chris

+0

如果我在2位小數的情況下工作,如果我將frac_digits更改爲另一個數字,例如3,它將不起作用。 – user805547

+0

您說得對,只有很少的文檔。我只是說明了我在使用「en-US」語言環境時注意到的內容。我真的沒有讀過任何關於它的東西,它提供了大量的信息。 – chris

回答

3

那些是C++標準的所有直接要求:

§22.4.6.2.2[locale.money.put.virtuals]/1

的參數單元被變換成寬字符序列好像通過ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) [012]模式是 結果mp.pos_format()

這裏,mpstd::moneypunct刻面,所以,繼續到它的要求,

§22.4.6.3需要[locale.moneypunct]/3

的位數小數點後(如果有)恰好是由frac_digits()返回的值。

最後, §22.4.6.3.2[locale.moneypunct.virtuals]/6

int do_frac_digits() const;返回:的小數基數分離器之後的數字,如果任何數。 [261]

261)在美國常見的語言環境,這是2

這一切的確可以概括爲「參數put_money在仙」

+0

+1。強調最後一行。其目的是使用諸如「long」之類的定點類型來啓用會計數學。 – Potatoswatter