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

时间:2011-01-22 22:15:23

标签: c string comparison startswith

标准C库中是否有类似startsWith(str_a, str_b)的内容?

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

示例:

"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc"    -> true

9 个答案:

答案 0 :(得分:121)

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

bool prefix(const char *pre, const char *str)
{
    return strncmp(pre, str, strlen(pre)) == 0;
}

我们不必担心str短于pre,因为根据C标准(7.21.4.4/2):

  

strncmp函数将n指向的数组与s1指向的数组进行比较,不超过s2个字符(不会比较空字符后面的字符) 1}}。“

答案 1 :(得分:60)

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

bool startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
           lenstr = strlen(str);
    return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0;
}

请注意,上面的内容非常简洁明了,但是如果您在紧密循环中使用非常大字符串,它可能无法提供最佳性能,因为它会扫描完整前面两个字符串的长度(strlen)。像wj32'sChristoph's这样的解决方案可能会提供更好的性能(尽管关于矢量化的this comment超出了我的C)。另请注意Fred Foo's solution,这会避免strlen str(他是对的,这是不必要的)。只适用于(非常)大字符串或在紧密循环中重复使用,但重要的是,它很重要。

答案 2 :(得分:27)

我可能会选择strncmp(),但只是为了实现原始实现:

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

    return 1;
}

答案 3 :(得分: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;
}

答案 4 :(得分:5)

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

答案 5 :(得分:1)

因为我运行了已接受的版本并且遇到了很长的str问题,所以我不得不添加以下逻辑:

bool longEnough(const char *str, int min_length) {
    int length = 0;
    while (str[length] && length < min_length)
        length++;
    if (length == min_length)
        return true;
    return false;
}

bool startsWith(const char *pre, const char *str) {
    size_t lenpre = strlen(pre);
    return longEnough(str, lenpre) ? strncmp(str, pre, lenpre) == 0 : false;
}

答案 6 :(得分:1)

优化(v.2。 - 更正):

uint32 startsWith( const void* prefix_, const void* str_ ) {
    uint8 _cp, _cs;
    const uint8* _pr = (uint8*) prefix_;
    const uint8* _str = (uint8*) str_;
    while ( ( _cs = *_str++ ) & ( _cp = *_pr++ ) ) {
        if ( _cp != _cs ) return 0;
    }
    return !_cp;
}

答案 7 :(得分:0)

或两种方法的组合:

_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
    char * const restrict prefix_end = prefix + 13;
    while (1)
    {
        if ( 0 == *prefix  )
            return 1;   
        if ( *prefix++ != *string++)
            return 0;
        if ( prefix_end <= prefix  )
            return 0 == strncmp(prefix, string, strlen(prefix));
    }  
}

另一个想法是按块比较。如果该块不相等,则将该块与原始函数进行比较:

_Bool starts_with_big(const char *restrict string, const char *restrict prefix)
{
    size_t block_size = 64;
    while (1)
    {
        if ( 0 != strncmp( string, prefix, block_size ) )
          return starts_with( string, prefix);
        if ( block_size < 4096 )
          block_size *= 2;
        string += block_size;
        prefix += block_size;
    }
}

常数13644096以及block_size的幂只是猜测。必须为使用的输入数据和硬件选择它。

答案 8 :(得分:-6)

优化

boolean StartsWith(char *s1, char *s2)
{
  while (*s1++ == *s2++)
  {
  }

  return *s2 == 0;
}