如何检查字符串是否以C中的另一个字符串开头?

the*_*ejh 73 c string comparison startswith

startsWith(str_a, str_b)标准C库中有类似的东西吗?

它应该指向两个以nullbytes结尾的字符串,并告诉我第一个字符串是否也完全出现在第二个字符串的开头.

例子:

"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc"    -> true
Run Code Online (Sandbox Code Playgroud)

Fre*_*Foo 130

这没有标准功能,但您可以定义

bool prefix(const char *pre, const char *str)
{
    return strncmp(pre, str, strlen(pre)) == 0;
}
Run Code Online (Sandbox Code Playgroud)

我们不必担心strpre根据C标准(7.21.4.4/2)更短:

strncmp函数比较不大于n字符从阵列指向(即跟随一个空字符不进行比较字符)s1到阵列指向s2".

  • 为什么答案没有?很明显,答案是肯定的,它被称为"strncmp". (11认同)
  • ^很明显,答案是否定的。使用“ strncmp”和“ strlen”的算法不被称为“ strncmp”。 (2认同)

T.J*_*der 65

显然,没有标准的C功能.所以:

bool startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
           lenstr = strlen(str);
    return lenstr < lenpre ? false : memcmp(pre, str, lenpre) == 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,上面的内容很好而且清晰,但是如果你是在一个紧凑的循环中或者使用非常大的字符串,它可能无法提供最佳性能,因为它会在前面(strlen)扫描两个字符串的全长.像wj32或者Christoph这样解决方案可能会提供更好的性能(虽然这个关于矢量化的评论超出了我的C).另请注意Fred Foo的解决方案,它避免strlenstr(他是对的,没有必要).只对(非常)大字符串或在紧密循环中重复使用有关,但是当它重要时,它很重要.

  • 我应该提到*通常*的东西是字符串是第一个参数,而前缀是第二个参数.但我让他们如上因为似乎是你的问题是如何陷害......的顺序完全取决于你,但我真的应该做它的其他方式"圆 - 大多数字符串函数采取完整的字符串作为第一个参数,子串作为第二个. (5认同)
  • 这是一个优雅的解决方案,但它确实存在一些性能问题。优化的实现永远不会查看每个字符串中超过 min(strlen(pre), strlen(str)) 个字符,也不会查看第一个不匹配之外的字符。如果琴弦很长,但早期不匹配很常见,那么它会很轻。但由于此实现预先获取了两个字符串的完整长度,因此即使字符串的第一个字符不同,它也会强制执行最坏情况的性能。这是否重要取决于具体情况,但这是一个潜在的问题。 (2认同)
  • @TomKarzes您可以在这里用“memcmp”替换“strncmp”,这样速度更快。没有 UB,因为已知两个字符串至少具有“lenpre”字节。`strncmp` 检查两个字符串的每个字节是否为 NUL,但 `strlen` 调用已经保证不存在任何 NUL。(但是当“pre”或“str”比实际的常见初始序列长时,它仍然会受到您提到的性能影响。) (2认同)

Chr*_*oph 32

我可能会去strncmp(),但只是为了一个原始实现的乐趣:

_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
    while(*prefix)
    {
        if(*prefix++ != *string++)
            return 0;
    }

    return 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 我最喜欢这个 - 没有理由扫描任何一个字符串的长度. (6认同)
  • 这可能比`strncmp`慢,除非你的编译器真的擅长矢量化,因为glibc编写者肯定是:-) (4认同)
  • 如果前缀不匹配,则此版本应比strlen + strncmp版本要快,尤其是如果前几个字符已经存在差异时。 (3认同)

wj3*_*j32 5

我不是写优雅代码的专家,但......

int prefix(const char *pre, const char *str)
{
    char cp;
    char cs;

    if (!*pre)
        return 1;

    while ((cp = *pre++) && (cs = *str++))
    {
        if (cp != cs)
            return 0;
    }

    if (!cs)
        return 0;

    return 1;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

使用strstr()功能. Stra == strstr(stra, strb)

  • 这样做似乎有些倒退-即使strb是否为前缀,即使从非常短的初始段中就应该清楚,您也将遍历整个stra。 (3认同)
  • @ilw 这是著名计算机科学家的一句名言——谷歌一下。它经常被误用(就像这里一样)......请参阅http://www.joshbarczak.com/blog/?p=580 (3认同)
  • 过早的优化是万恶之源。我认为这是最好的解决方案,如果它不是时间关键的代码或长字符串。 (2认同)