C++でC風ライブラリを作る(文字列比較編3)
高木です。おはようございます。
文字列比較編も前々回、前回に引き続き3回目となりました。
今回で最後です(「C++でC風ライブラリを作る」は続きますよ)。
それでは早速いってみましょう。
前回はstrcmp
関数を実装しました。
srcoll
関数相当のものは扱わない方針ですので、今回はstrncmp
関数相当のものを作ることにします。
まずはナル終端文字列どうしの比較です。
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 | namespace cloverfield { template <typename charT> inline int strncmp(charT const* s1, charT const* s2, std::size_t n) { auto ss1 = s1; auto ss2 = s2; while (*ss1 && (*ss1 == *ss2)) { ++ss1; ++ss2; if (ss1 - s1 >= n) return 0; } return *ss1 - *ss2; } inline int strncmp(char const* s1, char const* s2, std::size_t n) { return std::strncmp(s1, s2, n); } inline int strncmp(wchar_t const* s1, wchar_t const* s2, std::size_t n) { return std::wcsncmp(s1, s2, n); } } |
strcmp
関数とよく似ていますが、第3引数n
が増えた分だけ微妙に異なっています。
また、strcmp
関数と同様、char
型の文字列についてはstd::strncmp
関数を、wchar_t
型の文字列についてはstd::wcsncmp
関数を使っています。
続いて、比較対象の文字列の一方、または両方がstd::basic_string
の場合について多重定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | namespace cloverfield { template <typename charT, typename traits, typename Allocator1, typename Allocator2> inline int strncmp(std::basic_string<charT, traits, Allocator1> const& s1, std::basic_string<charT, traits, Allocator2> const& s2, std::size_t n) { return strncmp(s1.c_str(), s2.c_str(), n); } template <typename charT, typename traits, typename Allocator> inline int strncmp(std::basic_string<charT, traits, Allocator> const& s1, charT const* s2, std::size_t n) { return strncmp(s1.c_str(), s2, n); } template <typename charT, typename traits, typename Allocator> inline int strncmp(charT const* s1, std::basic_string<charT, traits, Allocator> const& s2, std::size_t n) { return strncmp(s1, s2.c_str(), n); } } |
これも安直な方法で実装しています。
これで文字列比較編は終わりですが、標準Cライブラリにはない大文字・小文字を区別せずに比較するとか、全角・半角を区別せずに比較するとか、ひがらな・カタカナを区別せずに比較するとかのstrcoll
関数とはまた違った形で一種の辞書順比較を行う関数もそのうち作りたいと思います。