Yanıtlar:
Son n karakteri aşağıdakileri kullanarak karşılaştırmanız yeterlidir 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;
}
Bu işlevi kullanın:
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());
}
std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()
Hata ayıklama modunda atar:_DEBUG_ERROR("string iterator not decrementable");
Kullanın boost::algorithm::ends_with
(bkz. Örneğin 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));
Not başlayarak o c ++ 20 std :: string nihayet sağlayacaktır starts_with ve ends_with . Görünüşe göre c ++ 'daki c ++ 30 dizeleri nihayet kullanılabilir hale gelebilir, eğer bunu uzak bir gelecekten okumuyorsanız, bu start'ları kullanabilirsiniz.
#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);
}
ve bazı ekstra yardımcı aşırı yüklemeler:
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 ++ dizeleri açıkça işlevsizdir ve gerçek dünya kodunda kullanılmamıştır. Ancak bunun en azından daha iyi olacağına dair bir umut var.
Sorunun C ++ için olduğunu biliyorum, ama herkes bunu yapmak için iyi ol 'moda C işlevine ihtiyacınız varsa:
/* 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 );
}
std::mismatch
Geriye doğru kullanılan bu amaca hizmet edebilir yöntemi, her iki şeritlerinin ucundan yineleme:
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() );
std::equal
olduğuna dikkat edin: sözde son ekin aradığınız dizeden daha uzun olmadığını önceden kontrol etmeniz gerekir. Tanımlanmamış davranışa neden olup olmadığını kontrol etmeyi ihmal etmek.
Bence en basit, C ++ çözümü:
bool endsWith(const string& s, const string& suffix)
{
return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}
s
sonunu test etmek yerine tüm dizeyi arayacağınız için oldukça yavaştır !
std::string::size()
sabit zamanlı bir işlemdir; gerek yok strlen
.
Izin a
vermek bir dize ve b
aradığınız dize. Tuşunun a.substr
son n karakterini almak a
ve bunları b ile karşılaştırmak için kullanın (burada n, uzunluğudur b
)
Veya kullanın std::equal
(dahil <algorithm>
)
Ör:
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());
}
Durum duyarsız versiyonu ile Joseph'in çözümünü genişletmeme izin verin ( çevrimiçi 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);
}
);
}
yukarıdakiyle aynı, işte benim çözümüm
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());
}
starts_with
'string :: compar' kullanılıyor? Neden olmasın std::equal(start.begin(), start.end(), str.begin())
?
başka bir seçenek regex kullanmaktır. Aşağıdaki kod, aramayı büyük / küçük harfe duyarsız hale getirir:
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
return std::regex_search(str,
std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}
muhtemelen çok verimli değil, ama uygulaması kolaydır.
string :: rfind kullanabilirsiniz
Yorumlara dayalı tam örnek:
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;
}
Str'nin son eki olup olmadığını kontrol edin :
/*
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;
}
<algorithms>
Ters yinelemeli std :: equal algoritması kullanın :
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
Grzegorz Bazior yanıtı ile ilgili. Bu uygulamayı kullandım, ancak orijinal bir hata var (".." ile ".so" karşılaştırırsanız doğru döner). Değiştirilmiş işlev öneriyorum:
bool endsWith(const string& s, const string& suffix)
{
return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
Kütüphane işlevlerini kullanmayan ham bir çözüm yayınlamanın mantıklı olduğunu düşündüm ...
// 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;
}
Basit bir ekleyerek std::tolower
, bu vakayı duyarsız yapabiliriz
// 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;
}
Benzer "startWith" sorusuna bu güzel cevabı buldum:
Yalnızca dizenin son yerinde arama yapmak için çözümü kullanabilirsiniz:
bool endsWith(const std::string& stack, const std::string& needle) {
return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}
Bu şekilde kısa, hızlı, standart c ++ kullanabilirsiniz ve okunabilir yapabilirsiniz.
Eğer benden hoşlanıyorsanız ve C ++ saflığına girmiyorsanız, işte eski bir skool melezi. Dizelerin bir avuç karakterden fazlası olmasının avantajı vardır, çünkü çoğu memcmp
uygulama mümkün olduğunda makine sözcüklerini karşılaştırır.
Karakter setinin kontrolünde olmalısınız. Örneğin, bu yaklaşım utf-8 veya wchar türüyle kullanılırsa, karakter eşlemeyi desteklemeyeceği için bazı dezavantajlar vardır - örneğin, iki veya daha fazla karakter mantıksal olarak aynı olduğunda .
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;
}
Benim görüşüm:
bool endsWith(std::string str, std::string suffix)
{
return str.find(suffix, str.size() - suffix.size()) != string::npos;
}