Câu trả lời:
Chỉ cần so sánh n ký tự cuối cùng bằng cách sử dụng 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;
}
Sử dụng chức năng này:
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()
Trong chế độ gỡ lỗi, nó sẽ ném:_DEBUG_ERROR("string iterator not decrementable");
Sử dụng boost::algorithm::ends_with
(xem ví dụ: http://www.boost.org/doc/libs/1_34_0/doc/html/boost/alerskym/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));
Lưu ý, bắt đầu từ c ++ 20 std :: string cuối cùng sẽ cung cấp started_with và end_with . Có vẻ như có khả năng bởi c ++ 30 chuỗi trong c ++ cuối cùng có thể trở nên có thể sử dụng được, nếu bạn không đọc được điều này từ tương lai xa, bạn có thể sử dụng các startWith / endWith:
#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);
}
và một số quá tải trợ giúp thêm:
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));
}
Các chuỗi IMO, c ++ rõ ràng là không hoạt động và không được sử dụng trong mã thế giới thực. Nhưng có một hy vọng rằng điều này sẽ trở nên tốt hơn ít nhất.
Tôi biết câu hỏi dành cho C ++, nhưng nếu có ai cần chức năng C thời trang tốt để làm điều này:
/* 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 );
}
Các std::mismatch
phương pháp có thể phục vụ mục đích này khi được sử dụng để ngược lặp từ ngày kết thúc cả chuỗi:
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
: bạn cần kiểm tra trước rằng hậu tố được cho là không dài hơn chuỗi bạn đang tìm kiếm. Bỏ qua để kiểm tra dẫn đến hành vi không xác định.
Theo tôi đơn giản nhất, giải pháp C ++ là:
bool endsWith(const string& s, const string& suffix)
{
return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}
s
thay vì chỉ kiểm tra kết thúc của chuỗi!
std::string::size()
là một hoạt động liên tục; nó không cần strlen
.
Hãy a
là một chuỗi và b
chuỗi bạn tìm kiếm. Sử dụng a.substr
để lấy n ký tự cuối cùng a
và so sánh chúng với b (trong đó n là độ dài của b
)
Hoặc sử dụng std::equal
(bao gồm <algorithm>
)
Ví dụ:
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());
}
Hãy để tôi mở rộng giải pháp của Joseph với phiên bản không nhạy cảm trường hợp ( bản demo trực tuyến )
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);
}
);
}
giống như trên, đây là giải pháp của tôi
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
sử dụng 'chuỗi :: so sánh'? Tại sao không std::equal(start.begin(), start.end(), str.begin())
?
tùy chọn khác là sử dụng regex. Đoạn mã sau làm cho tìm kiếm không nhạy cảm với chữ hoa / thường:
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
return std::regex_search(str,
std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}
có lẽ không hiệu quả, nhưng dễ thực hiện.
bạn có thể sử dụng chuỗi :: rfind
Ví dụ đầy đủ dựa trên ý kiến:
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;
}
Kiểm tra xem str có hậu tố không , sử dụng bên dưới:
/*
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;
}
Sử dụng thuật toán std :: bằng <algorithms>
với lặp lại:
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
Về phản ứng của Grzegorz Bazior. Tôi đã sử dụng triển khai này, nhưng bản gốc có lỗi (trả về true nếu tôi so sánh ".." với ".so"). Tôi đề xuất chức năng sửa đổi:
bool endsWith(const string& s, const string& suffix)
{
return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
Tôi nghĩ thật hợp lý khi đăng một giải pháp thô không sử dụng bất kỳ chức năng thư viện nào ...
// 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;
}
Thêm một đơn giản std::tolower
chúng ta có thể làm cho trường hợp này không nhạy cảm
// 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;
}
Tìm thấy câu trả lời hay này cho chương trình "startWith" tương tự:
Bạn có thể áp dụng giải pháp để chỉ tìm kiếm ở vị trí cuối cùng trong chuỗi:
bool endsWith(const std::string& stack, const std::string& needle) {
return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}
Bằng cách này bạn có thể làm cho nó ngắn, nhanh, sử dụng c ++ tiêu chuẩn và làm cho nó dễ đọc.
Nếu bạn giống tôi và không thích chủ nghĩa thuần túy C ++, thì đây là một bản lai tạo cũ. Có một số lợi thế khi các chuỗi nhiều hơn một số ký tự, vì hầu hết các memcmp
triển khai đều so sánh các từ máy khi có thể.
Bạn cần kiểm soát bộ ký tự. Ví dụ: nếu cách tiếp cận này được sử dụng với loại utf-8 hoặc wchar, sẽ có một số bất lợi vì nó không hỗ trợ ánh xạ ký tự - ví dụ: khi hai hoặc nhiều ký tự giống nhau về mặt logic .
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;
}