其他分享
首页 > 其他分享> > c-do_decimal_point和do_thousands_sep不起作用

c-do_decimal_point和do_thousands_sep不起作用

作者:互联网

我的信息流似乎完全忽略了do_decimal_pointdo_thousands_sep.

我想做的是在get_money中使用一个句号作为我的Millennium_Sep和一个逗号作为我的小数点.因此,我重写了moneypunct,但它只是被忽略了:(

struct punct_facet : public moneypunct<char> {
    char_type do_decimal_point() const { return ','; }
    char_type do_thousands_sep() const { return '.'; }
};

int main()
{
    istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
    USCurrency.imbue(locale(locale("en-US"), new punct_facet));
    int index = 0;
    long double value;

    do{
        value = 0.0;
        USCurrency >> get_money(value, true);
        cout << ++index << ": " << value << endl;
    } while (value == 123456.0 || value == -123456.0);
    return 0;
}

我希望这只会输出:

1: 123

但是我得到了:

1: 123456
2: -123456
3: 123

我究竟做错了什么?我正在使用Visual Studio 2013,以防从“ en-US”中显而易见.

编辑:

当我在do_decimal_point或do_thousands_sep中放置一个断点时,我发现它从未被击中.我不确定为什么不这样做,但是该信息似乎与问题有关.

解决方法:

该解决方案实际上只是对answer given here的解释.

货币构造函数删除了复制构造函数和赋值运算符.这给构造punct_facet留下了两个不好的选择:

>复制punct_facet中的所有moneypunct成员,并调用punct_facet构造函数中的所有moneypunct虚拟函数以对其进行初始化.这有一个明显的缺点,即punct_facet对象的胖度是其应有的两倍,并且其构造函数的运行时间超过了严格的要求.
>使用指针和特定于对象的编译器知识,以实现从moneypunct到punct_facet的复制构造.这具有明显的缺点,即不能跨平台,并且有意无视标准实现的设计.

对于这个答案,我选择了错误的选项2,因为moneypunct的实现已经是编译器所专有的,而不是“,”,“ C”或“ POSIX”以外的任何构造参数,并且因为针对已删除的moneypunct复制构造函数和赋值运算符. (顺便说一句,如果将moneypunct构造参数也调整为选项2 works in gcc 5.1.0,但在Clang 3.6.0中将不起作用.)希望Microsoft会尽快为该错误提供更多功能的解决方法,并且我们将不必使用任何错误的选项.

因此,如果punct_facet这样实现:

template <typename T>
class punct_facet : public T {
private:
    void Init(const T* money){
        const auto vTablePtrSize = sizeof(void*);

        memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
    }
protected:
    typename T::char_type do_decimal_point() const {
        return typename T::char_type(',');
    }

    typename T::char_type do_thousands_sep() const {
        return typename T::char_type('.');
    }
public:
    punct_facet(){
        Init(&use_facet<T>(cout.getloc()));
    }

    punct_facet(const T* money){
        Init(money);
    }
};

您可以使用punct_facet构造函数之一进行构造,您将获得预期的输出:

123

要使用默认构造函数,您需要添加cout.imdue(locale(“ en-US”));在main的顶部,并将您的适当陈述更改为:

USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>()));

要使用自定义构造函数,您只需要将imdue语句更改为:

USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>(&use_facet<moneypunct<char, true>>(locale("en-US")))));

最好使用默认构造函数,因为模板类型和构造函数参数之间的差异可能会导致某些不良行为.

值得注意的一点是,您的USCurrency不使用国际货币格式,因此无需使用moneypunct< char,true&gt ;, moneypunct< char>.会很好.只需记住要在各处进行更改,因为punct_facet的模板参数与get_money中使用的参数之间的差异将再次导致您所看到的意外行为.

标签:comma,decimal-point,period,c,locale
来源: https://codeday.me/bug/20191010/1883801.html