답변:
다음을 사용하여 마지막 n 문자를 간단히 비교하십시오 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;
}
이 기능을 사용하십시오 :
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()
. 디버그 모드에서는 다음이 발생합니다._DEBUG_ERROR("string iterator not decrementable");
사용하십시오 boost::algorithm::ends_with
(예 : 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));
c ++ 20 std :: string 부터 시작 하면 결국 starts_with 및 ends_with를 제공합니다 . 먼 미래에서 이것을 읽지 않으면 c ++의 c ++ 30 문자열이 마침내 사용 가능해질 가능성이있는 것처럼 보입니다. 먼저 다음과 같이 startsWith / endsWith를 사용할 수 있습니다.
#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);
}
추가 도우미 오버로드 :
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 ++ 문자열은 분명히 기능 장애이며 실제 코드에서 사용되도록 만들어지지 않았습니다. 그러나 이것이 더 좋아질 것이라는 희망이 있습니다.
나는 C ++에 대한 질문을 알고 있지만 누군가가 이것을하기 위해 좋은 ol'C 형 C 함수가 필요하다면 :
/* 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
방법은 두 문자열의 끝에서 거꾸로 반복 할 때이 목적을 달성 할 수 있습니다.
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
다음 과 같습니다. 접미사가 예상 문자열보다 길지 않은지 미리 확인해야합니다. 확인을 무시하면 정의되지 않은 동작이 발생합니다.
내 의견으로는 C ++ 솔루션은 다음과 같습니다.
bool endsWith(const string& s, const string& suffix)
{
return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}
s
의 끝을 테스트하는 대신 전체 문자열을 검색하기 때문에 속도가 느립니다 !
std::string::size()
는 상수 시간 작업입니다. 필요하지 않습니다 strlen
.
하자 a
문자열과 수 b
당신이 보는 문자열입니다. 사용 a.substr
의 마지막 n 문자를 얻을 수 a
와 b에 비교는 (여기서 n의 길이 b
)
또는 사용 std::equal
(포함 <algorithm>
)
전의:
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());
}
대소 문자를 구분하지 않는 버전으로 Joseph의 솔루션 을 확장하겠습니다 ( 온라인 데모 )
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);
}
);
}
위와 동일하게 여기 내 해결책이 있습니다.
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 :: compare'를 사용합니까? 왜 안돼 std::equal(start.begin(), start.end(), str.begin())
?
또 다른 옵션은 정규식을 사용하는 것입니다. 다음 코드는 대소 문자를 구분하지 않고 검색을 수행합니다.
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
return std::regex_search(str,
std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}
아마도 그렇게 효율적이지 않지만 구현하기 쉽습니다.
string :: rfind를 사용할 수 있습니다
주석을 기반으로 한 전체 예 :
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 에 접미사 가 있는지 확인하십시오 .
/*
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>
역 반복 에서 std :: equal 알고리즘을 사용하십시오 .
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
라이브러리 함수를 사용하지 않는 원시 솔루션을 게시하는 것이 합리적이라고 생각했습니다 ...
// 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;
}
간단하게 추가하면 std::tolower
이 대소 문자를 구분하지 않아도됩니다
// 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;
}
비슷한 "startWith"문제에 대한이 훌륭한 답변을 찾았습니다.
C ++ std :: string이 특정 문자열로 시작하고 하위 문자열을 int로 변환하는지 어떻게 확인합니까?
문자열의 마지막 위치에서만 검색하도록 솔루션을 채택 할 수 있습니다.
bool endsWith(const std::string& stack, const std::string& needle) {
return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}
이렇게하면 짧고 빠르며 표준 c ++을 사용하고 읽을 수 있습니다.
당신이 나와 같고 C ++ 순수주의에 빠져 있지 않다면 여기 오래된 스쿨 하이브리드가 있습니다. 대부분의 memcmp
구현은 가능한 경우 기계어를 비교 하기 때문에 문자열이 소수 이상의 문자 인 경우 이점이 있습니다.
문자 세트를 제어해야합니다. 예를 들어,이 접근 방식이 utf-8 또는 wchar 유형과 함께 사용되는 경우 문자 매핑을 지원하지 않기 때문에 (예 : 둘 이상의 문자가 논리적으로 동일한 경우) 몇 가지 단점이 있습니다 .
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;
}