如何国际化(i18n)vc ++中的winforms数字 [英] How to internationalisation (i18n) an number in vc++ for winforms

查看:100
本文介绍了如何国际化(i18n)vc ++中的winforms数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要用c ++将数字国际化。请给我一个方法来i18n一个数字,它接受数字作为输入参数。我尝试使用下面的代码,但它返回非英语域的垃圾值。



我尝试过:



I need to internationalisation an number in c++. Please give me a method to i18n an number, which accepts number as input parameter. I tried with below code but it returning junk value for Non-English domain.

What I have tried:

int CUGCell::FormatNumber(double number, long nbrDecs, char* destBuf, int bufSize)
{
	char		infoBuf[3];
	char		decimalSep[10];
	char		thousandSep[10];
	char		sourceNbr[50];
	NUMBERFMT*	customFormat = NULL;
	UINT		defDigits;
	LCID		lcid;
	int			status;

	lcid = GetUserDefaultLCID();

	status = GetLocaleInfo(lcid, LOCALE_IDIGITS, infoBuf, 3);
	if (status == 0){
		return status;
	}

	defDigits =  atoi(infoBuf);
	if (defDigits != (UINT) nbrDecs){
		customFormat = new NUMBERFMT;

		customFormat->NumDigits = nbrDecs;
		
		status = GetLocaleInfo(lcid, LOCALE_ILZERO, infoBuf, 3);
		customFormat->LeadingZero = atoi(infoBuf);

		status = GetLocaleInfo(lcid, LOCALE_SGROUPING, infoBuf, 3);
		customFormat->Grouping = atoi(infoBuf);

		status = GetLocaleInfo(lcid, LOCALE_STHOUSAND, thousandSep, 10);
		customFormat->lpThousandSep = thousandSep;

		status = GetLocaleInfo(lcid, LOCALE_SDECIMAL, decimalSep, 10);
		customFormat->lpDecimalSep = decimalSep;

 		status = GetLocaleInfo(lcid, LOCALE_INEGNUMBER, infoBuf, 3);
		customFormat->NegativeOrder = atoi(infoBuf);
	}
	customFormatConst = customFormat;

	//002 sprintf(sourceNbr, "%f", number);
	sprintf_s(sourceNbr, sizeof(sourceNbr),"%f", number);//002
	status = GetNumberFormat(lcid, 0, sourceNbr, customFormat, destBuf, bufSize);
	
	if (customFormat != NULL)
		delete customFormat;
	 
	return status; 
}

推荐答案

代码中有多个错误。



首先,你使用的是ANSI字符串,因为它会返回Unicode字符串,因此会失败。一些信息值仅作为Unicode字符串提供,因此它们总是会失败。



第二个错误是初始化全局对象 customFormatConst 包含本地数据。该结构包含指向字符串的指针,这些字符串设置为离开函数时超出范围的本地缓冲区。



另请参阅 GetLocaleInfo函数(Windows) [ ^ ](或使用 GetLocaleInfoEx功能(Windows) [ ^ ])。



所以你应该使用这样的东西:

There are multiple errors within in your code.

The first is that you are using ANSI strings which will fail when having a Unicode build because that will return Unicode strings. Some info values are only provided as Unicode strings so that these will always fail.

The second error is initialising the global object customFormatConst with local data. The structure contains pointers to strings which are set to local buffers that go out of scope when leaving the function.

See also the GetLocaleInfo function (Windows)[^] (or use GetLocaleInfoEx function (Windows)[^]).

So you should use something like this:
// Global / static data
NUMBERFMT customFormatConst;
TCHAR thousandSep[10];
// ...

// Within function
TCHAR infoBuf[128];
status = GetLocaleInfo(lcid, LOCALE_IDIGITS, infoBuf, sizeof(infoBuf) / sizeof(TCHAR));
defDigits =  _tstoi(infoBuf);

status = GetLocaleInfo(lcid, LOCALE_STHOUSAND, thousandSep, sizeof(thousandSep) / sizeof(TCHAR));
customFormat->lpThousandSep = thousandSep;

// ...
// Copy to global data
if (customFormat)
    customFormatConst = *customFormat;







如果要为C标准指定区域设置小数点 printf 函数有一个更简单的解决方案(特别是当它应该应用于整个应用程序而不能多次更改时)。



然后调用setlocale,_wsetlocale [ ^ ]( main InitInstance )。要为用户使用默认的区域设置,请使用




If you want to specify the locale decimal point for the C standard printf functions there is a much simpler solution (especially when this should be applied to the whole application and not be changed multiple times).

Then call setlocale, _wsetlocale[^] at program start (main, InitInstance). To use the default locale settings for the user use

setlocale(LC_ALL, "");



设置知道的代码页 LCID 使用


To set the code page for a know LCID use

// Default system code page
char loc[16] = ".ACP";
// Try to get the default ANSI code page for the LCID
// Note that the ANSI function is called to get the result as char
//  and that it is stored after the '.' in the locale string
::GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, loc + 1, 15);
setlocale(LC_ALL, loc);





请注意,上述内容会更改所有区域设置,包括日期,时间和整理顺序。如果您只想更改数值的行为,请使用 LC_NUMERIC 而不是 LC_ALL

[/ EDIT]



Note that the above changes all locale settings including dates, times, and collation order. If you only want to change the behaviour for numeric values use LC_NUMERIC isntead of LC_ALL.
[/EDIT]


这篇关于如何国际化(i18n)vc ++中的winforms数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