Jawaban:
Cukup bandingkan n karakter terakhir menggunakan 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;
}
Gunakan fungsi ini:
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()
Dalam mode debug, ia melempar:_DEBUG_ERROR("string iterator not decrementable");
Gunakan boost::algorithm::ends_with
(lihat misalnya 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));
Catatan, bahwa mulai dari c ++ 20 std :: string akhirnya akan menyediakan begin_with dan ends_with . Sepertinya ada kemungkinan bahwa dengan c ++ 30 string dalam c ++ akhirnya bisa digunakan, jika Anda tidak membaca ini dari masa depan yang jauh, Anda dapat menggunakan ini dimulai Dengan / berakhir Dengan:
#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);
}
dan beberapa kelebihan pembantu ekstra:
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 ++ string jelas tidak berfungsi, dan tidak dibuat untuk digunakan dalam kode dunia nyata. Tetapi ada harapan bahwa ini akan menjadi lebih baik setidaknya.
Saya tahu pertanyaannya untuk C ++, tetapi jika ada yang membutuhkan fungsi C yang bagus untuk melakukan ini:
/* 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 );
}
The std::mismatch
Metode dapat melayani tujuan ini bila digunakan untuk mundur iterate dari akhir kedua string:
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
: Anda harus memeriksa terlebih dahulu bahwa sufiks yang seharusnya tidak lebih panjang dari string yang Anda cari. Tidak mengikutinya yang mengarah ke perilaku yang tidak terdefinisi.
Menurut pendapat saya paling sederhana, solusi C ++ adalah:
bool endsWith(const string& s, const string& suffix)
{
return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}
s
alih-alih hanya menguji ujungnya!
std::string::size()
adalah operasi waktu-konstan; tidak perlu strlen
.
Biarkan a
menjadi string dan b
string yang Anda cari. Gunakan a.substr
untuk mendapatkan n karakter terakhir a
dan bandingkan dengan b (di mana n adalah panjang b
)
Atau gunakan std::equal
(termasuk <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());
}
Biarkan saya memperluas solusi Joseph dengan versi case case ( demo online )
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);
}
);
}
sama seperti di atas, di sini adalah solusi saya
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
menggunakan 'string :: compare'? Mengapa tidak std::equal(start.begin(), start.end(), str.begin())
?
Pilihan lain adalah menggunakan regex. Kode berikut membuat pencarian tidak sensitif terhadap huruf besar / kecil:
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
return std::regex_search(str,
std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}
mungkin tidak begitu efisien, tetapi mudah diimplementasikan.
Anda dapat menggunakan string :: rfind
Contoh lengkap berdasarkan komentar:
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;
}
Periksa apakah str memiliki akhiran , menggunakan di bawah ini:
/*
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;
}
Gunakan std :: equal algoritma from <algorithms>
dengan iterasi terbalik:
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
Mengenai tanggapan Grzegorz Bazior. Saya menggunakan implementasi ini, tetapi yang asli memiliki bug (mengembalikan true jika saya membandingkan ".." dengan ".so"). Saya mengusulkan fungsi yang dimodifikasi:
bool endsWith(const string& s, const string& suffix)
{
return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
Saya pikir masuk akal untuk mengirim solusi mentah yang tidak menggunakan fungsi pustaka ...
// 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;
}
Menambahkan sederhana, std::tolower
kita bisa membuat case ini tidak sensitif
// 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;
}
Menemukan jawaban yang bagus untuk masalah "startWith" yang serupa:
Anda dapat mengadopsi solusi hanya mencari di tempat terakhir di string:
bool endsWith(const std::string& stack, const std::string& needle) {
return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}
Dengan cara ini Anda dapat membuatnya pendek, cepat, menggunakan standar c ++ dan membuatnya mudah dibaca.
Jika Anda seperti saya dan tidak begitu menyukai C ++ purism, inilah skool hybrid lama. Ada beberapa keuntungan ketika string lebih dari beberapa karakter, karena sebagian besar memcmp
implementasi membandingkan kata-kata mesin bila memungkinkan.
Anda harus mengendalikan set karakter. Misalnya, jika pendekatan ini digunakan dengan utf-8 atau tipe wchar, ada beberapa kelemahan karena tidak akan mendukung pemetaan karakter - misalnya, ketika dua atau lebih karakter identik secara logis .
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;
}
Dua sen saya:
bool endsWith(std::string str, std::string suffix)
{
return str.find(suffix, str.size() - suffix.size()) != string::npos;
}