Board index » Visual Studio » CString to LPCSTR

CString to LPCSTR

Visual Studio9
I am getting an error

<error>

C2440: 'type cast' : cannot covert from 'CString' to 'LPCSTR'

<error>



I am using VS2005 and I am taking code out of CodeGuru and I am getting this

error message. I have read something about the CString length has change

using VS2005. How can I convert CString to LPCSTR? To be a little more

specific I am trying to StreamIn & StreamOut with a CRichEditCtrl.

--

Just Al


-
 

Re:CString to LPCSTR

Do you really want an LPCSTR? Wouldn't you rather have an LPCTSTR?



The code is probably incorrectly written, and probably should have said LPCTSTR. Reason

is that CString used to default to 8-bit characters in a standard build, but in VS2005,

they sensibly changed builds to default to Unicode. So code that was improperly written

would work in 8-bit builds, but correctly produces error messages when built in Unicode.



Note that when giving error messages like this, it is considered sensible to actually show

the source line that produced the error, and ideally the declarations of all variables

involved in the statement.

joe



On Fri, 28 Dec 2007 19:48:01 -0800, Al <Al@discussions.microsoft.com>wrote:



Quote
I am getting an error

<error>

C2440: 'type cast' : cannot covert from 'CString' to 'LPCSTR'

<error>



I am using VS2005 and I am taking code out of CodeGuru and I am getting this

error message. I have read something about the CString length has change

using VS2005. How can I convert CString to LPCSTR? To be a little more

specific I am trying to StreamIn & StreamOut with a CRichEditCtrl.

Joseph M. Newcomer [MVP]

email: newcomer@flounder.com

Web: www.flounder.com">www.flounder.com

MVP Tips: www.flounder.com/mvp_tips.htm">www.flounder.com/mvp_tips.htm

-

Re:CString to LPCSTR

This is one version that I have been trying to use but the same problem

arises with other versions of similar code. I have showed below where the

errors occur.





<code>

static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG

cb,

LONG *pcb)

{

CString *pstr = (CString *)dwCookie;



if( pstr->GetLength() < cb )

{

*pcb = pstr->GetLength();

<error>

memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

<error>

pstr->Empty();

}

else

{

*pcb = cb;

<error>

memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

<error>

*pstr = pstr->Right( pstr->GetLength() - cb );

}

return 0;

}

<code>



--

Just Al





"Joseph M. Newcomer" wrote:



Quote
Do you really want an LPCSTR? Wouldn't you rather have an LPCTSTR?



The code is probably incorrectly written, and probably should have said LPCTSTR. Reason

is that CString used to default to 8-bit characters in a standard build, but in VS2005,

they sensibly changed builds to default to Unicode. So code that was improperly written

would work in 8-bit builds, but correctly produces error messages when built in Unicode.



Note that when giving error messages like this, it is considered sensible to actually show

the source line that produced the error, and ideally the declarations of all variables

involved in the statement.

joe



On Fri, 28 Dec 2007 19:48:01 -0800, Al <Al@discussions.microsoft.com>wrote:



>I am getting an error

><error>

>C2440: 'type cast' : cannot covert from 'CString' to 'LPCSTR'

><error>

>

>I am using VS2005 and I am taking code out of CodeGuru and I am getting this

>error message. I have read something about the CString length has change

>using VS2005. How can I convert CString to LPCSTR? To be a little more

>specific I am trying to StreamIn & StreamOut with a CRichEditCtrl.

Joseph M. Newcomer [MVP]

email: newcomer@flounder.com

Web: www.flounder.com">www.flounder.com

MVP Tips: www.flounder.com/mvp_tips.htm">www.flounder.com/mvp_tips.htm



-

Re:CString to LPCSTR



"Al" <Al@discussions.microsoft.com>wrote in message



Quote
This is one version that I have been trying to use but the same problem

arises with other versions of similar code. I have showed below where the

errors occur.



Then act on Joe's advice.



Quote
CString *pstr = (CString *)dwCookie;



// I assume that you are sure that dwCookie is the address of a CString

// (and not for example a char *, wchar_t * or anything else)?



Quote
if( pstr->GetLength() < cb )

