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


当前回答

我认为发布一个不使用任何库函数的原始解决方案是有意义的…

// 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;
}

其他回答

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

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

让我用不区分大小写的版本扩展Joseph的解决方案(在线演示)

#include <string>
#include <cctype>

static bool EndsWithCaseInsensitive(const std::string& value, const std::string& ending) {
    if (ending.size() > value.size()) {
        return false;
    }
    return std::equal(ending.crbegin(), ending.crend(), value.crbegin(),
        [](const unsigned char a, const unsigned char b) {
            return std::tolower(a) == std::tolower(b);
        }
    );
}

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

在我看来,最简单的c++解决方案是:

bool endsWith(const std::string& s, const std::string& suffix)
{
    return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}

警告:如果匹配失败,这将在放弃之前向后搜索整个字符串,从而可能浪费大量循环。

使用这个函数:

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());
}