STLで大文字小文字の違いを無視して文字列比較

[戻る]
sunyopu 2005/07/24(日) 14:11:43
文字列比較について質問があります。

英語文字列同士を比較して、
同一かどうか判定する処理を作成しています。
ただし、大文字小文字のみの違いなら
一致していると判定したいです。

現在はC共通関数_stricmp()を使用し
以下のようにしています。

  std::string str1 = "ABCDE";
  std::string str2 = "abcde";

  if(_stricmp(str1.c_str(),str2.c_str()) == 0)
  {
    // 同じ文字列
  }

これと同等のことを、
STLのみで行うことはできるのでしょうか?

Ban 2005/07/24(日) 17:20:49
単純な実装だと例えばこんなのとか。

namespace foo {

int
stricmp(std::string lhs, std::string rhs)
{
    // 小文字に変換してから比較
    std::transform(lhs.begin(), lhs.end(), lhs.begin(), std::tolower);
    std::transform(rhs.begin(), rhs.end(), rhs.begin(), std::tolower);
    return lhs.compare(rhs);
}    

}

変換が無駄でいやだと思うなら、std::equal で比較関数を書けばよいと思います。

επιστημη 2005/07/25(月) 14:58:29
こんなんでいいのかしら?

#include <string>
#include <iostream>
#include <algorithm>
#include <locale>

struct equal_char_ignorecase {
  bool operator()(char x, char y) const {
    std::locale loc;
    return std::tolower(x,loc) == std::tolower(y,loc);
  }
};

bool icomp(const std::string& x, const std::string& y) {
  return x.size() == y.size() && 
     std::equal(x.begin(), x.end(), y.begin(), equal_char_ignorecase());
}

int main() {
  std::cout << (icomp("Hello","hElLo") ? "same" : "different") << std::endl;
}

sunyopu 2005/07/26(火) 17:21:17
[[解決]]
ご返事ありがとうございます。

大文字小文字の一致も含めて判定する場合は、
以下のようにしているので、

  std::string str1 = "ABCDE";
  std::string str2 = "abcde";

  if(str1.compare(str2) == 0)
  {
    // 同じ文字列
  }

  if(str1 == str2)
  {
    // 同じ文字列
  }

大文字小文字の一致を無視する場合も
STLのみですっきりコーディングできないかと
思い質問してみました。

_stricmp()の方がすっきりしそうなので、
これで行ってみます。

でも以下とか普段使わないので、
用法が勉強になりました。
 std::tolower(), std::equal()

ありがとうございました。

Ban 2005/07/26(火) 18:24:46
> 大文字小文字の一致を無視する場合もSTLのみですっきりコーディングできないかと
> 思い質問してみました。
> _stricmp()の方がすっきりしそうなので、これで行ってみます。

例えば私のやつを最初のsunyopuさんの形式にあわせるとこんな感じになります。
  if(foo::stricmp(str1,str2) == 0)
  {
    // 同じ文字列
  }

επιστημηさんのものだとこんな感じ。
  if(icomp(str1,str2))
  {
    // 同じ文字列
  }


「すっきり」の基準は呼ぶ側でなく、自分で実装するか否かということでしょうか。

VC専用で言語標準以外の機能を使ってもいいなら、
_stricmp 使うと何の実装に必要がない分だけ確かに楽だと思います。

そうでないなら、直接 _stricmp を使わずにラッパーなりを書くのでしょうから、
結局大差ないような気もします。
inline int my_stricmp(......){ return ::_stricmp(.......); }

古いスレッドには追加発言できません。