money_get<>工作正常吗?

时间:2018-01-13 15:42:56

标签: c++

在coliru上,我测试了 money_get <>面对美元和欧元。

对于USD而言,它正常工作(就我的测试数据而言),而不是EUR。

为美元测试它的程序是:

int main()
{
    std::string str = "$1.11 $2.22 $3.33 4.44 5.55";

    std::istringstream s1(str);
    s1.imbue(std::locale("en_US.UTF-8"));

    std::cout << std::fixed << std::setprecision(2);
    std::cout << '"' << str << "\" parsed with the I/O manipulator: ";

    long double val;

    while(s1 >> std::get_money(val))
        std::cout << val/100 << ' ';
    std::cout << '\n';


    str = "USD  1,234.56";

    std::istringstream s2(str);
    s2.imbue(std::locale("en_US.UTF-8"));

    std::cout << '"' << str << "\" parsed with the facet directly: ";

    auto& f = std::use_facet<std::money_get<char>>(s2.getloc());
    std::ios_base::iostate err;
    std::istreambuf_iterator<char> beg(s2), end;

    f.get(beg, end, true, s2, err, val);

    std::cout << val/100 << '\n';
}

http://coliru.stacked-crooked.com/a/be545f641718040e

O / P是正确的:

"$1.11 $2.22 $3.33 4.44 5.55" parsed with the I/O manipulator: 1.11 2.22 3.33 4.44 5.55 
"USD  1,234.56" parsed with the facet directly: 1234.56

为EUR测试它的程序类似:

int main()
{
    std::string str = "1,11 2,22 3,33 € 456789,12 €";

    std::istringstream s1(str);
    s1.imbue(std::locale("de_DE.utf8"));

    std::cout << std::fixed << std::setprecision(2);
    std::cout << '"' << str << "\" parsed with the I/O manipulator: ";

    long double val;

    while(s1 >> std::get_money(val))
        std::cout << val/100 << ' ';
    std::cout << '\n';


    str = "1.234,56 EUR";

    std::istringstream s2(str);
    s2.imbue(std::locale("de_DE.utf8"));

    std::cout << '"' << str << "\" parsed with the facet directly: ";

    auto& f = std::use_facet<std::money_get<char>>(s2.getloc());
    std::ios_base::iostate err;
    std::istreambuf_iterator<char> beg(s2), end;

    f.get(beg, end, true, s2, err, val);

    std::cout << val/100 << '\n';
}

http://coliru.stacked-crooked.com/a/a91720a9dbd4eb5e

O / P错了:

"1,11 2,22 3,33 € 456789,12 €" parsed with the I/O manipulator: 1.11 2.22 3.33 
"1.234,56 EUR" parsed with the facet directly: 1234.56

请注意,未打印第4欧元金额。这是因为只要money_get&lt;&gt; .get()函数遇到第3个值中的€符号,就会产生错误。它只处理没有€符号的普通金额。

money_punct &lt;&gt; coliru上的facet for German locale给出了以下定义:

moneypunct in locale "de_DE.utf8":
 decimal_point: ,
 thousands_sep: .
 grouping:      3 3 
 curr_symbol:   €
 positive_sign: 
 negative_sign: -
 frac_digits:   2
 pos_format:    sign value space symbol 
 neg_format:    sign value space symbol 

请注意,我已按照neg_format的规定正确输入了欧元金额。

如何解决这样的问题?

感谢。

2 个答案:

答案 0 :(得分:1)

正如std::money_get::get的cppreference页面所述,std::showbase是必要的,以使最终位置的货币符号不可选:

std::string str = "3,33 € 456789,12 €";
std::istringstream s1(str);
s1.imbue(std::locale("de_DE.utf8"));
std::cout << std::fixed << std::setprecision(2);
std::cout << '"' << str << "\" parsed with the I/O manipulator: ";
long double val;
s1 >> std::showbase; // <-- this
while(s1 >> std::get_money(val))
    std::cout << val/100 << ' ';
std::cout << '\n';

输出coliru

"3,33 € 456789,12 €" parsed with the I/O manipulator: 3.33 456789.12 

答案 1 :(得分:0)

是的,你是对的,Cubbi。

根据您提供的信息,我编写了程序,并解释了为什么会发生这种情况。

1)阅读 USD 金额的计划已经开始运作。没问题。

http://coliru.stacked-crooked.com/a/be545f641718040e

2)要读取 EUR 金额,您必须设置输入流的showbase标志,如Cubbi所示。

当涉及的欧元金额使用当地符号€时,这就是必要的。

但是,当涉及的欧元金额使用国际符号EUR时,读取数据中的符号必须是4个字符的字符串“EUR”。最后一个空间很重要,否则它不会被消耗掉。这可能是因为国际表示是一个4字符的C风格字符串,最后一个字符是终止零。 [Stroustrup,“The C ++ Programming Language”,4th Ed,pg 1136。]

http://coliru.stacked-crooked.com/a/ef38fb1d1c98aa22

/// ...

str = "1.234,56 EUR ";

std::istringstream s2(str);
s2.imbue(std::locale("de_DE.utf8"));
// s2 >> std::showbase;

std::cout << '"' << str << "\" parsed with the facet directly: ";

auto& f = std::use_facet<std::money_get<char>>(s2.getloc());
std::ios_base::iostate err;
std::istreambuf_iterator<char> beg(s2), end;

f.get(beg, end, true, s2, err, val);

std::cout << val/100 << '\n';


"1.234,56 EUR " parsed with the facet directly: 1234.56  

3)同样,要读取 INR 金额,您必须设置输入流的showbase标志。

当涉及的INR数量使用本地符号₹时,这就是所有必要的。

但是,当涉及的INR数量使用国际符号INR时,读取数据中的符号必须是4个字符的字符串“INR”。最后一个空间很重要,否则它不会消耗。

http://coliru.stacked-crooked.com/a/216cc78592141ae1

/// ...

str = "INR  100,234.56";

std::istringstream s2(str);
s2.imbue(std::locale("en_IN"));

//  s2 >> std::showbase;

std::cout << '"' << str << "\" parsed with the facet directly: ";

auto& f = std::use_facet<std::money_get<char>>(s2.getloc());
std::ios_base::iostate err;
std::istreambuf_iterator<char> beg(s2), end;

f.get(beg, end, true, s2, err, val);

std::cout << val/100 << '\n';

请注意,数据字符串中有2个相邻的空格:INR符号后面的1和值前面的1。这是模式{符号符号空间值}。

所必需的
"INR  100,234.56" parsed with the facet directly: 100234.56