大阪市中央区 システムソフトウェア開発会社

営業時間:平日09:15〜18:15
MENU

C++でC風ライブラリを作る(文字列比較編2)

著者:高木信尚
公開日:2019/07/20
最終更新日:2019/07/20
カテゴリー:技術情報

高木です。おはようございます。

前回に引き続き、文字列比較編です。
今回は実際のコードを紹介していくことにします。

そういえば前回、strcoll関数相当のものは面倒なので割愛すると書きました。
実際にはstd::collateを使えば簡単に実装することはできます。
ただ、そもそも使用頻度が低いということもありますし、現在作っているライブラリはロケールの切り替えを想定していないということもあります。
また、仮にロケールを切り替えるにしても、私が普段よく使う処理系のひとつであるMinGW-w64はstd::localeで設定できるのはCロケールしかないという問題もあります。
そういうこともあって、やはりstrcoll関数相当のものは割愛ということにしたいと思います。

それでは順に実装していくことにします。

まずは基本からということで、ナル終端文字列どうしの単純比較からです。
まあ、素直な作りですね。

なお、char型とwchar_t型の文字列については多重定義することにします。
とくにchar型の文字列を扱うstd::strcmp関数はビルトイン関数のこともあるので標準ライブラリを使う方が性能がよいことも多いと思います。

namespace cloverfield
{
  template <typename charT>
  inline int strcmp(charT const* s1, charT const* s2)
  {
    auto ss1 = s1;
    auto ss2 = s2;

    while (*ss1 && *ss1 == *ss2)
    {
      ++ss1;
      ++ss2;
    }
    return *ss1 - *ss2;
  }

  inline int strcmp(char const* s1, char const* s2)
  {
    return std::strcmp(s1, s2);
  }

  inline int strcmp(wchar_t const* s1, wchar_t const* s2)
  {
    return std::wcscmp(s1, s2);
  }
}

続いて、一方または両方がstd::basic_stringクラステンプレートの場合について多重定義することにしましょう。

namespace cloverfield
{
  template <typename charT, typename traits, typename Allocator1, typename Allocator2>
  inline int strcmp(std::basic_string<charT, traits, Allocator1> const& s1, std::basic_string<charT, traits, Allocator2> const& s2)
  {
    return strcmp(s1.c_str(), s2.c_str());
  }

  template <typename charT, typename traits, typename Allocator>
  inline int strcmp(std::basic_string<charT, traits, Allocator> const& s1, charT const* s2)
  {
    return strcmp(s1.c_str(), s2);
  }

  template <typename charT, typename traits, typename Allocator>
  inline int strcmp(charT const* s1, std::basic_string<charT, traits, Allocator> const& s2)
  {
    return strcmp(s1, s2.c_str());
  }
}

std::basic_stringクラステンプレートあるいはstd::char_traitsクラステンプレートのcompareメンバ関数を使うという手もありますが、今回はナル終端文字列用の関数を内部的に呼び出すことで対応することにしました。

長くなってきたので、strncmp関数相当のものは次回にまわすことにしましょう。

    上に戻る