stl — Стандартная ошибка 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

Решение

Это все прямые требования стандарта C ++:

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

Единицы аргумента преобразуются в последовательность широких символов, как если бы ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) […] образец является
Результат mp.pos_format(),

Вот, mp это std::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 в центах

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]