String-Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung in C++ [closed]

Lesezeit: 8 Minuten

String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
Adam

Was ist der beste Weg, um einen String-Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung in C++ durchzuführen, ohne einen String in Groß- oder Kleinbuchstaben umzuwandeln?

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

  • @[Adam](#11679): Während diese Variante in Bezug auf die Benutzerfreundlichkeit gut ist, ist sie in Bezug auf die Leistung schlecht, da sie unnötige Kopien erstellt. Ich könnte etwas übersehen, aber ich glaube, der beste (Nicht-Unicode) Weg ist die Verwendung std::stricmp. Ansonsten lies was Herb muss sagen.

    – Konrad Rudolf

    26. August 2008 um 12:17 Uhr

  • In c war man normalerweise gezwungen, die gesamte Zeichenfolge zu überschreiben und dann auf diese Weise zu vergleichen – oder würfeln Sie Ihren eigenen Vergleich: P

    – Michael Dorgan

    22. Mai 2010 um 1:10 Uhr

  • Eine spätere Frage hat eine einfachere Antwort: strcasecmp (zumindest für BSD- und POSIX-Compiler) stackoverflow.com/questions/9182912/…

    – Móż

    5. November 2013 um 21:39 Uhr

  • @Mσᶎ Diese Frage hat auch diese Antwort, mit der wichtigen Einschränkung, dass strcasecmp ist nicht Teil des Standards und fehlt bei mindestens einem gängigen Compiler.

    – Markieren Sie Lösegeld

    1. Dezember 2014 um 19:57 Uhr

String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
rauben

Boost enthält dafür einen praktischen Algorithmus:

#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
}

  • Ist das UTF-8-freundlich? Ich denke nicht.

    – vladr

    30. Oktober 2010 um 0:23 Uhr

  • Nein, da UTF-8 aufgrund von Akzenten, Kombinationen, Bidi-Problemen usw. die Codierung identischer Zeichenfolgen mit unterschiedlichen Binärcodes zulässt.

    – vy32

    18. Juni 2011 um 23:35 Uhr

  • @vy32 Das ist absolut falsch! Die UTF-8-Kombinationen schließen sich gegenseitig aus. Es muss immer die kürzestmögliche Darstellung verwendet werden, wenn dies nicht der Fall ist, handelt es sich um eine fehlerhafte UTF-8-Sequenz oder einen Codepunkt, der mit Vorsicht behandelt werden muss.

    – Wiz

    10. November 2011 um 23:44 Uhr


  • @Wiz, Sie ignorieren das Problem der Normalisierung von Unicode-Strings. ñ kann als Kombination von ˜ gefolgt von einem n oder mit einem ñ-Zeichen dargestellt werden. Sie müssen die Unicode-String-Normalisierung verwenden, bevor Sie den Vergleich durchführen. Bitte lesen Sie den technischen Unicode-Bericht Nr. 15, unicode.org/reports/tr15

    – vy32

    11. November 2011 um 3:21 Uhr

  • @wonkorealtime: weil “ß” in Großbuchstaben umgewandelt “SS” ist: fileformat.info/info/unicode/char/df/index.htm

    – Muhende Ente

    29. Mai 2014 um 23:11 Uhr


1647188410 348 String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
wilhelmell

Profitieren Sie von der Norm char_traits. Denken Sie daran, dass a std::string ist in der Tat ein Typedef für std::basic_string<char>oder genauer gesagt, std::basic_string<char, std::char_traits<char> >. Die char_traits type beschreibt, wie sich Zeichen vergleichen, wie sie kopieren, wie sie gecastet werden usw. Alles, was Sie tun müssen, ist, einen neuen String darüber zu schreiben basic_stringund versehen Sie es mit Ihrem eigenen Benutzernamen char_traits die Groß- und Kleinschreibung unsensibel vergleichen.

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;

Die Details sind auf Guru der Woche Nummer 29.

  • Soweit ich aus eigenen Experimenten weiß, macht dies Ihren neuen Zeichenfolgentyp inkompatibel mit std::string.

    – Zan Luchs

    26. September 2012 um 21:25 Uhr

  • Natürlich tut es das – zu seinem eigenen Besten. Eine Zeichenfolge ohne Berücksichtigung der Groß-/Kleinschreibung ist etwas anderes: typedef std::basic_string<char, ci_char_traits<char> > istringnicht typedef std::basic_string<char, std::char_traits<char> > string.

    – Andreas Spindler

    9. Oktober 2012 um 9:24 Uhr


  • “Alles, was Sie tun müssen …”

    – Tim MB

    19. April 2013 um 10:03 Uhr

  • Jedes Sprachkonstrukt, das in diesem trivialen Fall einen solchen Wahnsinn erzwingt, sollte und kann ohne Reue aufgegeben werden.

    – Erik Aronesty

    14. November 2014 um 14:17 Uhr


  • @DaveKennedy Ich denke, Erik rät dazu, menschliche Sprachen aufzugeben diese sind die Sprachkonstrukte, die diesen Wahnsinn erzwingen. 🙂

    – srm

    21. März 2018 um 16:35 Uhr

1647188411 586 String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
Timmm

Das Problem mit Boost ist, dass Sie sich mit Boost verbinden und sich auf Boost verlassen müssen. In einigen Fällen nicht einfach (z. B. Android).

Und die Verwendung von char_traits bedeutet alle Bei Ihren Vergleichen wird die Groß- und Kleinschreibung nicht beachtet, was normalerweise nicht das ist, was Sie möchten.

Dies sollte genügen. Es sollte einigermaßen effizient sein. Behandelt jedoch kein Unicode oder ähnliches.

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

Update: Bonus C++14-Version (#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);
                      });
}

Update: C++20-Version mit std::ranges:

#include <ranges>
#include <algorithm>
#include <string>

bool iequals(const std::string_view& lhs, const std::string_view& rhs) {
    auto to_lower{ std::ranges::views::transform(std::tolower) };
    return std::ranges::equal(lhs | to_lower, rhs | to_lower);
}

  • Tatsächlich ist die Boost-String-Bibliothek eine reine Header-Bibliothek, sodass keine Verknüpfung zu irgendetwas erforderlich ist. Außerdem können Sie das Dienstprogramm „bcp“ von boost verwenden, um nur die String-Header in Ihren Quellbaum zu kopieren, sodass Sie nicht die vollständige Boost-Bibliothek benötigen.

    – Gretchen

    9. März 2011 um 21:47 Uhr


  • Gut, eine einfache Version ohne Boost-Abhängigkeit zu kennen.

    – Deqing

    17. Mai 2014 um 3:31 Uhr

  • @Anna Textbibliothek von Boost muss erstellt und verlinkt werden. Es verwendet IBM ICU.

    – Behrouz.M

    1. Juni 2015 um 6:46 Uhr


  • std::tolower sollte nicht angerufen werden char direkt, a static_cast zu unsigned char wird gebraucht.

    – Evg

    26. September 2020 um 9:50 Uhr


  • @Timmmm Ich habe mir erlaubt, dieser Antwort eine C ++ 20-Version hinzuzufügen, da ich glaube, dass hier die beste Lösung ist, und im Vergleich zu anderen Antworten in diesem Thread glaube ich, dass sie Ihren anderen Lösungen am ähnlichsten ist.

    – Ben Cottrell

    2. Januar um 11:39 Uhr


1647188411 942 String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
Derek Park

Wenn Sie sich auf einem POSIX-System befinden, können Sie verwenden strcasecmp. Diese Funktion ist jedoch nicht Teil von Standard-C und steht auch nicht unter Windows zur Verfügung. Dies führt einen Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung für 8-Bit-Zeichen durch, solange das Gebietsschema POSIX ist. Wenn das Gebietsschema nicht POSIX ist, sind die Ergebnisse undefiniert (es kann also ein lokalisierter Vergleich durchgeführt werden oder nicht). Ein Breitzeichen-Äquivalent ist nicht verfügbar.

Andernfalls verfügen viele historische Implementierungen von C-Bibliotheken über die Funktionen stricmp() und strnicmp(). Visual C++ unter Windows hat all diese umbenannt, indem ihnen ein Unterstrich vorangestellt wurde, weil sie nicht Teil des ANSI-Standards sind, also heißen sie auf diesem System _stricmp oder _strnicmp. Einige Bibliotheken können auch Wide-Character- oder Multibyte-äquivalente Funktionen haben (normalerweise zB wcsicmp, mbcsicmp und so weiter genannt).

C und C++ sind beide weitgehend unwissend in Bezug auf Internationalisierungsprobleme, daher gibt es keine gute Lösung für dieses Problem, außer die Verwendung einer Bibliothek eines Drittanbieters. Kasse IBM ICU (Internationale Komponenten für Unicode) wenn Sie eine robuste Bibliothek für C/C++ benötigen. ICU ist sowohl für Windows- als auch für Unix-Systeme.

1647188411 908 String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
Münze

Sprechen Sie von einem dummen Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung oder einem vollständig normalisierten Unicode-Vergleich?

Ein dummer Vergleich findet keine Zeichenfolgen, die möglicherweise gleich sind, aber nicht binär gleich sind.

Beispiel:

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

Sind alle gleichwertig, haben aber auch unterschiedliche binäre Darstellungen.

Das gesagt, Unicode-Normalisierung sollte eine Pflichtlektüre sein, besonders wenn Sie vorhaben, Hangul, Thaï und andere asiatische Sprachen zu unterstützen.

Außerdem hat IBM die meisten optimierten Unicode-Algorithmen so ziemlich patentiert und öffentlich zugänglich gemacht. Sie pflegen auch eine Implementierung: IBM Intensivstation

1647188412 232 String Vergleich ohne Berucksichtigung der Gros Kleinschreibung in C closed
Igor Miljakow

boost::iequals ist im Fall 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 — Akzente und Groß-/Kleinschreibung ignorieren, nur Grundbuchstaben vergleichen. Beispielsweise sind „Fassade“ und „Fassade“ gleich.
  • Sekundär – Groß-/Kleinschreibung ignorieren, aber Akzente berücksichtigen. “Fassade” und “Fassade” sind unterschiedlich, aber “Fassade” und “Fassade” sind dasselbe.
  • Tertiär – Groß- und Kleinschreibung beachten: „Fassade“ und „Fassade“ sind unterschiedlich. Satzzeichen ignorieren.
  • Quartär – berücksichtigen Sie Groß- und Kleinschreibung, Akzente und Interpunktion. Die Wörter müssen hinsichtlich der Unicode-Darstellung identisch sein.
  • Identisch – wie quaternär, aber auch Codepunkte vergleichen.

Mein erster Gedanke für eine Nicht-Unicode-Version war, so etwas zu tun:

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

  • std::tolower sollte nicht angerufen werden char direkt, a static_cast zu unsigned char wird gebraucht.

    – Evg

    26. September 2020 um 9:50 Uhr


  • @Evg, also if (tolower(static_cast<unsigned char>(*c1)) != tolower(static_cast<unsigned char>(*c2)) Wird besorgt?

    – Shadow2531

    27. September 2020 um 10:51 Uhr

  • Ja, das sollte der richtige Weg sein.

    – Evg

    27. September 2020 um 11:54 Uhr

998370cookie-checkString-Vergleich ohne Berücksichtigung der Groß-/Kleinschreibung in C++ [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy