it-swarm.com.de

Finden Sie, ob die Zeichenfolge mit einer anderen Zeichenfolge in C++ endet

Wie kann ich feststellen, ob eine Zeichenfolge in C++ mit einer anderen Zeichenfolge endet?

229
sofr

Vergleichen Sie einfach die letzten n Zeichen mit std::string::compare :

#include <iostream>

bool hasEnding (std::string const &fullString, std::string const &ending) {
    if (fullString.length() >= ending.length()) {
        return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
    } else {
        return false;
    }
}

int main () {
    std::string test1 = "binary";
    std::string test2 = "unary";
    std::string test3 = "tertiary";
    std::string test4 = "ry";
    std::string ending = "nary";

    std::cout << hasEnding (test1, ending) << std::endl;
    std::cout << hasEnding (test2, ending) << std::endl;
    std::cout << hasEnding (test3, ending) << std::endl;
    std::cout << hasEnding (test4, ending) << std::endl;

    return 0;
}
185
kdt

Verwenden Sie diese Funktion:

inline bool ends_with(std::string const & value, std::string const & ending)
{
    if (ending.size() > value.size()) return false;
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
154
Joseph

Verwenden Sie boost::algorithm::ends_with (siehe beispielsweise http://www.boost.org/doc/libs/1_34_0/doc/html/boost/algorithm/ends_with.html ):

#include <boost/algorithm/string/predicate.hpp>

// works with const char* 
assert(boost::algorithm::ends_with("mystring", "ing"));

// also works with std::string
std::string haystack("mystring");
std::string needle("ing");
assert(boost::algorithm::ends_with(haystack, needle));

std::string haystack2("ng");
assert(! boost::algorithm::ends_with(haystack2, needle));
143
Andre Holzner

Ich kenne die Frage für C++, aber wenn jemand eine gute, altmodische C-Funktion benötigt, um dies auszuführen:


/*  returns 1 iff str ends with suffix  */
int str_ends_with(const char * str, const char * suffix) {

  if( str == NULL || suffix == NULL )
    return 0;

  size_t str_len = strlen(str);
  size_t suffix_len = strlen(suffix);

  if(suffix_len > str_len)
    return 0;

  return 0 == strncmp( str + str_len - suffix_len, suffix, suffix_len );
}
38
Tom

Beachten Sie, dass ab c ++ 20 std :: string schließlich starts_with und ends_with bereitgestellt wird. Es scheint, als gäbe es eine Chance, dass durch C++ 30 Strings in C++ endlich nutzbar werden könnten. Wenn Sie dies nicht aus ferner Zukunft lesen, können Sie diese startsWith/endsWith verwenden:

#include <string>

static bool endsWith(const std::string& str, const std::string& suffix)
{
    return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}

static bool startsWith(const std::string& str, const std::string& prefix)
{
    return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
}

und einige zusätzliche Helferüberladungen:

static bool endsWith(const std::string& str, const char* suffix, unsigned suffixLen)
{
    return str.size() >= suffixLen && 0 == str.compare(str.size()-suffixLen, suffixLen, suffix, suffixLen);
}

static bool endsWith(const std::string& str, const char* suffix)
{
    return endsWith(str, suffix, std::string::traits_type::length(suffix));
}

static bool startsWith(const std::string& str, const char* prefix, unsigned prefixLen)
{
    return str.size() >= prefixLen && 0 == str.compare(0, prefixLen, prefix, prefixLen);
}

static bool startsWith(const std::string& str, const char* prefix)
{
    return startsWith(str, prefix, std::string::traits_type::length(prefix));
}

IMO-, C++ - Zeichenfolgen sind eindeutig dysfunktionell und wurden nicht für die Verwendung in Code der realen Welt entwickelt. Es besteht jedoch die Hoffnung, dass dies zumindest besser wird.

26
Pavel

Die std::mismatch-Methode kann diesem Zweck dienen, wenn sie vom Ende beider Strings rückwärts iteriert wird:

const string sNoFruit = "ThisOneEndsOnNothingMuchFruitLike";
const string sOrange = "ThisOneEndsOnOrange";

const string sPattern = "Orange";

assert( mismatch( sPattern.rbegin(), sPattern.rend(), sNoFruit.rbegin() )
          .first != sPattern.rend() );

assert( mismatch( sPattern.rbegin(), sPattern.rend(), sOrange.rbegin() )
          .first == sPattern.rend() );
25
xtofl

Die einfachste C++ - Lösung ist meiner Meinung nach

bool endsWith(const string& s, const string& suffix)
{
    return s.rfind(suffix) == (s.size()-suffix.size());
}
10
Grzegorz Bazior

Sei a eine Zeichenkette und b die Zeichenkette, nach der du suchst. Benutze a.substr, um die letzten n Zeichen von a abzurufen und sie mit b zu vergleichen (wobei n die Länge von b ist)

Oder benutze std::equal (Include <algorithm>)

Ex:

bool EndsWith(const string& a, const string& b) {
    if (b.size() > a.size()) return false;
    return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
}
9
Dario

Lassen Sie mich Josephs Lösung mit der Groß-/Kleinschreibung ( Online Demo )

static bool EndsWithCaseInsensitive(const std::string& value, const std::string& ending) {
    if (ending.size() > value.size()) {
        return false;
    }
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin(),
        [](const char a, const char b) {
            return tolower(a) == tolower(b);
        }
    );
}
3
PolarBear

sie können string :: rfind verwenden.

Das vollständige Beispiel basiert auf Kommentaren:

bool EndsWith(string &str, string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();

if(keylen =< strlen)
    return string::npos != str.rfind(key,strlen - keylen, keylen);
else return false;
}
3
Ahmed Said

genau wie oben, hier ist meine Lösung

 template<typename TString>
  inline bool starts_with(const TString& str, const TString& start) {
    if (start.size() > str.size()) return false;
    return str.compare(0, start.size(), start) == 0;
  }
  template<typename TString>
  inline bool ends_with(const TString& str, const TString& end) {
    if (end.size() > str.size()) return false;
    return std::equal(end.rbegin(), end.rend(), str.rbegin());
  }
2
dodjango

Zur Antwort von Grzegorz Bazior. Ich habe diese Implementierung verwendet, aber der ursprüngliche Fehler hat einen Fehler (gibt "true" zurück, wenn ich ".." mit ".so" vergleiche).

bool endsWith(const string& s, const string& suffix)
{
    return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
1
Andrew123

Wenn Sie wie ich sind und keinen C++ - Purismus haben, ist hier ein alter Skool-Hybrid. Es gibt einige Vorteile, wenn Strings mehr als eine Handvoll Zeichen sind, da die meisten memcmp-Implementierungen, wenn möglich, Maschinenwörter vergleichen.

Sie müssen die Kontrolle über den Zeichensatz haben. Wenn dieser Ansatz beispielsweise mit dem Typ utf-8 oder wchar verwendet wird, gibt es einige Nachteile, da er die Zeichenzuordnung nicht unterstützt - z. B. wenn zwei oder mehr Zeichen logisch identisch sind .

bool starts_with(std::string const & value, std::string const & prefix)
{
    size_t valueSize = value.size();
    size_t prefixSize = prefix.size();

    if (prefixSize > valueSize)
    {
        return false;
    }

    return memcmp(value.data(), prefix.data(), prefixSize) == 0;
}


bool ends_with(std::string const & value, std::string const & suffix)
{
    size_t valueSize = value.size();
    size_t suffixSize = suffix.size();

    if (suffixSize > valueSize)
    {
        return false;
    }

    const char * valuePtr = value.data() + valueSize - suffixSize;

    return memcmp(valuePtr, suffix.data(), suffixSize) == 0;
}
0
jws

Ich dachte, es wäre sinnvoll, eine unbearbeitete Lösung zu posten, die keine Bibliotheksfunktionen verwendet ...

// Checks whether `str' ends with `suffix'
bool endsWith(const std::string& str, const std::string& suffix) {
    if (&suffix == &str) return true; // str and suffix are the same string
    if (suffix.length() > str.length()) return false;
    size_t delta = str.length() - suffix.length();
    for (size_t i = 0; i < suffix.length(); ++i) {
        if (suffix[i] != str[delta + i]) return false;
    }
    return true;
}

Durch Hinzufügen eines einfachen std::tolower können wir diesen Fall unempfindlich machen

// Checks whether `str' ends with `suffix' ignoring case
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
    if (&suffix == &str) return true; // str and suffix are the same string
    if (suffix.length() > str.length()) return false;
    size_t delta = str.length() - suffix.length();
    for (size_t i = 0; i < suffix.length(); ++i) {
        if (std::tolower(suffix[i]) != std::tolower(str[delta + i])) return false;
    }
    return true;
}
0
cute_ptr

eine weitere Option ist die Verwendung von Regex. Der folgende Code macht die Suche unempfindlich gegenüber Groß-/Kleinschreibung:

bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
  return std::regex_search(str,
     std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}

wahrscheinlich nicht so effizient, aber leicht umzusetzen.

0
Julien Pilet

Prüfen Sie, ob str über Suffix verfügt.

/*
Check string is end with extension/suffix
*/
int strEndWith(char* str, const char* suffix)
{
  size_t strLen = strlen(str);
  size_t suffixLen = strlen(suffix);
  if (suffixLen <= strLen) {
    return strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
  }
  return 0;
}
0
James Yang