{

*pcb = pstr->GetLength();

<error>

memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

<error>



As Joe said



memcpy( pbBuff, (LPCTSTR)(*pstr), ((*pcb)+1)*(sizeof TCHAR) );



[I have added brackets which may or may not be necessary - my memory is a

seive on this so I play safe - and, with the "+1", I have copied the nul

TCHAR on the end. It's your job to make sure pbbuf is big enough.]



Dave

--

David Webber

Author of 'Mozart the Music Processor'

www.mozart.co.uk">www.mozart.co.uk

For discussion/support see

www.mozart.co.uk/mozartists/mailinglist.htm">www.mozart.co.uk/mozartists/mailinglist.htm



-

Re:CString to LPCSTR

Thanks for the help and the extra help. I was thinking that I had to convert

the CString to a LPCSTR and I wasn't getting the fact that I could just

change the code to LPCTSTR. Thanks for clearing that up.

--

Just Al





"David Webber" wrote:



Quote


"Al" <Al@discussions.microsoft.com>wrote in message

news:29FCF33E-3B59-400D-A227-3D363BE30A15@microsoft.com...



>This is one version that I have been trying to use but the same problem

>arises with other versions of similar code. I have showed below where the

>errors occur.



Then act on Joe's advice.



>CString *pstr = (CString *)dwCookie;



// I assume that you are sure that dwCookie is the address of a CString

// (and not for example a char *, wchar_t * or anything else)?



>if( pstr->GetLength() < cb )

>{

>*pcb = pstr->GetLength();

><error>

>memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

><error>



As Joe said



memcpy( pbBuff, (LPCTSTR)(*pstr), ((*pcb)+1)*(sizeof TCHAR) );



[I have added brackets which may or may not be necessary - my memory is a

seive on this so I play safe - and, with the "+1", I have copied the nul

TCHAR on the end. It's your job to make sure pbbuf is big enough.]



Dave

--

David Webber

Author of 'Mozart the Music Processor'

www.mozart.co.uk">www.mozart.co.uk

For discussion/support see

www.mozart.co.uk/mozartists/mailinglist.htm">www.mozart.co.uk/mozartists/mailinglist.htm





-

Re:CString to LPCSTR

On Fri, 28 Dec 2007 20:43:01 -0800, Al <Al@discussions.microsoft.com>wrote:



Quote
This is one version that I have been trying to use but the same problem

arises with other versions of similar code. I have showed below where the

errors occur.





<code>

static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG

cb,

LONG *pcb)

{

CString *pstr = (CString *)dwCookie;



if( pstr->GetLength() < cb )

****

This should be <=, and it is comparing the wrong value. It MUST be

if(pstr->GetLength() * sizeof(TCHAR) <= cb)

or you will overwrite the buffer. This code was obviously written by someone who didn't

understand Unicode, and you should post a correction to the codeproject article when you

are done.

****

Quote
{

*pcb = pstr->GetLength();

<error>

****

WHAT <error>? It would have been useful to know what kind of error occurred here! When

asking questions like this, you have to show BOTH the source line (and all declarations)

AND the error message!



However, one thing is wrong with this: it is supposed to be a byte count of the number of

characters to transfer, but instead it is given as a *character* count, which is

erroneous. It should have said

*pcb = pstr->GetLength() * sizeof(TCHAR);

****



Quote
memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

<error>

****

This one is obvious: it is caused by the erroneous use of LPCSTR instead of LPCTSTR. In

addition, the length is wrong; it should have been written as

memcpy(pbBuff, (LPCTSTR)*ptr, *pcb);

but note above that *pcb is erroneously computed, and until you apply the first

correction, the code as written using *pcb as the length is erroneous

*****

Quote
pstr->Empty();

}

else

{

*pcb = cb;

****

Note that this can be erroneous if cb is an odd number; to be absolutely correct, you

should make sure that this number is not an odd number in Unicode builds

****

Quote
<error>

memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

<error>

****

Same problem as above: the code is not Unicode-aware, and should have been LPCTSTR

****

Quote
*pstr = pstr->Right( pstr->GetLength() - cb );

*****

For the same reasons given above, this non-Unicode-aware code is erroneous. It must be

rewritten as

*pstr = pstr->Right(pstr->GetLenght() - (cb / sizeof(TCHAR));

which is another reason you must make sure cb is an even value, and truncate downwards if

it is not.



One of the better features of VS2005 defaulting to Unicode builds is that it does not

allow the kind of sloppiness that created this code to continue. Consider the error

messages a Good Thing, they kept fundamentally incorrect code from compiling and doing

serious damage.

joe



****

Quote
}

return 0;

}

<code>

Joseph M. Newcomer [MVP]

email: newcomer@flounder.com

Web: www.flounder.com">www.flounder.com

MVP Tips: www.flounder.com/mvp_tips.htm">www.flounder.com/mvp_tips.htm

-

Re:CString to LPCSTR

"Al" <Al@discussions.microsoft.com>wrote in message

Quote
Thanks for the help and the extra help. I was thinking that I had to

convert

the CString to a LPCSTR and I wasn't getting the fact that I could just

change the code to LPCTSTR. Thanks for clearing that up.

--

Just Al





The proper thing to do depends on what format of text the RichEdit control

is expecting. Since you're apparently building the project with UNICODE

(since CString doesn't cast to LPCSTR), I assume the RichEdit control is

expecting Unicode text. In that case, yes, you do can cast the CString to

LPCTSTR (which translates to LPCWSTR) and put that into the byte buffer of

the RichEdit control. But the memcpy() last parameter needs to be limited

by the minimum size of the byte buffer, or the length of the string. I like

to use StringCbCopy() to ensure the destination buffer does not get

overwritten.



Also, the RichEdit callback works such that if the entire contents can't fit

into the byte buffer, then you get called back again to put the next chunk

of contents into the byte buffer. Your callback needs to remember where it

left off the previous time so it can start at that point in the string. I

don't see the code to do that here.



-- David





-

Re:CString to LPCSTR

Joseph



Thanks for all of the indepth explaination of the errors and with the

corrections on the code. I appreciate everyones help on this.



THANKS!



--

Just Al





"Joseph M. Newcomer" wrote:



Quote
On Fri, 28 Dec 2007 20:43:01 -0800, Al <Al@discussions.microsoft.com>wrote:



>This is one version that I have been trying to use but the same problem

>arises with other versions of similar code. I have showed below where the

>errors occur.

>

>

><code>

>static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG

>cb,

>LONG *pcb)

>{

>CString *pstr = (CString *)dwCookie;

>

>if( pstr->GetLength() < cb )

****

This should be <=, and it is comparing the wrong value. It MUST be

if(pstr->GetLength() * sizeof(TCHAR) <= cb)

or you will overwrite the buffer. This code was obviously written by someone who didn't

understand Unicode, and you should post a correction to the codeproject article when you

are done.

****

>{

>*pcb = pstr->GetLength();

><error>

****

WHAT <error>? It would have been useful to know what kind of error occurred here! When

asking questions like this, you have to show BOTH the source line (and all declarations)

AND the error message!



However, one thing is wrong with this: it is supposed to be a byte count of the number of

characters to transfer, but instead it is given as a *character* count, which is

erroneous. It should have said

*pcb = pstr->GetLength() * sizeof(TCHAR);

****



>memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

><error>

****

This one is obvious: it is caused by the erroneous use of LPCSTR instead of LPCTSTR. In

addition, the length is wrong; it should have been written as

memcpy(pbBuff, (LPCTSTR)*ptr, *pcb);

but note above that *pcb is erroneously computed, and until you apply the first

correction, the code as written using *pcb as the length is erroneous

*****

>pstr->Empty();

>}

>else

>{

>*pcb = cb;

****

Note that this can be erroneous if cb is an odd number; to be absolutely correct, you

should make sure that this number is not an odd number in Unicode builds

****

><error>

>memcpy(pbBuff, (LPCSTR)*pstr, *pcb );

><error>

****

Same problem as above: the code is not Unicode-aware, and should have been LPCTSTR

****

>*pstr = pstr->Right( pstr->GetLength() - cb );

*****

For the same reasons given above, this non-Unicode-aware code is erroneous. It must be

rewritten as

*pstr = pstr->Right(pstr->GetLenght() - (cb / sizeof(TCHAR));

which is another reason you must make sure cb is an even value, and truncate downwards if

it is not.



One of the better features of VS2005 defaulting to Unicode builds is that it does not

allow the kind of sloppiness that created this code to continue. Consider the error

messages a Good Thing, they kept fundamentally incorrect code from compiling and doing

serious damage.

joe



****

>}

>return 0;

>}

><code>

Joseph M. Newcomer [MVP]

email: newcomer@flounder.com

Web: www.flounder.com">www.flounder.com

MVP Tips: www.flounder.com/mvp_tips.htm">www.flounder.com/mvp_tips.htm



-

Re:CString to LPCSTR

Actually, it does take that into account; the string = string.Right(...) handles lopping

off the first part. Of course, since it isn't Unicode-aware, it gets it wrong in a number

of ways, but once fixed for Unicode-awareness, it should handle that situation (I would

have done .Mid(cb/sizeof(TCHAR)) which seems easier, but Right(), done right, should work)

joe



On Sat, 29 Dec 2007 14:40:14 GMT, "David Ching" <dc@remove-this.dcsoft.com>wrote:



Quote
"Al" <Al@discussions.microsoft.com>wrote in message

news:3E2D7296-DB98-4F4E-8A73-D0D161E859CF@microsoft.com...

>Thanks for the help and the extra help. I was thinking that I had to

>convert

>the CString to a LPCSTR and I wasn't getting the fact that I could just

>change the code to LPCTSTR. Thanks for clearing that up.

>--

>Just Al

>



The proper thing to do depends on what format of text the RichEdit control

is expecting. Since you're apparently building the project with UNICODE

(since CString doesn't cast to LPCSTR), I assume the RichEdit control is

expecting Unicode text. In that case, yes, you do can cast the CString to

LPCTSTR (which translates to LPCWSTR) and put that into the byte buffer of

the RichEdit control. But the memcpy() last parameter needs to be limited

by the minimum size of the byte buffer, or the length of the string. I like

to use StringCbCopy() to ensure the destination buffer does not get

overwritten.



Also, the RichEdit callback works such that if the entire contents can't fit

into the byte buffer, then you get called back again to put the next chunk

of contents into the byte buffer. Your callback needs to remember where it

left off the previous time so it can start at that point in the string. I

don't see the code to do that here.



-- David



Joseph M. Newcomer [MVP]

email: newcomer@flounder.com

Web: www.flounder.com">www.flounder.com

MVP Tips: www.flounder.com/mvp_tips.htm">www.flounder.com/mvp_tips.htm

-