【问题标题】:How to print a double with a comma如何用逗号打印双精度
【发布时间】:2009-09-14 15:08:37
【问题描述】:

在 C++ 中,我有一个浮点/双精度变量。

当我用例如 cout 打印这个时,结果字符串是句点分隔的。

cout << 3.1415 << endl
$> 3.1415

有没有一种简单的方法可以强制使用逗号打印双精度?

cout << 3.1415 << endl
$> 3,1415

【问题讨论】:

    标签: c++ floating-point double


    【解决方案1】:

    imbue() coutlocalenumpunct facet 的 decimal_point() 成员函数返回一个逗号。

    可以通过多种方式获得这样的locale。您可以使用系统上可用的命名语言环境(可能是std::locale("fr"))。或者,您可以派生自己的 numpuct,在其中实现 do_decimal_point() 成员。

    第二种方法的例子:

    template<typename CharT>
    class DecimalSeparator : public std::numpunct<CharT>
    {
    public:
        DecimalSeparator(CharT Separator)
        : m_Separator(Separator)
        {}
    
    protected:
        CharT do_decimal_point()const
        {
            return m_Separator;
        }
    
    private:
        CharT m_Separator;
    };
    

    用作:

    std::cout.imbue(std::locale(std::cout.getloc(), new DecimalSeparator<char>(',')));
    

    【讨论】:

    • 使用您的示例会导致:std::runtime error locale::facet::_S_create_c_locale name not valid
    • 此错误可能意味着,在您的平台上,“fr”名称未绑定到语言环境。
    • 我猜的差不多了,但是你怎么知道哪些名字绑定到一个语言环境的。
    • 遗憾的是,我认为没有便携的方式。
    • 在 linux 上:locale -a 命令,但我不知道如何以编程方式执行此操作。
    【解决方案2】:

    这由您的程序的语言环境控制。

    如何设置程序的默认语言环境取决于平台。例如,在 POSIX 类型平台上,它带有 LANG 和 LC_* 环境变量。

    您可以通过调用 ios::imbue 在 C++ 程序中强制使用特定的语言环境(不同于默认语言环境)。这样的事情可能会奏效:

    #include <locale>
    cout.imbue(std::locale("German_germany"));
    

    这个想法是强制使用逗号作为小数分隔符的语言环境。您可能需要调整“German_germany”字符串以在特定平台上获得所需的行为。

    【讨论】:

    • 使用您的示例会导致:std::runtime error locale::facet::_S_create_c_locale name not valid
    【解决方案3】:

    您需要使用不同的语言环境来填充流,其 num_punct (iirc) facet 指定逗号。

    如果您的平台语言环境格式使用逗号,那么

    cout.imbue(locale(""));
    

    应该足够了。

    【讨论】:

    • 谢谢,您的回答有效。但是我想接受一个更通用的答案(如果您对平台上正确的语言环境预设不太幸运)。仍然 +1,因为它是最简单的方法。
    【解决方案4】:

    确切地说,这是由std::numpunct&lt;charT&gt;::decimal_point() 值控制的。你可以imbue()另一个语言环境和另一个decimal_point()

    【讨论】:

      【解决方案5】:

      旧线程,但无论如何......人们应该知道,使用std::locale 会使字符串“漂亮”,并带有正确的小数点、千位分隔符等等,具体取决于平台和语言环境。最有可能的是,使用imbue() 会在格式化后破坏对字符串的任何解析。例如:

      std::ostringstream s;
      std::locale l("fr-fr");
      s << "without locale: " << 1234.56L << std::endl;
      s.imbue(l);
      s << "with fr locale: " << 1234.56L << std::endl;
      std::cout << s.str();
      

      给出以下输出:
      without locale: 1234.56
      with fr locale: 1 234,56

      在第二个字符串上使用strtod() 或类似的可能不会很好地工作......另外,第二个输出字符串中的“1”和“2”之间的空格是不间断的,使字符串更漂亮:-)

      【讨论】:

        【解决方案6】:

        非常旧的线程,但无论如何......我在 Gtkmm-3.0 下用距离计算的结果填充文本条目时遇到了问题。为了让事情更清楚,我添加了一个示例,其中我集中了我最近几天阅读的几篇文章的一些智慧:

        #include <locale>
        // next not necessary, added only for clarity
        #include <gtkmm-3.0/gtkmm.h>
        Gtk::Entry m_Text;
        // a distance measured in kilometers
        double totalDistance = 35.45678;
        std::stringstream str;
        // I am using locale of Germany, pay attention to the _
        str.imbue(std::locale("de_DE"));
        // now we have decimal comma instead of point
        str << std::fixed << std::setprecision(4) << std::setw(16) << totalDistance << " km";
        // the wished formatting corresponds to "%16.4f km" in printf
        m_Text.set_text(str.str());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多