Doing a Case-Insensitive String Comparison

Problem

You have two strings, and you want to know if they are equal, regardless of the case of the characters. For example, "cat" is not equal to "dog," but "Cat," for your purposes, is equal to "cat," "CAT," or "caT."

Solution

Compare the strings using the equal standard algorithm (defined in ), and supply your own comparison function that uses the toupper function in (or towupper in for wide characters) to compare the uppercase versions of characters. Example 4-21 offers a generic solution. It also demonstrates the use and flexibility of the STL; see the discussion below for a full explanation.

Example 4-21. Case-insensitive string comparison

 

1 #include 
2 #include 
3 #include 
4 #include 
5 #include 
6 
7 using namespace std;
8
9 inline bool caseInsCharCompareN(char a, char b) {
10 return(toupper(a) == toupper(b));
11 }
12
13 inline bool caseInsCharCompareW(wchar_t a, wchar_t b) {
14 return(towupper(a) == towupper(b));
15 }
16
17 bool caseInsCompare(const string& s1, const string& s2) {
18 return((s1.size( ) == s2.size( )) &&
19 equal(s1.begin( ), s1.end( ), s2.begin( ), caseInsCharCompareN));
20 }
21
22 bool caseInsCompare(const wstring& s1, const wstring& s2) {
23 return((s1.size( ) == s2.size( )) &&
24 equal(s1.begin( ), s1.end( ), s2.begin( ), caseInsCharCompareW));
25 }
26
27 int main( ) {
28 string s1 = "In the BEGINNING...";
29 string s2 = "In the beginning...";
30 wstring ws1 = L"The END";
31 wstring ws2 = L"the endd";
32
33 if (caseInsCompare(s1, s2))
34 cout << "Equal!
";
35
36 if (caseInsCompare(ws1, ws2))
37 cout << "Equal!
";
38 }

 

Discussion

The critical part of case-insensitive string comparison is the equality test of each corresponding pair of characters, so let's discuss that first. Since I am using the equal standard algorithm in this approach but I want it to use my special comparison criterion, I have to create a standalone function to handle my special comparison.

Lines 9-15 of Example 4-21 define the functions that do the character comparison, caseInsCharCompareN and caseInsCharCompareW . These use toupper and towupper to convert each character to uppercase and then return whether they are equal.

Once I have my comparison functions complete, it's time to use a standard algorithm to handle applying my comparison functions to arbitrary sequences of characters. The caseInsCompare functions defined in lines 17-25 do just that using equal. There are two overloads, one for each character type I care about. They both do the same thing, but each instantiates the appropriate character comparison function for its character type. For this example, I overloaded two ordinary functions, but you can achieve the same effect with templates. See the sidebar "Should I Use a Template?" for a discussion.

equal compares two sequence ranges for equality. There are two versions: one that uses operator==, and another that uses whatever binary predicate (i.e., takes two arguments and returns a bool) function object you supply. In Example 4-21, caseInsCharCompareN and W are the binary predicate functions.

But that's not all you have to doyou need to compare the sizes, too. Consider equal's declaration:

template
bool equal(InputIterator1 first1, InputIterator1 last1,
 InputIterator2 first2, BinaryPredicate pred);

Let n be the distance between first1 and last1, or in other words, the length of the first range. equal returns true if the first n elements of both sequences are equal. That means that if, given two sequences where the first n elements are equal, and the second sequence has more than n elements, equal will return true. Include a size check in your comparison to avoid this false positive.

You don't need to encapsulate this logic in a function. Your code or your client's code can just call the algorithm directly, but it's easier to remember and cleaner to write this:

if (caseInsCompare(s1, s2)) {
// they are equal, do something

than this:

if ((s1.size( ) == s2.size( )) &&
 std::equal(s1.begin( ), s1.end( ), s2.begin( ), caseInsCharCompare)) {
// they are equal, do something

whenever you want to do a case-insensitive string comparison.

Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index



C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net