将 NUMBERFMT 与 GetNumberFormatEx 一起使用的正确方法是啥?
Posted
技术标签:
【中文标题】将 NUMBERFMT 与 GetNumberFormatEx 一起使用的正确方法是啥?【英文标题】:What's the proper way to use `NUMBERFMT` with `GetNumberFormatEx`?将 NUMBERFMT 与 GetNumberFormatEx 一起使用的正确方法是什么? 【发布时间】:2021-08-27 17:00:02 【问题描述】:我正在为 Windows、Mac 和 Linux 编写一个区域感知节点应用程序。由于 javascript 对语言环境的处理没有考虑用户的自定义区域设置,因此我正在编写一个原生 Node 模块来为每个平台处理这个问题。
我正在设计一个函数,它需要一个数字来格式化和一个精度(小数点后的位数)并返回一个字符串。例如,如果我以 1 的精度传入 1234.456,并且我的区域设置使用“_”表示组,使用“/”表示小数,我希望使用用户当前语言和区域的适当区域设置信息“1_234/5”设置。
在 Windows 方面,我正在努力让 Windows API 准确地提供我想要的东西。这是我正在编写的 C++ 函数:
std::string FormatNumber(const double number, const int precision)
std::wstringstream stream;
stream.setf(std::ios::fixed, std::ios::floatfield);
stream.precision(precision);
stream << number;
std::wstring roundedNumberStr = stream.str();
const wchar_t *numStr = roundedNumberStr.c_str();
wchar_t wBuffer[MAX_PATH];
GetNumberFormatEx(
LOCALE_NAME_USER_DEFAULT, // lpLocaleName,
0, // dwFlags,
numStr, // lpValue,
NULL, // lpFormat,
wBuffer, // lpNumberStr,
MAX_PATH // cchNumber
);
// Return a std::string using wBuffer
这几乎可以完美运行,但无论我使用的精度如何(例如“1_234/00”),它总是精确到小数点后 2 位。为了解决这个问题,我怀疑我需要为lpFormat
传递一个参数。 Windows API 文档建议我只需要提供我想要控制的值并将其余的留给用户设置,所以我尝试了这样的事情:
NUMBERFMTW format precision ;
GetNumberFormatEx(
LOCALE_NAME_USER_DEFAULT, // lpLocaleName,
0, // dwFlags,
numStr, // lpValue,
&format, // lpFormat,
wBuffer, // lpNumberStr,
MAX_PATH // cchNumber
);
但是...这会导致ERROR_INVALID_PARAMETER
错误。遗憾的是,文档并没有给我更多的见解。
那么如何让这个函数给我我期望的字符串呢?
【问题讨论】:
你需要更多的代码来设置format的所有成员。 我要做的第一件事是初始化format
: NUMBERFMTW format ;
有趣的是,当我将旧代码库切换到 VS2019 时,我现在在将 NUMBERFMT
结构初始化为 const 文字时收到 const 不兼容警告!看起来NUMBERFMT
的定义是LPWSTR
而不是LPCWSTR
。我不太相信微软,这不仅仅是旧 C 时代的保留,不修改它......我将用 #pragma strict_gs_check(push, on)
/#pragma strict_gs_check(pop)
指令包围该函数,以确保更加安全!
【参考方案1】:
完全初始化您的NUMBERFORMAT:
NUMBERFMTW formatNumDigits ;
您拥有的任何未初始化的成员都有未指定的(可能是随机的)值。
【讨论】:
感谢您的提示!我的 C++ 有点生疏了。不幸的是,这并不能消除错误。【参考方案2】:NUMBERFMT 中的两个字符串不是可选的。其他成员是可选的,因为 0 是有效的,但 0 并不意味着它们获得正确的区域设置特定值!
使用LOCALE_SDECIMAL
和LOCALE_STHOUSAND
调用GetLocaleInfoEx
以加载“正确”字符串,并使用LOCALE_SGROUPING
进行分组。 MSDN 会告诉您为其他成员使用哪个区域设置查询。
【讨论】:
以上是关于将 NUMBERFMT 与 GetNumberFormatEx 一起使用的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy