大文字と小文字を区別しな文字列比較にはC++[定休日]

StackOverflow https://stackoverflow.com/questions/11635

  •  08-06-2019
  •  | 
  •  

質問

には、どうするのがベストな行う上での大文字と小文字を区別しな文字列比較にはC++なしの変換文字列をすべて大文字はすべて小文字?

をご用意いただけると助かの方法にUnicodeに優しい、どのよう携帯用のもの。

役に立ちましたか?

解決

ブ印刷とデータのアルゴリズムのための本:

#include <boost/algorithm/string.hpp>
// Or, for fewer header dependencies:
//#include <boost/algorithm/string/predicate.hpp>

std::string str1 = "hello, world!";
std::string str2 = "HELLO, WORLD!";

if (boost::iequals(str1, str2))
{
    // Strings are identical
}

他のヒント

の標準 char_traits.いたことは記憶に std::string はtypedefのための std::basic_string<char>, 以上の明示的に std::basic_string<char, std::char_traits<char> >.の char_traits 型が記述する方法文字を比較し、どのようなコピー、どのようにキャストなど。だがtypedefの新しい文字列以上 basic_string, は、提供することおよびユーザーインターフェイス char_traits この比較の場合insensitively.

struct ci_char_traits : public char_traits<char> {
    static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
    static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
    static bool lt(char c1, char c2) { return toupper(c1) <  toupper(c2); }
    static int compare(const char* s1, const char* s2, size_t n) {
        while( n-- != 0 ) {
            if( toupper(*s1) < toupper(*s2) ) return -1;
            if( toupper(*s1) > toupper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a) {
        while( n-- > 0 && toupper(*s) != toupper(a) ) {
            ++s;
        }
        return s;
    }
};

typedef std::basic_string<char, ci_char_traits> ci_string;

詳細は上 グル週の番号29.

トラブルに力をしているリンクにより異なります。容易ではない場合(例えばandroid).

使用char_traits手段 すべての ご比較では大文字と小文字を区別しませんではないが、通常は望ましい.

こべ言わずもがなである。すべき合理的に効率的です。んunicodeなものです。

bool iequals(const string& a, const string& b)
{
    unsigned int sz = a.size();
    if (b.size() != sz)
        return false;
    for (unsigned int i = 0; i < sz; ++i)
        if (tolower(a[i]) != tolower(b[i]))
            return false;
    return true;
}

更新:ボーナスC++14版#include <algorithm>):

bool iequals(const string& a, const string& b)
{
    return std::equal(a.begin(), a.end(),
                      b.begin(), b.end(),
                      [](char a, char b) {
                          return tolower(a) == tolower(b);
                      });
}

の場合には、POSIXシステムを使用でき strcasecmp.この機能は標準Cがも可能でWindows上でしか利用できません。このことを大文字小文字を区別しない比較、8ビットのcharをロケールがPOSIX.の場合はロケールがPOSIXには、結果は未定義です(でいられることもありますが、局所的な比較やかであるとを問いません)広文字相当額はありません。

失敗した数多くの歴史のあるCライブラリの実装には、機能stricmp()およびstrnicmp().Visual C++はWindowsと改称すべてのこれらによりprefixingとしてアンダースコアではありませんが、ANSI準となるシステムのよう呼 _stricmpは_strnicmp.一部の図の場合においてマルチバイト文字または同等の機能(通常は名などwcsicmp,mbcsicmp。

CとC++の両方が大きく無知の国際化の問題なソリューションにこの問題を除き、利用、第三者の図書館があります。チェック IBM ICU(国際部Unicode) が必要な場合は、堅牢な図書館のためのC/C++.ICUは、WindowsとUnixシステム。

それって、ダム大文字と小文字を区別しませんの比較を正規化したUnicodeの比較?

拠を比較しな文字列が同じでもないバイナリー平等なものとする。

例:

U212B (ANGSTROM SIGN)
U0041 (LATIN CAPITAL LETTER A) + U030A (COMBINING RING ABOVE)
U00C5 (LATIN CAPITAL LETTER A WITH RING ABOVE).

すべて相当なもの異なるバイナリ表現に変換するものである。

とはいえ、 Unicode正規化 すべき必須の読み合わせを計画支援ハングル、Thaïその他のアジアの言語である。

また、IBMほとんどの特許最も最適なUnicodeアルゴリズムについて一般の人が入手可能にします。も維持の実装: IBM学

ブ::iequalsはutf-8対応の場合は文字列です。利用できる ブ::ロケール.

comparator<char,collator_base::secondary> cmpr;
cout << (cmpr(str1, str2) ? "str1 < str2" : "str1 >= str2") << endl;
  • 一次無効にするには--アクセントと文字の場合、比較ベース文字です。例えば、"ファサード"と"ファサード"は同じです。
  • 二次無効にするには--文字の場合で考えるアクセントに。"ファサード"と"ファサード"が異なるのが"ファサード"と"ファサード"は同じです。
  • 三次--であると考える場合、アクセント:"ファサード"と"ファサード"が異なります。無視する句読点が含まれます。
  • 第四紀--すべての場合、アクセントには、句読点が含まれます。の言葉で同一でなければならないのUnicode表現。
  • 同一と第四紀は比較的コードポイントです。

私の最初の思いが非unicode版へようこ:


bool caseInsensitiveStringCompare(const string& str1, const string& str2) {
    if (str1.size() != str2.size()) {
        return false;
    }
    for (string::const_iterator c1 = str1.begin(), c2 = str2.begin(); c1 != str1.end(); ++c1, ++c2) {
        if (tolower(*c1) != tolower(*c2)) {
            return false;
        }
    }
    return true;
}

利用できる strcasecmp Unixでは、 stricmp Windows上でしか利用できません。

ものとれていないことをご使用の場合はstl形式の文字列とこれらの方法でに役立つ最初の比較の長さの文字列を、この情報は、既にご利用いた文字列のクラスです。これを防ぐって費用のかかる文字列比較の場合は二つの文字列で比較になっても同じ長さのもの。

Visual C++の文字列関数unicode: http://msdn.microsoft.com/en-us/library/cc194799.aspx

のことがあるでしょう求めているのは、 _wcsnicmp

監督-選手コメンブラと答えたからではなくなったこの編集:

この方法では、ここは変えるには文字列ではないUnicodeでは携帯であるプラス:

bool caseInsensitiveStringCompare( const std::string& str1, const std::string& str2 ) {
    std::string str1Cpy( str1 );
    std::string str2Cpy( str2 );
    std::transform( str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower );
    std::transform( str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower );
    return ( str1Cpy == str2Cpy );
}

からだったのでここでは携帯用よりstricmpでstricmp()は実際の標準図書館が実施する最もコンパイラベンダー

を真にUnicodeに優しい実施されなければなりの外std図書館があります。しているのではなく3サードパーティ製ライブラリは、 IBM ICU(国際部Unicode)

ブ::iequals 提供となることを明らかにし、このような比較です。

が進みました。文字列 図書館のアルゴリズムをやっている場合-insenstiveの比較です。

きの実施、なぜわざわざがで行われている?

ストラヴァ工科大学, strcmp()stricmp() に脆弱なバッファオーバーフローからかなりの工程までの予約なら、世界最大のオンライン、nullでターミネーター.であり、使用 _strncmp()_strnicmp().

私の基本大文字と小文字を区別しませんの文字列比較のニーズを私はあまり好きではないのですがて外部の図書館にない別の文字列クラスの大文字と小文字を区別しません性と相いれないすべての私のその他の文字列です。

うんちはこの:

bool icasecmp(const string& l, const string& r)
{
    return l.size() == r.size()
        && equal(l.cbegin(), l.cend(), r.cbegin(),
            [](string::value_type l1, string::value_type r1)
                { return toupper(l1) == toupper(r1); });
}

bool icasecmp(const wstring& l, const wstring& r)
{
    return l.size() == r.size()
        && equal(l.cbegin(), l.cend(), r.cbegin(),
            [](wstring::value_type l1, wstring::value_type r1)
                { return towupper(l1) == towupper(r1); });
}

単純な機能過負荷のためのcharとwhar_t.使用していないものの非標準的なフランスのプラットフォーム.

の平等と比較しな検討課題のように可変長符号化およびUnicode正規化がbasic_stringしないという意識のもとではない普通の課題。

場合により高度辞書的な操作のテキストが必要で、そのすだけの使用が第三者に図書館のように向上するが予想されます。

std::equal(str1.begin(), str1.end(), str2.begin(), [](auto a, auto b){return std::tolower(a)==std::tolower(b);})

利用できる上記のコードをC++で14の場合は利用が進みました。ただし、使用 std::towlower 広char.

短います。他にはない依存関係のため、より 延長 std C lib.

strcasecmp(str1.c_str(), str2.c_str()) == 0

を返します true の場合 str1str2 等しいことになります。strcasecmp 存在していないかもしれない可能性があ誘導体 stricmp, strcmpi, など。

例コード:

#include <iostream>
#include <string>
#include <string.h> //For strcasecmp(). Also could be found in <mem.h>

using namespace std;

/// Simple wrapper
inline bool str_ignoreCase_cmp(std::string const& s1, std::string const& s2) {
    if(s1.length() != s2.length())
        return false;  // optimization since std::string holds length in variable.
    return strcasecmp(s1.c_str(), s2.c_str()) == 0;
}

/// Function object - comparator
struct StringCaseInsensetiveCompare {
    bool operator()(std::string const& s1, std::string const& s2) {
        if(s1.length() != s2.length())
            return false;  // optimization since std::string holds length in variable.
        return strcasecmp(s1.c_str(), s2.c_str()) == 0;
    }
    bool operator()(const char *s1, const char * s2){ 
        return strcasecmp(s1,s2)==0;
    }
};


/// Convert bool to string
inline char const* bool2str(bool b){ return b?"true":"false"; }

int main()
{
    cout<< bool2str(strcasecmp("asd","AsD")==0) <<endl;
    cout<< bool2str(strcasecmp(string{"aasd"}.c_str(),string{"AasD"}.c_str())==0) <<endl;
    StringCaseInsensetiveCompare cmp;
    cout<< bool2str(cmp("A","a")) <<endl;
    cout<< bool2str(cmp(string{"Aaaa"},string{"aaaA"})) <<endl;
    cout<< bool2str(str_ignoreCase_cmp(string{"Aaaa"},string{"aaaA"})) <<endl;
    return 0;
}

出力:

true
true
true
true
true

std::lexicographical_compare:

// lexicographical_compare example
#include <iostream>  // std::cout, std::boolalpha
#include <algorithm>  // std::lexicographical_compare
#include <cctype>  // std::tolower

// a case-insensitive comparison function:
bool mycomp (char c1, char c2) {
    return std::tolower(c1)<std::tolower(c2);
}

int main () {
    char foo[] = "Apple";
    char bar[] = "apartment";

    std::cout << std::boolalpha;

    std::cout << "Comparing foo and bar lexicographically (foo < bar):\n";

    std::cout << "Using default comparison (operator<): ";
    std::cout << std::lexicographical_compare(foo, foo + 5, bar, bar + 9);
    std::cout << '\n';

    std::cout << "Using mycomp as comparison object: ";
    std::cout << std::lexicographical_compare(foo, foo + 5, bar, bar + 9, mycomp);
    std::cout << '\n';

    return 0;
}

デモ

とをお探しの方法ではなくマジック機能を既存のが正直なります。またすべての書コードスニペットを巧みな技限定文字セットが一日の終わりでsomepointいに変換する文字です。

ための最適なアプローチこの変換は行う前と比較しました。このときの良い取引に対する柔軟性のエンコーディング方式のうち、実際のオペレーターとの比較は無知です。

もちろんの'非表示'この変換の背後に自分の文字列関数やクラスがまだに変換する必要がある文字列の前と比較しました。

書いた大文字小文字を区別しない版char_traits用std::basic_string生成するためstd::文字列は大文字と小文字は区別されませんが比較、検索などの内蔵std::basic_string員ます。

つん。

std::string a = "Hello, World!";
std::string b = "hello, world!";

assert( a == b );

る---std::stringできない。こちらはご利用の新しいchar_traits:

std::istring a = "Hello, World!";
std::istring b = "hello, world!";

assert( a == b );

とは---ここでの実践:

/*  ---

        Case-Insensitive char_traits for std::string's

        Use:

            To declare a std::string which preserves case but ignores case in comparisons & search,
            use the following syntax:

                std::basic_string<char, char_traits_nocase<char> > noCaseString;

            A typedef is declared below which simplifies this use for chars:

                typedef std::basic_string<char, char_traits_nocase<char> > istring;

    --- */

    template<class C>
    struct char_traits_nocase : public std::char_traits<C>
    {
        static bool eq( const C& c1, const C& c2 )
        { 
            return ::toupper(c1) == ::toupper(c2); 
        }

        static bool lt( const C& c1, const C& c2 )
        { 
            return ::toupper(c1) < ::toupper(c2);
        }

        static int compare( const C* s1, const C* s2, size_t N )
        {
            return _strnicmp(s1, s2, N);
        }

        static const char* find( const C* s, size_t N, const C& 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) ; 
        }       
    };

    template<>
    struct char_traits_nocase<wchar_t> : public std::char_traits<wchar_t>
    {
        static bool eq( const wchar_t& c1, const wchar_t& c2 )
        { 
            return ::towupper(c1) == ::towupper(c2); 
        }

        static bool lt( const wchar_t& c1, const wchar_t& c2 )
        { 
            return ::towupper(c1) < ::towupper(c2);
        }

        static int compare( const wchar_t* s1, const wchar_t* s2, size_t N )
        {
            return _wcsnicmp(s1, s2, N);
        }

        static const wchar_t* find( const wchar_t* s, size_t N, const wchar_t& a )
        {
            for( size_t i=0 ; i<N ; ++i )
            {
                if( ::towupper(s[i]) == ::towupper(a) ) 
                    return s+i ;
            }
            return 0 ;
        }

        static bool eq_int_type( const int_type& c1, const int_type& c2 )
        { 
            return ::towupper(c1) == ::towupper(c2) ; 
        }       
    };

    typedef std::basic_string<char, char_traits_nocase<char> > istring;
    typedef std::basic_string<wchar_t, char_traits_nocase<wchar_t> > iwstring;

これを使用せずに向きによっては、C文字列ポインタ c_str() を使用 strcasecmp:

std::string str1 ="aBcD";
std::string str2 = "AbCd";;
if (strcasecmp(str1.c_str(), str2.c_str()) == 0)
{
    //case insensitive equal 
}

私は良い経験を使用 国際部品Unicode図書館 -彼らは非常に強力で、提供方法を変換、ロケールの支援、日付と時間レンダリング、ケースマッピング(きんたい) 照合, を含む場合は、アクセントの大小文字の区別を比較します。自分はまだ使いのC++版の図書館が表示されているJava版しています。

方法を規格化を比較して、引き@Coincoinもできたおかげでインドアロケール-ついては、例えば、この選別の例では、ではなく平等)では、伝統的スペイン語(スペイン)、文字の組み合わせ"ll"などと"l"、"m"、"lz" < "ll" < "ma".

使おう strcmp() のための大文字と小文字が区別および strcmpi() または stricmp() のための大文字と小文字を区別しません。において、ヘッダファイル <string.h>

フォーマット:

int strcmp(const char*,const char*);    //for case sensitive
int strcmpi(const char*,const char*);   //for case insensitive

使用量:

string a="apple",b="ApPlE",c="ball";
if(strcmpi(a.c_str(),b.c_str())==0)      //(if it is a match it will return 0)
    cout<<a<<" and "<<b<<" are the same"<<"\n";
if(strcmpi(a.c_str(),b.c_str()<0)
    cout<<a[0]<<" comes before ball "<<b[0]<<", so "<<a<<" comes before "<<b;

出力

apple、ApPlEの

aがbのでリンゴがボール

ただのおい方法で最後に選ばれる方法その利用 strcmp 一部の回答を提案:

strcmp なUnicodeデータを一般的です。一般のするものではありませんについてバイトに基づくUnicodeエンコーディングなどutf-8からの strcmp 詳細については、更なるバイト当たりのバイトの比較およびUnicodeコードポイントは、utf-8で符号化できる以上の1バイトになります。の特定のUnicodeの場合 strcmp を適正に取り扱う場合は、符号化された文字列とバイトに基づく符号化のみを含むコードポイント以下のU+00FFのバイト当たりのバイト比較は必要なものではありません。

として2013年、本学プロジェクト、IBM、なかなか良い答えです。

http://site.icu-project.org/

ICUは、携帯Unicode図書館に密着したトラック業界基準に" は、特定の問題の文字列比較の照合オブジェクトが何をしています。

のMozillaプロジェクトを採用しICU国際化のためのFirefoxで中旬-2012年すでに工学討論を含め、問題のシステムの構築やデータファイルサイズはこちら

開催時間内に、変異体を使用する std::locale, は、このように正しく取り扱うトルコの:

auto tolower = std::bind1st(
    std::mem_fun(
        &std::ctype<char>::tolower),
    &std::use_facet<std::ctype<char> >(
        std::locale()));

き元の活躍のロケールに変換する文字小文字、を利用できますよ std::transform 発生する場合の文字列:

std::string left = "fOo";
transform(left.begin(), left.end(), left.begin(), tolower);

この仕事も wchar_t に基づく文字列です。

のように見え、上記解な用の比較方法及び実施計ものでは溶液と希望を動作させることができます(このクラスタを管理).

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
string tolow(string a)
{
    for(unsigned int i=0;i<a.length();i++)
    {
        a[i]=tolower(a[i]);
    }
    return a;
}
int main()
{
    string str1,str2;
    cin>>str1>>str2;
    int temp=tolow(str1).compare(tolow(str2));
    if(temp>0)
        cout<<1;
    else if(temp==0)
        cout<<0;
    else
        cout<<-1;
}

ない場合に使いたい Boostライブラリ そしてこの溶液に利用いただけるようになっていけC++の標準ioヘッダを表します。

#include <iostream>

struct iequal
{
    bool operator()(int c1, int c2) const
    {
        // case insensitive comparison of two characters.
        return std::toupper(c1) == std::toupper(c2);
    }
};

bool iequals(const std::string& str1, const std::string& str2)
{
    // use std::equal() to compare range of characters using the functor above.
    return std::equal(str1.begin(), str1.end(), str2.begin(), iequal());
}

int main(void)
{
    std::string str_1 = "HELLO";
    std::string str_2 = "hello";

    if(iequals(str_1,str_2))
    {
        std::cout<<"String are equal"<<std::endl;   
    }

    else
    {
        std::cout<<"String are not equal"<<std::endl;
    }


    return 0;
}

またベクトルの文字列は、例えば:

std::sort(std::begin(myvector), std::end(myvector), [](std::string const &a, std::string const &b)
{
    return std::lexicographical_compare(std::begin(a), std::end(a), std::begin(b), std::end(b), [](std::string::value_type a, std::string::value_type b)
    {
        return std::tolower(a) < std::tolower(b); //case-insensitive
    });
});

http://ideone.com/N6sq6X

の場合を比較し、ソース文字列が他の文字列の一つエレガントな解決方法を用regex.

std::wstring first = L"Test";
std::wstring second = L"TEST";

std::wregex pattern(first, std::wregex::icase);
bool isEqual = std::regex_match(second, pattern);

単純に比較できるよう二つの文字列はc++したwindows用)を使用 _stricmp

// Case insensitive (could use equivalent _stricmp)  
result = _stricmp( string1, string2 );  

ご利用std::string,例:

std::string s1 = string("Hello");
if ( _stricmp(s1.c_str(), "HELLO") == 0)
   std::cout << "The string are equals.";

詳しい情報はこちら https://msdn.microsoft.com/it-it/library/e0z9k731.aspx

bool insensitive_c_compare(char A, char B){
  static char mid_c = ('Z' + 'a') / 2 + 'Z';
  static char up2lo = 'A' - 'a'; /// the offset between upper and lowers

  if ('a' >= A and A >= 'z' or 'A' >= A and 'Z' >= A)
      if ('a' >= B and B >= 'z' or 'A' >= B and 'Z' >= B)
      /// check that the character is infact a letter
      /// (trying to turn a 3 into an E would not be pretty!)
      {
        if (A > mid_c and B > mid_c or A < mid_c and B < mid_c)
        {
          return A == B;
        }
        else
        {
          if (A > mid_c)
            A = A - 'a' + 'A'; 
          if (B > mid_c)/// convert all uppercase letters to a lowercase ones
            B = B - 'a' + 'A';
          /// this could be changed to B = B + up2lo;
          return A == B;
        }
      }
}

このようになってき効率的なものは粗大ごみバージョンそのすべてのビットです。

すべてではないことを携帯でも、何らかの形でコンピュータ(うんの絵は語)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top