C++字符串完全指引之一:Win32 字符编码
2010-10-15 09:08:06 来源:Web开发网当使用 GetConfigFileName() 检查尾部的''\''时,它寻找安装目录名中最后的非0字节,看它是等于''\''的,所以没有重新增加一个''\''。结果是代码返回了错误的文件名。
哪里出错了呢?看看上面两个被用蓝色高量显示的字节。斜杠''\''的值是0x5c。'' ''的值是83 5c。上面的代码错误的读取了一个 trail byte,把它当作了一个字符。
正确的后向遍历方法是使用能够识别DBCS字符的函数,使指针移动正确的字节数。下面是正确的代码。(指针移动的地方用红色标明)
bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
{
char szConfigFilename[MAX_PATH];
// Read install dir from registry... we''ll assume it succeeds.
// Add on a backslash if it wasn''t present in the registry value.
// First, get a pointer to the terminating zero.
char* pLastChar = _mbschr ( szConfigFilename, '''' );
// Now move it back one double-byte character.
pLastChar = CharPrev ( szConfigFilename, pLastChar );
if ( *pLastChar != ''\'' )
_mbscat ( szConfigFilename, "\" );
// Add on the name of the config file.
_mbscat ( szConfigFilename, "config.bin" );
// If the caller''s buffer is big enough, return the filename.
if ( _mbslen ( szInstallDir ) >= nBuffSize )
return false;
else
{
_mbscpy ( pszName, szConfigFilename );
return true;
}
}
上面的函数使用CharPrev() API使pLastChar向后移动一个字符,这个字符可能是两个字节长。在这个版本里,if条件正常工作,因为lead byte永远不会等于0x5c。
让我们来想象一个违背规则1的场合。例如,你可能要检测一个用户输入的文件名是否多次出现了'':''。如果,你使用++操作来遍历字符串,而不是使用CharNext(),你可能会发出不正确的错误警告如果恰巧有一个trail byte它的值的等于'':''的值。
与规则2相关的关于字符串索引的规则:
2a. 永远不要使用减法去得到一个字符串的索引。
违背这条规则的代码和违背规则2的代码很相似。例如,
char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1];
这和向后移动一个指针是同样的效果。
回到关于str***()和_mbs***()的区别
现在,我们应该很清楚为什么_mbs***()函数是必需的。Str***()函数根本不考虑DBCS字符,而_mbs***()考虑。如果,你调用strrchr("C:\ ", ''\''),返回结果可能是错误的,然而_mbsrchr()将会认出最后的双字节字符,返回一个指向真的''\''的指针。
关于字符串函数的最后一点:str***()和_mbs***()函数认为字符串的长度都是以char来计算的。所以,如果一个字符串包含3个双字节字符,_mbslen()将会返回6。Unicode函数返回的长度是按wchar_t来计算的。例如,wcslen(L"Bob")返回3。
更多精彩
赞助商链接