C++ 格式化 int 数字以用点分隔千位

Posted

技术标签:

【中文标题】C++ 格式化 int 数字以用点分隔千位【英文标题】:C++ format int numbers to separate thousands with a dot 【发布时间】:2015-07-27 14:58:50 【问题描述】:

我正在开发 Eclipse,在 Fedora 上。我想用一个点来分隔数千个数字,使数字更容易理解。这个数字是一个整数值,可以是0<Value<99.999

所以...如果Value = 1000 它显示1000 而我想要显示1.000(注意点)。我需要更改的代码是下一个:

char str[12];
sprintf(str, "%d", (int)(Value));
m_Text.SetText(str); 

而我的想法是:

if (Value > 999) 

 int RightPart = (int)Value % 1000;
 int LeftPart = Val/1000 ;

然后追加一个字符串 LeftPart + "." + RightPart 所以如果Value = 1563 它将是1+.+5631.563

我的问题是这样做非常难看,我想知道是否有更好的方法。我在谷歌上搜索过,发现imbuelocale但它们只适用于cout。我也看到过一些类似this 和this 的帖子,但这对我的问题没有帮助。

谢谢。

注意:我想说明我不想更改输出格式。我想更改收到的 int,这样我就可以在 str var 中添加点,以便稍后使用。

注意 2:基本上,代码必须:接收一个整数(值),并将其像字符串一样发送到 setText()。 setText() 基本上会在屏幕上何时何地打印它,我希望它打印 1.563 而不是更难阅读的 1563。

【问题讨论】:

您可以使用 C++ 语言环境工具来输出带有自定义千位分隔符和十进制数字分隔符的数值。有关详细信息,请参阅en.cppreference.com/w/cpp/locale/numpunct。您可以使用 stringstreams 来格式化字符串。 使用字符串流***.com/a/7276879/786186 @AlessandroPezzato 如果我输入int Val = 1563; std::stringstream ss; ss.imbue(std::locale("")); ss << std::fixed << Val; sprintf(str, "%d", (int)(Val)); std::cout << " ss = " << ss << " str = "<< str << std::endl; 那么输出是ss = 0xbfffe398 VAL = 5634 所以我想是出了点问题 @AlessandroPezzato 我现在也一样:ss = 5634 str = 5634 因为@AlessandroPezzato 链接的问题接受了错误的答案。正确答案是那里的节点。 【参考方案1】:

使用stringstream 和相同的灌输技术。

例如:

struct dotted : std::numpunct<char> 
    char do_thousands_sep()   const  return '.';   // separate with dots
    std::string do_grouping() const  return "\3";  // groups of 3 digits
    static void imbue(std::ostream &os) 
        os.imbue(std::locale(os.getloc(), new dotted));
    
;

然后:

    std::stringstream ss;
    dotted::imbue(ss);
    ss << Value;
    std::cout << ss.str();

Demo

【讨论】:

有了你的 cout 我得到了我想要的 1.563 值,但是如果我写 sprintf(str, "%d", (int)(Val)); std::cout &lt;&lt; " str = "&lt;&lt; str &lt;&lt; std::endl;然后它会打印 1563。所以我也是这样。正如我所说,我不希望视觉输出发生变化,我希望收到的 int 发生变化,这样我就可以在 str 中添加点。【参考方案2】:
#include <iomanip>
#include <locale>
#include <iostream>
#include <sstream>

using namespace std;

template<class T>
string format(T value)

    stringstream ss;
    ss.imbue(locale(""));
    ss << fixed << value;
    return ss.str();



int main(int argc, char argv[])

    cout.imbue(locale(""));
    cout << 1000000 << endl;

    return 0;

打印:

1.000.000

您可能应该查看传递“”时使用的语言环境,并使用更合适的语言环境进行更改。

反之亦然:

int str_to_nr(string str)

    int val;

    stringstream ss(str);
    ss.imbue(locale(""));
    ss >> val;

    return val;



int main(int argc, char argv[])

    cout << str_to_nr("1.000") << endl;

    return 0;

打印:

1000

【讨论】:

再次,我不想改变输出格式,我想改变int读取格式。我已在我的问题中添加了一条注释以说明问题。 我仍然不确定我是否完全理解您想要实现的目标,但我更新了我的答案。 我已经添加了第二条注释以进一步澄清它,很抱歉造成误解。我稍后会看到你的答案,因为现在我无法测试它【参考方案3】:

@gandgandi's answer 基本上为您提供了一种使用 C++ 流按需打印带有点的值的技术。

sprintf(通常使用起来并不安全,顺便说一句)是一个 C 库函数。 C 没有提供与 C++ 提供的相同方式来更改语言环境行为的机制。在 C 中,您必须使用操作系统提供的机制/工具来定义语言环境行为并为其分配名称。然后,您可以使用 C 函数 setlocale 将程序中的语言环境更改为您创建的语言环境,以使其按您想要的方式打印。 但是,这仅适用于安装了您创建的语言环境的机器。它不会在任何其他机器上工作。

只需一点点工作,几乎不需要任何创造性工作,您就可以使用已经提供的 C++ 解决方案并调用sprintf

char str[12];
stringstream ss;
dotted::imbue(ss);
ss << Value;
sprintf(str, "%s", ss.str());
m_Text.SetText(str);

但是,完全没有理由使用sprintf

stringstream ss;
dotted::imbue(ss);
ss << Value;
m_Text.SetText(ss.str());

【讨论】:

以上是关于C++ 格式化 int 数字以用点分隔千位的主要内容,如果未能解决你的问题,请参考以下文章

如何格式化数字来定义千位分隔符?

如何在 Dart 中将数字格式化为千位分隔符

如何格式化带有千位分隔符和括号中的负数的数据透视表数字?

在python中使用本地化的千位分隔符和小数精度格式化数字

数字格式,去掉千位分隔符

.NET 通用数字格式与千位分隔符