a string which can be used ala std::string, preserves case, but comparisons are not case sensitive.
case insensitive string
#include <string>
#include <iostream>
#include <cctype>
// case insensitive character traits
// inherited copy (preserves case),
// case insensitive comparison, search
struct traits_nocase : std::char_traits<char>
{
static bool eq( const char& c1, const char& c2 )
{ return toupper(c1) == toupper(c2) ; }
static bool lt( const char& c1, const char& c2 )
{ return toupper(c1) < toupper(c2) ; }
static int compare( const char* s1, const char* s2, size_t N )
{
return strncasecmp( s1, s2, N ) ; // posix
// mirosoft C++ - use _strnicmp instead
}
static const char* find( const char* s, size_t N, const char& a )
{
for( size_t i=0 ; i<N ; ++i )
if( toupper(s[i]) == toupper(a) ) return s+i ;
return 0 ;
}
static bool eq_int_type ( const int_type& c1, const int_type& c2 )
{ return toupper(c1) == toupper(c2) ; }
};
// string preserves case; comparisons are case insensitive
typedef std::basic_string< char, traits_nocase > string_nocase ;
// make string_nocase work like a std::string
// with streams using std::char_traits
// std::basic_istream< char, std::char_traits<char> > (std::istream) and
// std::basic_ostream< char, std::char_traits<char> > (std::ostream)
inline std::ostream& operator<< ( std::ostream& stm, const string_nocase& str )
{ return stm << reinterpret_cast<const std::string&>(str) ; }
inline std::istream& operator>> ( std::istream& stm, string_nocase& str )
{
std::string s ; stm >> s ;
if(stm) str.assign(s.begin(),s.end()) ;
return stm ;
}
inline std::istream& getline( std::istream& stm, string_nocase& str )
{
std::string s ; std::getline(stm,s) ;
if(stm) str.assign(s.begin(),s.end()) ;
return stm ;
}
// some examples of using string_nocase
#include <fstream>
#include <iterator>
#include <algorithm>
#include <map>
using namespace std;
int main()
{
string_nocase str1 = "http://www.daniweb.com/forums/forum8.html" ;
string_nocase str2 = "Http://www.DaniWeb.com/Forums/FORUM8.html" ;
cout << "str1 == str2 ? " << boolalpha << (str1==str2) << '\n' ;
string_nocase sub_str ;
cout << "string to find? " ; getline(cin,sub_str) ;
if( str1.find( sub_str ) != string_nocase::npos )
cout << "found " << sub_str << " in " << str1 << '\n' ;
ifstream file(__FILE__) ;
istream_iterator<string_nocase> begin(file), end ;
cout << "#includes: " << count( begin, end, "#INCLUDE" ) << '\n' ;
map<string_nocase,int> phone_book ;
phone_book[ "SALEM" ] = -72 ;
phone_book[ "~s.o.s~" ] = 1234567 ;
phone_book[ "salem" ] = 9999999 ;
cout << phone_book[ "~S.O.S~" ] << '\t' << phone_book[ "SALEM" ] << '\n' ;
}
// what we have done is customize the character traits policy
// std::basic_string is also policy free wrt memory management
// see http://www.ddj.com/dept/cpp/184403784 for some examples of
// customizing the memory allocator policy.
/**
Output:
> g++ -Wall -std=c++98 string_nocase.cpp && ./a.out
str1 == str2 ? true
string to find? OM/FOR
found OM/FOR in http://www.daniweb.com/forums/forum8.html
#includes: 7
1234567 9999999
*/
~s.o.s~ 2,560 Failure as a human Team Colleague Featured Poster
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.