Problem:

In the C time, we used to use sscanf to read data from string as following:


char strUserName[20], strPassword[20];
// if the content of m_recvBuff is “Microsoft Bill”.
sscanf((const char *)m_recvBuff, “%s %s”, strUserName, strPassword);

And when you first get CString in sight, you may write the similar code:


CString strUserName, strPassword;
// if the content of m_recvBuff is “Microsoft Bill”.
sscanf((const char *)m_recvBuff, “%s %s” , strUserName, strPassword);

Unfortunately, it can not work as you expected and, in most cases, the process will crash.

Solution:

First, you should not be using sccanf, since this is not Unicode-aware. You should use _stscanf which allows for Unicode.  In addition, it is not a “safe” methodology because it can generate buffer overruns.

Second, the problem here is that you are doing something profoundly illegal: you are passing a CString pointer to a call that expects an LPTSTR.  You can’t do this.  It won’t work, and it surprised me that it merely produces an erroneous result instead of crashing with an access fault, heap corruption assert, or some similar fatal situation.

After all, you can use scanf safely, but you should try to use the new _s versions to make them more “trustworthy”.  Here’s some info on it:

http://msdn2.microsoft.com/en-us/library/w40768et(VS.80).aspx

The problem you’re having is that you are not actually passing the buffers
of the CStrings to the scanf function. Take a look at the GetBuffer()
function in CString.  Also, this function might be useful to you:

http://msdn2.microsoft.com/en-us/library/k4ftfkd2(VS.80).aspx

In additional, You can cast a CString to type LPCTSTR to get read-only access to the contents of the string.  However,
(1)  You can’t cast a CString to type LPTSTR to get writeable access.  You have to do something like call GetBufferSetLength and make sure you set the buffer large enough.
(2)  In variable parameters to sscanf, you can’t expect any casting to be done automatically, you have to code the casts.

But if you take enouth care of your code, sscanf may be not necessarily dangerous. You should check the length of the string and make sure you’ve allocated large enough sizes for your other variables then you won’t have buffer overruns.

At last, in MFC, the following code may be the general solution:


CString strUserName;
CString strPassword;
m_recBuff.Trim(); // remove leading and trailing space
int n = m_recvBuff.Find(_T(” “));
if(n>0) /* has space */
{
strUserName = m_recvBuff.Left(n);
strPassword = m_recvBuff.Mid(n + 1);
strPassword.Trim();
}

Unlike sscanf, which should no longer be considered a viable mechanism for any purpose dealing with string outputs, this actually works and is safe.  It will not cause a buffer overrun.  You should make it a practice to avoid mechanisms that can cause buffer overrun.

The next paragraph is writen by Joseph M. Newcomer, as reference.

There is no economy in using obsolete and unsafe mechanisms.  sscanf is overused and I consider it one of the design errors of the C language.  I have never yet found a situation in which I would trust it to do the right thing in the presence of bad input, and the best I can say for it is that it is only suitable for use in the most naively trusting situations possible.  I never use it, and I have never used it since I first learned of it.  I had, as a beginner, used and trusted such mechanisms in languages I learned in the 1960s, and I quickly learned that such mechanisms are simply not to be trusted.  I doubt if I have used such a mechanism since about 1967 or so.  It was a bad idea then and it remains a bad idea today.  The passage of 40 years does not make a bad idea good.