Boost is a full blown C++ template framework with many different modules and ten thousands of code lines. It contains many useful template utilities and should be a major reference for ambitious C++ programmers, who are interested in template programming. Boost contains some good portions of C++ template magic such as the hilarious meta programming and functional programming modules. But this complex network of modules, classes and functions is also a big overhead, if you only want to use some of the helper utilities. One of these helper utilities is boost::iequals. boost::iequals offers a simple interface for case insensitive string comparison.
The following code searches for the literal ‘world’ in a simple utf8/ascii std::string object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
int main() { static const std::string myString = "Hello WoRlD!"; static const std::string world = "world"; /// Or as lambda auto firstOf = std::search( myString.begin(), myString.end(), world.begin(), world.end(), [] ( std::string::value_type a, std::string::value_type b ) -> bool { return std::tolower( a ) == std::tolower( b ); } ); if ( firstOf != myString.end() ) { std::cout << std::string( firstOf, firstOf + world.size() ); } else { std::cout << "Not found!" << std::endl; } return 0; } |
It’s also possible to search in a wide string without any usage of boost and only a few lines of code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
int main() { static const std::wstring myString = L"Hello WoRlD!"; static const std::wstring world = L"world"; /// Or as lambda auto firstOf = std::search( myString.begin(), myString.end(), world.begin(), world.end(), [] ( std::wstring::value_type a, std::wstring::value_type b ) -> bool { return std::tolower( a ) == std::tolower( b ); } ); if ( firstOf != myString.end() ) { std::cout << std::string( firstOf, firstOf + world.size() ); } else { std::cout << "Not found!" << std::endl; } return 0; } |
In most of the cases, this is the ugliest and slowest solution. This is a general rule of thumb:
- If the data you are working on, is not in a suitable format and you access the data more than a few times, convert the data to a suitable format.
In other words:
- If you search many times for case insensitive substrings, convert all strings you work on, to lower or upper case, so you don’t have to convert two strings every time you search for a specific substring.
The advantages of this rule is obvious:
- More performance( N function calls less( N >= 0, N <= src.size() ) )
- Less error-prone
- Clean code
Lower/Uppercase string conversion can be very easily achieved with std::transform:
|
|
int main() { const std::string dataChunk( "Hello World!" ); std::string lwDataChunk( dataChunk.size() ); std::transform( dataChunk.begin(), dataChunk.end(), lwDataChunk.begin(), std::tolower ); } |
All code samples are fully compatible with Visual Studio 2010, GCC 4.5 and Clang 2.9.