How to convert CString to long? VC++

9.5k views Asked by At

How to convert CString to long in VC++. I have used atol but it is throwing error.

long ldata = atol(str);

Error no suitable conversion from CString to const char*.

3

There are 3 answers

0
Barmak Shemirani On BEST ANSWER

As mentioned earlier, you are using Unicode. You have to use Unicode for other functions:

long ldata = _wtol(str);

Somewhere inside CString declarations is something like this:

#ifdef UNICODE
#define CString CStringW
#else 
#define CString CStringA
#endif

When project is compiled as Unicode, CString becomes wide char CStringW, so you have to use wide char version of atol which is _wtol and same for every other string function.

0
js sol On

from https://msdn.microsoft.com/en-us/library/awkwbzyc.aspx

"To use a CString object as a C-style string, cast the object to LPCTSTR."

So str should be casted to LPCTSTR like this: atol((LPCTSTR)str);

0
Ivan On

atol(CStringA(xxx)) or _ttol

atol((LPCTSTR)str luckily doesn't compile, but if it did, it would likely give the wrong result, see below.

Someone made a terrible decision to store Windows Unicode characters as UTF16 in CStrings, leading to the CStringW and CStringA horror. (16 bits is not enough to store all Unicode characters anyway, see the bat example.)

If you convert the CString to CStringA, (and then to a null terminated string pointer if you think that's better than hoping the compiler will do it,) then atol should have the ASCII string it wants.

The reason the last option in the software example doesn't give 1000 is that the CStringW is storing two bytes for the 1 (and two more for each subsequent character), an ASCII '1' and a null byte. Just casting the pointer to an ASCII null terminated string pointer makes the string look like a null terminated string with just a 1 in it. So keep well clear of any (LPCTSTR) suggestions.

Example

Reason

Converting to CStringA should work for 16-bit-wide or 8-bit-wide character strings, so you shouldn't have to pollute your software with horrible compiler directives like #ifdef UNICODE.

On systems where it is available, you can use _ttol, which is like _atol and _wtol, but (like the solution above) will work regardless of whether the compiler directive UNICODE is active or not.

Note that there are other functions like _atol_l which will work using a locale definition that may be useful if you want to read integers from strings like "400.456 Deutsch Marks" or "400,456 pounds sterling".