Pass the string, please

by Michael S. Kaplan, published on 2005/05/29 02:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2005/05/29/422980.aspx


A little over a month ago, I was talking about how SetLocaleInfo really stinks. Buried in my tirade was the germ of a question that people have asked in the past -- why is there no setting analogue to the LOCALE_RETURN_NUMBER flag used by functions like GetLocaleInfo, a sort of LOCALE_SPECIFY_NUMBER flag for the numeric fields? They are all small integers, so there is a simple enough method and datatype for such a flag to use.

Of course that is kind of syntactic sugar for SetLocaleInfo. The functions where the problem looks worse for us are GetCurrencyFormat and GetNumberFormat. They both have the following text for their lpValue parameters:

lpValue
[in] Pointer to a null-terminated string containing the number string to format.

This string can contain only the following characters:

All other characters are invalid. The function returns an error if the string pointed to by lpValue deviates from these rules.

So not only is there no way to pass an actual number to these functions (you must pass a string), but you also have to use a simple string that is not even vaguely internationally wise. It is not even a good US string, since you would have to pass long numbers without grouping separators, something that is very un-natural. Yuck!

But if you think about it, this does make sense. Would you want a function that would accept input one moment and then potentially fail with that same input moments later after a change to settings? Not to mention the performance impact of having to insert complex parsing logic into the function based on those settings, giving developers a very difficult to debug problem in the most common cases.

Of course one could expect that the function could use the same format as is expected in the locale passed in, but if the developer was able to format a string with that locale's settings, she would not need the function, right?

Now the fact that there is no LOCALE_SPECIFY_NUMBER type flag to pass is a bit stranger since it's not like this function gives the benefits of passing a string, right?

But before you agree with my strawman question, consider for a moment what datatype you would use.

Both functions will accept outrageously large numbers, much larger than any common C-style type that is available under Windows. And both will accept fractional values that are 100% precise -- way more precise than any floating point type that is available. You can start imagining complex schemes with different flags for different types of numbers, I suppose. And all that work and the functions would become hideously complex for customers to call and for us to maintain, all to provide less functionality than the current simple string allows!

Sometimes the simple answers are the best ones. If you ask me, both GetCurrencyFormat and GetNumberFormat fall in that category, and on the whole I am happy with how these funcions work....

 

This post brought to you by "Z" (U+005a, LATIN CAPITAL LETTER Z)
(All of the other letters were still asleep, and when they were saying Zzzzzzz, the Z woke up, thinking someone was calling her name!)


# Mihai on 29 May 2005 5:56 PM:

There is a slightly different problem I have with the two functions.
I cannot change only parts of the formatting. It is all or nothing.

Example: I would like to format number with GetNumberFormat but to get 4 decimals, not 2 (or 3, or whatever the locale wants). Because sometimes is really important.
Or I want to format the currency properly, but not change the currency symbol (or, even nicer, having it localized).

What I would like: GetCurrencyFormat( "12345.67" )
en_US => $12,345.67
ro_RO => 12.345,67 dolari americani
or 12.345,67 USD

What I do now to solve the problem: I fill in the NUMBERFMT & CURRENCYFMT structures using GetLocaleInfo. But some of the structure fields are not compatible with the GetLocaleInfo result (ex. NUMBERFMT::Grouping), so I have to do some parsing. Ouch!

Would be nice to have APIs to fill in the structure for me. Then I can change the one or two fields I need and use it (well, I have this already, but wouldn't this be useful for others?)

# Michael S. Kaplan on 29 May 2005 6:23 PM:

Ah, these are interesting things to consider for the future -- I will pass the ideas along.

Thanks! :-)

# John Bates on 5 Jun 2005 7:40 PM:

I second Mihai's suggestion.

One of my web forms (an invoice) has a column of currency amounts with a total at the bottom. The customer prefers to have the currency symbol only on the total.

So I should really be using GetCurrencyFormat for all the numbers, but have to use GetNumberFormat to get a string without the currency symbol.

So my question is: Does the number format for any locale differ from its currency format, with the exception of the symbol?

Thanks, John.

Please consider a donation to keep this archive running, maintained and free of advertising.
Donate €20 or more to receive an offline copy of the whole archive including all images.

referenced by

2008/03/10 What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?

2005/06/21 Number format and currency format are not always the same

go to newer or older post, or back to index or month or day