ฉันจะทราบได้อย่างไรว่าสตริงลงท้ายด้วยสตริงอื่นใน C ++?
ฉันจะทราบได้อย่างไรว่าสตริงลงท้ายด้วยสตริงอื่นใน C ++?
คำตอบ:
เพียงเปรียบเทียบอักขระสุดท้าย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มาตรฐาน :: สตริงในที่สุดก็จะให้starts_withและends_with ดูเหมือนว่ามีโอกาสที่ c ++ 30 สายใน c ++ อาจใช้งานได้ในที่สุดหากคุณไม่ได้อ่านสิ่งนี้จากอนาคตอันไกลคุณสามารถใช้การเริ่มต้นเหล่านี้ด้วย / สิ้นสุดด้วย:
#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 ++ แต่ถ้าใครต้องการฟังก์ชั่น 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>
)
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());
}
ให้ฉันขยายโซลูชันของโจเซฟด้วยรุ่นที่ไม่คำนึงถึงขนาดตัวพิมพ์ ( การสาธิตออนไลน์ )
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
ใช้ 'สตริง :: เปรียบเทียบ' ทำไมstd::equal(start.begin(), start.end(), str.begin())
ล่ะ
ตัวเลือกอื่นคือการใช้ regex รหัสต่อไปนี้ทำให้การค้นหาไม่คำนึงถึงตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก:
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;
}
ใช้ std :: อัลกอริทึมที่เท่ากันจาก<algorithms>
ด้วยการวนซ้ำย้อนกลับ:
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
เกี่ยวกับการตอบสนองของ Grzegorz Bazior ฉันใช้การใช้งานนี้ แต่ดั้งเดิมมีข้อผิดพลาด (ผลตอบแทนจริงถ้าฉันเปรียบเทียบ ".. " กับ ".so") ฉันเสนอฟังก์ชั่นการแก้ไข:
bool endsWith(const string& s, const string& suffix)
{
return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
ฉันคิดว่ามันสมเหตุสมผลแล้วที่จะโพสต์คำตอบที่ไม่ใช้ฟังก์ชั่นห้องสมุด ...
// 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 :: เริ่มต้นด้วยสตริงที่แน่นอนและแปลงสตริงย่อยเป็น int ได้อย่างไร
คุณสามารถใช้วิธีแก้ปัญหาเพื่อค้นหาเฉพาะตำแหน่งสุดท้ายในสตริง:
bool endsWith(const std::string& stack, const std::string& needle) {
return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}
วิธีนี้ทำให้คุณสั้นเร็วใช้มาตรฐาน c ++ และทำให้อ่านง่าย
หากคุณเป็นเหมือนฉันและไม่ได้เป็นคนเจ้าเล่ห์ C ++ นี่คือลูกผสม skool แบบเก่า มีข้อได้เปรียบบางอย่างเมื่อสตริงมีอักขระมากกว่าหนึ่งตัวเนื่องจาก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;
}
สองเซ็นต์ของฉัน:
bool endsWith(std::string str, std::string suffix)
{
return str.find(suffix, str.size() - suffix.size()) != string::npos;
}