我有一个基于Windows 7 SP1 Visual Studio 2010 SP1构建的应用程序。
似乎CompareString
在Windows 7和Windows XP上的工作方式不同。我正在创建EndsWith
/ StartsWith
- 类似(请参阅C#String.EndsWith
)方法,但它在Windows 7上按预期工作,但不在Windows XP上。
以下是我的StartsWith
和EndsWith
:
bool String::StartsWith( const String& value, bool bCaseSensitive ) const
{
if(this->strLen == 0 || value.strLen == 0)
return false;
DWORD flags;
if(bCaseSensitive == false)
flags = LINGUISTIC_IGNORECASE;
else
flags = NORM_LINGUISTIC_CASING;
if( CSTR_EQUAL == CompareStringW(LOCALE_USER_DEFAULT, flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)) )
return true;
else if(CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)))
return true;
else if(CSTR_EQUAL == CompareStringW(GetThreadLocale(), flags, this->_str, static_cast<int>(value.strLen), value._str, static_cast<int>(value.strLen)))
return true;
else
return false;
}
bool String::EndsWith( const String& value, bool bCaseSensitive ) const
{
if(this->strLen == 0 || value.strLen == 0)
return false;
DWORD flags;
if(bCaseSensitive == false)
flags = LINGUISTIC_IGNORECASE;
else
flags = NORM_LINGUISTIC_CASING;
size_t maxLen;
if(this->strLen < value.strLen)
maxLen = this->strLen;
else
maxLen = value.strLen;
LPCWSTR szStartOffset;
if(maxLen == this->strLen)
szStartOffset = this->_str;
else
szStartOffset = (this->_str + (this->strLen - value.strLen));
if( CSTR_EQUAL == CompareStringW(LOCALE_USER_DEFAULT, flags, szStartOffset, static_cast<int>(maxLen), value._str, static_cast<int>(maxLen)) )
return true;
else if(CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, flags, szStartOffset, static_cast<int>(maxLen), value._str, static_cast<int>(maxLen)))
return true;
else if(CSTR_EQUAL == CompareStringW(GetThreadLocale(), flags, szStartOffset, static_cast<int>(maxLen), value._str, static_cast<int>(maxLen)))
return true;
else
return false;
}
如果有人能帮助我,我会非常感激。
答案 0 :(得分:1)
所以有各种各样的事情。
首先,CompareString在出错时返回0,正如您所看到的,我不会检查它。在Windows XP上,它确实失败了,并且GetLastError()设置为1004 =“无效标志。”。错误是下一期的线索。
其次,我总是使用一个标志或另一个标志,而在Windows XP上,NORM_LINGUISTIC_CASING会导致1004错误。由于此函数的默认行为区分大小写,因此大部分时间并非真正需要此标志,并且标志可以设置为0.
我创建了一个实现StartsWith的演示程序: stringtest.cpp
// cl /MTd /DUNICODE /D_UNICODE_ stringtest.cpp
// MTd - statically compile libcrt to binary, this way you don't have to copy msvcrtd100.dll etc to the XP machine.
#include <windows.h>
#include <cstdio>
int StartsWith(LCID locale, const WCHAR* szOrg, const WCHAR* szValue, bool sensitive, bool expected /* Can be used for asserts. */)
{
int retval(0)
DWORD flags = sensitive ? 0 : NORM_IGNORECASE; // You could replace 0 with NORM_LINGUISTIC_CASING to make it fail on Windows XP.
int cchValue = lstrlenW(szValue);
// if szOrg can't hold szValue, it doesn't start with szValue.
if( cchValue > lstrlenW(szOrg) )
return CSTR_LESS_THAN;
// We trick CompareString to think szOrg is the same length as szValue.
// This is how we check only the cchValue first characters of szOrg.
retval = CompareStringW(locale, flags, szOrg, cchValue, szValue, cchValue);
// You could assert on retval and parameter 'expected '.
return(retval);
}
// Some compiler magic..
#define SHOWBOOL(expr) { \
int ret = expr; \
DWORD gle=GetLastError(); /* Cache GLE in case printf changes it. */ \
printf( "%s = %s\r\n", ( ret == CSTR_EQUAL ? "true" : "false"), #expr ); \
printf("GetLastError() = %d - ret = %d\r\n\r\n", gle, ret); \
}
// Named this way since we get the expression to console, easier to read.
bool ExpectsTrue = true;
bool ExpectsFalse = false;
bool Sensitive = true;
bool Insensitive = false;
int main(int argc, WCHAR* argv[])
{
SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(LOCALE_USER_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"hello", Insensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(LOCALE_SYSTEM_DEFAULT, L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetThreadLocale(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"Hello", Sensitive, ExpectsTrue) );
SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Sensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"hello", Insensitive, ExpectsFalse) );
SHOWBOOL( StartsWith(GetSystemDefaultLCID(), L"Hello World", L"1Hello", Sensitive, ExpectsFalse) );
return(NO_ERROR);
}