<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx</link><description>Please read the disclaimer ; content of Michael Kaplan's blog not approved by Microsoft! 
 Some of you may recall Igor Levicki, the guy who had 64-bit keyboards working before MSKLC 1.4 was released who I mentioned in If you just don't think you can</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx#8159199</link><pubDate>Tue, 11 Mar 2008 23:22:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8159199</guid><dc:creator>Igor Levicki</dc:creator><description>&lt;P&gt;This is how I would write GetDoubleFormat():&lt;/P&gt;&lt;FONT face="Consolas,Lucida Console,Courier New,Courier" size=1&gt;
&lt;P&gt;#ifndef _WIN32_WINNT&lt;BR&gt;#define _WIN32_WINNT 0x0501&lt;BR&gt;#endif&lt;BR&gt;&lt;BR&gt;#include &amp;lt;tchar.h&amp;gt;&lt;BR&gt;#include &amp;lt;stdio.h&amp;gt;&lt;BR&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;BR&gt;#include &amp;lt;math.h&amp;gt;&lt;BR&gt;#include &amp;lt;float.h&amp;gt;&lt;BR&gt;#include &amp;lt;windows.h&amp;gt;&lt;BR&gt;&lt;BR&gt;#define MSEP_MAX 5&amp;nbsp;&amp;nbsp;&amp;nbsp; // 4 characters + NULL, actual Windows XP limit&lt;BR&gt;#define TSEP_MAX 4&amp;nbsp;&amp;nbsp;&amp;nbsp; // 3 characters + NULL, actual Windows XP limit&lt;BR&gt;#define DSEP_MAX 4&amp;nbsp;&amp;nbsp;&amp;nbsp; // 3 characters + NULL, actual Windows XP limit&lt;BR&gt;#define NDEC_MAX 9&amp;nbsp;&amp;nbsp;&amp;nbsp; // 9 decimal places, actual Windows XP limit&lt;BR&gt;#define PDBL_MAX&amp;nbsp;320&amp;nbsp; // 1.7976931348623158e+308&lt;BR&gt;#define PDBL_MAX2&amp;nbsp;640&lt;BR&gt;// Copyright (c) 2008 by Igor Levicki. All Bugs Reserved. :-)&lt;BR&gt;&lt;BR&gt;LPCTSTR GetDoubleFormat(const double Value, const UINT DecimalPlaces) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static TCHAR Formatted[MAX_PATH];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR StrValue[MAX_PATH];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR StrFraction[MAX_PATH];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR MSep[MSEP_MAX] = _T("-");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR TSep[TSEP_MAX] = _T(",");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TCHAR DSep[DSEP_MAX] = _T(".");&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; const TCHAR Dot = _T('.');&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; const TCHAR Zero = _T('0');&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LPTSTR FracPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; size_t Cch, Mod, Idx;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (DecimalPlaces &amp;gt; NDEC_MAX) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetLastError(ERROR_INVALID_PARAMETER);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Value &amp;gt; DBL_MAX) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetLastError(ERROR_INVALID_PARAMETER);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, MSep, MSEP_MAX);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, TSep, TSEP_MAX);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, DSep, DSEP_MAX);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Formatted[0] = 0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (_fpclass(Value)) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_SNAN:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_QNAN:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_NINF:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_ND;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_PD:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_PINF:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetLastError(ERROR_INVALID_PARAMETER); // or ERROR_INVALID_DATA&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NULL; // or ERROR_NOT_SUPPORTED&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_NZ:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, MAX_PATH, MSep);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case _FPCLASS_PZ:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcsncat_s(Formatted, MAX_PATH, &amp;amp;Zero, 1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (DecimalPlaces &amp;gt; 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, MAX_PATH, DSep);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size_t Len = _tcslen(Formatted);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (UINT i = 0; i &amp;lt; DecimalPlaces; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Formatted[Len + i] = Zero;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Formatted[Len + DecimalPlaces] = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Formatted;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _stprintf_s(StrValue, PDBL_MAX, _T("%0.*f"), DecimalPlaces, abs(Value));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FracPtr = _tcsrchr(StrValue, Dot);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (FracPtr != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *FracPtr++ = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tcscpy_s(StrFraction, PDBL_MAX, FracPtr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StrFraction[0] = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cch = _tcslen(StrValue);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Mod = (Cch % 3);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Idx = (Mod == 0) ? 3 : Mod;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Formatted[0] = 0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Value &amp;lt; 0.0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, PDBL_MAX2, MSep);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; Cch; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (i == Idx) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, PDBL_MAX2, TSep);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Idx += 3;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcsncat_s(Formatted, MAX_PATH, &amp;amp;StrValue[i], 1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (DecimalPlaces &amp;gt; 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, PDBL_MAX2, DSep);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _tcscat_s(Formatted, PDBL_MAX2, StrFraction);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return Formatted;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;int _tmain(int argc, _TCHAR* argv[]) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (--argc != 2) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Usage : %s &amp;lt;decimal_number&amp;gt; &amp;lt;places&amp;gt;\n", argv[0]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double Value = _tstof(argv[1]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int DecimalPlaces = _tstoi(argv[2]);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_tprintf(_T("DecimalPlaces = %ld, Formatted : %s"), DecimalPlaces, GetDoubleFormat(Value, DecimalPlaces));&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;It properly handles user overrides for minus sign (up to 4 characters), thousand separator and decimal separator (up to 3 characters each), and it allows showing more decimal places than the original which could only chop the fractional part, not extend it.&lt;/P&gt;
&lt;P&gt;Function could be easily expanded to handle +/- Infinity (and use locale supplied strings for that), to handle denormals and to display SNaN and QNaN text if needed. A bit more challenging task would be to handle digit replacement correctly and to use digit grouping other than 3.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8159199" width="1" height="1"&gt;</description></item><item><title>re: What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx#8152009</link><pubDate>Tue, 11 Mar 2008 16:06:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8152009</guid><dc:creator>Michael S. Kaplan</dc:creator><description>&lt;p&gt;I guess the lack of clarity on that point could be considered a fourth problem to fix? :-)&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8152009" width="1" height="1"&gt;</description></item><item><title>re: What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx#8146839</link><pubDate>Tue, 11 Mar 2008 10:58:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8146839</guid><dc:creator>Leo Davidson</dc:creator><description>&lt;p&gt;&amp;quot;GetNumberFormatW assumes that space for the NULL is included in the buffer -- why allocate a wchar_t array of 256 if you are only going to pass 255 for the length?&amp;quot;&lt;/p&gt;
&lt;p&gt;Because MSDN is almost always vague about what the length arguments mean. MSDN typically talks about the length of the string, but doesn't say if it means the length as in what strlen (etc.) would return, or if it means the number of characters in the string including the null.&lt;/p&gt;
&lt;p&gt;I expect most APIs do include the null in their lengths but it only takes one bad API call to cause a crash or corrupt memory when the string happens to be the same length as the buffer and the null either doesn't get written or gets written off the end of the buffer...&lt;/p&gt;
&lt;p&gt;So I almost always, unless the MSDN documentation is very explicit, allocate that one extra character. It's just two bytes of memory, so why not? Not everyone has the advantage of being able to look in the API source when the documentation falls short and it's quicker to waste 2 bytes (for the millisecond that stack frame is in scope) than to run tests on every API to see how it behaves when the result fills the buffer exactly.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8146839" width="1" height="1"&gt;</description></item><item><title>re: What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx#8144496</link><pubDate>Tue, 11 Mar 2008 07:37:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8144496</guid><dc:creator>Michael S. Kaplan</dc:creator><description>&lt;p&gt;Not sure how this gets all the user 's preferences?&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8144496" width="1" height="1"&gt;</description></item><item><title>re: What's wrong with one of GetNumberFormat's callers? And what's wrong with GetNumberFormat?</title><link>http://blogs.msdn.com/b/michkap/archive/2008/03/10/8120567.aspx#8135036</link><pubDate>Mon, 10 Mar 2008 20:16:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8135036</guid><dc:creator>Pseudo</dc:creator><description>&lt;p&gt;The simplest way would seem to be:&lt;/p&gt;
&lt;p&gt;set f = 10^DecimalPlaces&lt;/p&gt;
&lt;p&gt;multiply Value by f&lt;/p&gt;
&lt;p&gt;round or truncate to an integer&lt;/p&gt;
&lt;p&gt;divide by f&lt;/p&gt;
&lt;p&gt;wsprintf to get the string&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8135036" width="1" height="1"&gt;</description></item></channel></rss>