Could you say that again? I am having trouble parsing it...

by Michael S. Kaplan, published on 2007/02/10 03:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/02/10/1640807.aspx


As a good principle to follow (if not a downright rule), you should always try to match up the methods you use to convert values both into and back out of strings.

(I am assuming that matching methods to perform both operations are of course available; this is of course not always the case!)

I was reminded of this principle again the other day when Venkat asked me:

Hi,

I am working on Internationalization of my current project.

I have taken care most of the aspects like externalizing strings to resources, message file and formating date using COleDateTime::Format(). One scenario I have is I have to handle user input float/double values based on current Locale. ie When current Locale is German then I have to support value 3.000,67 (or) 300.000,4. I have gone through article CRTSynch from code project. Which ensures both C-runtime routine and current Thread locale context are in Sync. I need suggestion for handling float numbers based on current Locale as explained in example. Even if I use setLocale() still I am not getting expected result . eg: _tcstod( _T("3.000,6", NULL) should give me double value of 3000.6 instead it gives me 3.000 ie it is handling decimal symbol not the digit Grouping symbol.

Any type of suggestion is welcome.

Thanks,

Venkat.

Well, if one is using COM (which usually takes an LCID) to format the values into strings, then one should also use COM to parse them out of the string. In this case, VariantChangeTypeEx will do a nice job taking a Variant containing a BSTR and converting it to a Variant containing a Double -- just pass the right LCID and the parsing will simply work in strings like the one Venkat provided.

The code might look something like this (I am assuming COM has already been initialized since there were other COM calls going on!):

VARIANT vDouble, vString;
BSTR string = SysAllocString(L"3.000,6");

VariantInit(&vDouble);
VariantInit(&vString);

vString.vt = VT_BSTR;
vString.bstrVal = string;
VariantChangeType(&vDouble, &vString, 0, VT_R8);

VariantClear(&vString);
VariantClear(&vDouble);

You get the idea. The value in vDouble will be 3000.6, not 3.000. Behind the scenes it is doing a whole bunch of potential work here (well, actually I guess it is "undoing" some work in this case!) -- about as much as COM will do to format, in fact.

Interestingly, there is even an old 1999 Dr. GUI article that talks about using that function for the locale-specific parsing. :-)

The C Runtime does not have a function that will do full service parsing here, though since the string was not produced by the CRT anyway, it makes sense that the CRT would not know much about how to parse it later....

 

This post brought to you by Ö (U+00d6, a.k.a. LATIN CAPITAL LETTER O WITH DIARESIS)


# Haali on 10 Feb 2007 3:14 AM:

There is no need to call SysFreeString, VariantClear frees the BSTR itself.

# Michael S. Kaplan on 10 Feb 2007 8:05 AM:

Good point, Haali! :-)


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.

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