std::stringは==で比較すると、大文字小文字を区別する。いまvector<string>があってここからある文字列が存在するかを調べたいが、大文字小文字を無視して比較したいとする。
普通にstrcmpiなどでやってしまうのが簡単だが、せっかくなのでstd::stringを調べてこれを改良してやる方法。
std::stringは以下のようにtypedefされている。
1 |
typedef basic_string<char, char_traits<char>, allocator<char> > string; |
basic_stringのテンプレート第2引数のchar_traitsが、文字列の比較の実装などを提供するクラスになっている、==演算でこのクラスのstatic関数compareが呼ばれる。
よってこのchar_traitsを自分で実装し、そこでCaseInsensitiveに扱う関数をつくり、basic_stringの第2引数にこれを渡せばいいはず。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <string> #include <vector> using namespace std; struct ci_char_traits : public char_traits < char > { static int compare(const char *s1, const char *s2, size_t n) { return memicmp(s1, s2, n); } }; int main(int argc, char* argv[]) { string normal; normal = "eee"; bool b = (normal=="eeE"); basic_string<char, ci_char_traits> cistring; cistring = "eee"; b = (cistring=="eeE"); cistring = "Eee"; b = (cistring=="eEE"); b = (cistring=="Eee"); b = (cistring==""); b = (cistring=="fff"); return 0; } |
vectorのfindでも動いた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <string> #include <vector> #include <algorithm> using namespace std; struct ci_char_traits : public char_traits < char > { static int compare(const char *s1, const char *s2, size_t n) { return memicmp(s1, s2, n); } }; int main(int argc, char* argv[]) { vector<string> normal; normal.push_back("aaa"); normal.push_back("bbb"); normal.push_back("ccc"); bool b = find(normal.begin(), normal.end(), "bbB") != normal.end(); vector<basic_string<char, ci_char_traits> > cistring; cistring.push_back("aaa"); cistring.push_back("bbb"); cistring.push_back("ccc"); b = find(cistring.begin(), cistring.end(), "bbB") != cistring.end(); return 0; } |
今回はこれが動いたが実際にはchar_traitsの他の関数が呼ばれるかもしれないのか良くわからないので、注意が必要。