372 Stimmen

Groß-/Kleinschreibung unempfindlicher String-Vergleich in C++

Was ist der beste Weg, um case-insensitive String-Vergleich in C++ ohne Umwandlung einer Zeichenfolge in alle Groß- oder Kleinschreibung zu tun?

Bitte geben Sie an, ob die Methoden Unicode-freundlich sind und wie portabel sie sind.

35voto

Shadow2531 Punkte 11620

Mein erster Gedanke für eine Nicht-Unicode-Version war, etwas in dieser Art zu machen:

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(static_cast<unsigned char>(*c1)) != tolower(static_cast<unsigned char>(*c2))) {
            return false;
        }
    }
    return true;
}

35voto

Igor Milyakov Punkte 582

Boost::iequals ist im Falle von string nicht utf-8 kompatibel. Sie können verwenden boost::locale .

comparator<char,collator_base::secondary> cmpr;
cout << (cmpr(str1, str2) ? "str1 < str2" : "str1 >= str2") << endl;
  • Primär - ignoriert Akzente und Groß- und Kleinschreibung und vergleicht nur Grundbuchstaben. Zum Beispiel sind "Fassade" und "Fassade" dasselbe.
  • Sekundär - Groß- und Kleinschreibung ignorieren, aber Akzente berücksichtigen. "Fassade" und "Fassade" sind unterschiedlich, aber "Fassade" und "Fassade" sind dasselbe.
  • Tertiär - Groß- und Kleinschreibung sowie Akzente beachten: "Fassade" und "Fassade" sind unterschiedlich. Interpunktion ignorieren.
  • Quartär - alle Groß- und Kleinschreibung, Akzente und Interpunktion beachten. Die Wörter müssen in Bezug auf die Unicode-Darstellung identisch sein.
  • Identisch - wie quaternär, aber auch Vergleich der Codepunkte.

29voto

bradtgmurray Punkte 12945

Sie können verwenden strcasecmp unter Unix, oder stricmp unter Windows.

Eine Sache, die bisher noch nicht erwähnt wurde, ist, dass es bei der Verwendung von stl-Strings mit diesen Methoden sinnvoll ist, zunächst die Länge der beiden Strings zu vergleichen, da diese Information bereits in der String-Klasse zur Verfügung steht. Dadurch kann der kostspielige String-Vergleich vermieden werden, wenn die beiden Strings, die Sie vergleichen, gar nicht erst gleich lang sind.

17voto

vine'th Punkte 4708
str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](auto a, auto b){return std::tolower(a)==std::tolower(b);})

Sie können den obigen Code in C++14 verwenden, wenn Sie nicht in der Lage sind, boost zu verwenden. Sie müssen verwenden std::towlower für breite Zeichen.

17voto

Adam Punkte 25228

Ich versuche, aus all den Beiträgen eine gute Antwort zusammenzuschustern, also helfen Sie mir, das hier zu bearbeiten:

Hier ist eine Methode, die zwar die Zeichenketten umwandelt und nicht Unicode-freundlich ist, aber portabel sein sollte, was ein Plus ist:

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 );
}

Nach dem, was ich gelesen habe, ist dies portabler als stricmp(), da stricmp() in der Tat nicht Teil der Standardbibliothek ist, sondern nur von den meisten Compilerherstellern implementiert wird.

Um eine wirklich Unicode-freundliche Implementierung zu erhalten, müssen Sie offenbar die Standardbibliothek verlassen. Eine gute Bibliothek eines Drittanbieters ist die IBM ICU (Internationale Komponenten für Unicode)

También boost::iequals bietet ein recht gutes Hilfsmittel für diese Art von Vergleich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X