kalaivanan from Bangalore, India Ответов: 1

Как интернационализировать (i18n) число в vc++ для winforms


Мне нужно интернационализировать число в c++. Пожалуйста, дайте мне метод i18n an number, который принимает number в качестве входного параметра. Я попробовал использовать приведенный ниже код, но он возвращает ненужное значение для неанглийского домена.

Что я уже пробовал:

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; 
}

Richard MacCutchan

Невозможно угадать, какие ошибки вы видите или где они происходят. Вам нужно использовать свой отладчик, чтобы пройти через код и посмотреть, какие значения вызывают проблему.

1 Ответов

Рейтинг:
0

Jochen Arndt

В вашем коде есть несколько ошибок.

Во-первых, вы используете строки ANSI, которые потерпят неудачу при сборке Unicode, потому что это вернет строки Unicode. Некоторые информационные значения предоставляются только в виде строк Unicode, так что они всегда будут терпеть неудачу.

Вторая ошибка-инициализация глобального объекта customFormatConst с локальными данными. Структура содержит указатели на строки, которые устанавливаются в локальные буферы, выходящие из области видимости при выходе из функции.

См. также Функция GetLocaleInfo (Windows)[^] (или использовать Функция GetLocaleInfoEx (Windows)[^]).

Поэтому вы должны использовать что-то вроде этого:

// 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). Чтобы использовать настройки локали по умолчанию для пользователя, используйте
setlocale(LC_ALL, "");

Чтобы установить кодовую страницу для ноу-хау LCID использовать
// 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 isntead из LC_ALL.
[/РЕДАКТИРОВАТЬ]