CompareNoCase does not work as expected
July 30th, 2008
Recently I found a program of mine doing all kind of unexpected things because of CString::CompareNoCase() not returning what I expected it to return.
My application usered names containing the characters: é, è, à. Somewhere in my app I used the given name to search the corresponding object in a list. Since the given names had to be (case insensitive) unique I stored those names in uppercase format.
Afterwards I compared (in a case insensitive way) the given name with the uppercase name of each object in the list.
And that went unexpectedly wrong! Look at the following code snippet:
CString strText("élève - à la façon - château"); CString strTextUpper(strText); strTextUpper.MakeUpper(); // Upper case the original int match = strTextUpper.CompareNoCase(strText); //does not match
For CString::CompareNoCase I read:
Compares this CString object with another string using the generic-text function _tcsicmp. The generic-text function _tcsicmp, which is defined in TCHAR.H, maps to either _stricmp, _wcsicmp, _mbsicmp depending on the character set that is defined at compile time. Each of these functions performs a case-insensitive comparison of the strings, and is not affected by locale.
While digging deeper in MSDN I discovered the existence of CString::CollateNoCase for which I read:
Compares this CString object with another string using the generic-text function _tcscoll. The generic-text function _tcscoll, which is defined in TCHAR.H, maps to either stricoll, wcsicoll, or _mbsicoll depending on the character set that is defined at compile time. Each of these functions performs a case-insensitive comparison of the strings, according to the code page currently in use.
This knowledge led me to two workarounds:
- Use
CString::CollateNoCaseinstead ofCompareNoCase. - Although the help says it works independent of the locale, before calling
CString::CompareNoCaseset (theLC_CTYPEpart of the) the locale. e.g.:
setlocale(LC_CTYPE, "french-belgian");
Finally my confidence in MFC’s CString comparison functions isn’t great after I discovered this. And that’s why I wrote my own ever-working workaround:
int MyCompareNoCase(LPCTSTR str1, LPCTSTR str2) { CString strTmp1(str1); CString strTmp2(str2); strTmp1.MakeUpper(); strTmp2.MakeUpper(); return strTmp1.Compare(strTmp2); }





