gpt4 book ai didi

c++ - 标准 C++ MoneyPunct/put_money 错误?

转载 作者:行者123 更新时间:2023-11-28 00:51:04 32 4
gpt4 key购买 nike

关于这些货币操纵者的文档似乎几乎为零。我试图通过反复试验来解决这个问题。考虑示例程序:

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

观察接受 double 但有一个 sprintf 的函数,该函数会去掉所有小数。在我再次重新发明轮子之前,我想在这里征求一下 C++ 专家的意见。

最佳答案

这些都是 C++ 标准的直接要求:

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

The argument units is transformed into a sequence of wide characters as if by ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) [...] the pattern is the result of mp.pos_format().

这里,mpstd::moneypunct 方面,因此,继续满足其要求,

§22.4.6.3[locale.moneypunct]/3

The number of digits required after the decimal point (if any) is exactly the value returned by frac_digits().

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

int do_frac_digits() const; Returns: The number of digits after the decimal radix separator, if any. [261]

261) In common U.S. locales, this is 2.

所有这些确实可以概括为“put_money 的参数以美分为单位”

关于c++ - 标准 C++ MoneyPunct/put_money 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14079108/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com