在c++中,如何知道字符串是否以另一个字符串结束?


当前回答

注意,从c++20开始std::string将最终提供starts_with和ends_with。看起来c++中的字符串有可能最终变得可用,如果你不是在遥远的将来读到这篇文章,你可以在c++ 17中使用这些startsWith/endsWith:

#if __cplusplus >= 201703L // C++17 and later 
#include <string_view>

static bool endsWith(std::string_view str, std::string_view suffix)
{
    return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}

static bool startsWith(std::string_view str, std::string_view prefix)
{
    return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
}
#endif // C++17

如果你坚持使用旧的c++,你可以使用这些:

#if __cplusplus < 201703L // pre C++17
#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);
}

并且一些额外的helper会重载:

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));
}
#endif

在我看来,c++字符串显然是功能失调的,而且不适合在现实世界的代码中使用。但至少有希望情况会有所好转。

其他回答

使用std::string::compare:比较最后n个字符:

#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;
}
bool endswith(const std::string &str, const std::string &suffix)
{
    string::size_type totalSize = str.size();
    string::size_type suffixSize = suffix.size();

    if(totalSize < suffixSize) {
        return false;
    }

    return str.compare(totalSize - suffixSize, suffixSize, suffix) == 0;
}

使用std::equal算法从<algorithms>与反向迭代:

std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
   …
}

从c++ 20开始引入ends_with。

如果像我一样,你需要endsWith来检查文件扩展名,你可以使用std::filesystem库:

std::filesystem::path("/foo/bar.txt").extension() == ".txt"

如果你像我一样,对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;
}