如何比较C中字符串的结尾?

34 c string

我想确保我的字符串以".foo"结尾.我正在使用C,这是一种我并不完全熟悉的语言.我发现这样做的最好方法是在下面.任何C大师都想确保我优雅而明智地做到这一点?

int EndsWithFoo(char *str)
{
    if(strlen(str) >= strlen(".foo"))
    {
        if(!strcmp(str + strlen(str) - strlen(".foo"), ".foo"))
        {
            return 1;
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

pli*_*nth 47

不要每个字符串多次调用strlen.

int EndsWith(const char *str, const char *suffix)
{
    if (!str || !suffix)
        return 0;
    size_t lenstr = strlen(str);
    size_t lensuffix = strlen(suffix);
    if (lensuffix >  lenstr)
        return 0;
    return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}

int EndsWithFoo(const char *str) { return EndsWith(str, ".foo"); }
Run Code Online (Sandbox Code Playgroud)

编辑:添加NULL检查迂腐.对于超级迂腐,如果str和后缀都是NULL,它是否应该返回非零的争论.

  • 在这种情况下,您可以使用 strcmp() 而不是 strncmp()(甚至 memcmp()),因为我们确切地知道此时两个字符串中还剩下多少字符,尽管速度差异几乎不明显. (3认同)
  • 一旦您打开优化,对 strlen 的任何调用都会从程序集中消失,因此这可能是过早优化的一种情况(尽管 C 字符串很糟糕,足以让人思考此类问题) (2认同)
  • @MattJ:有点晚了...,但我认为 adam 的意思是编译器将删除所有调用,但每个字符串的第一个调用除外,因为它们没有更改。您当然是正确的,并非所有这些都可以被优化掉。 (2认同)

小智 11

int EndsWithFoo( char *string )
{
  string = strrchr(string, '.');

  if( string != NULL )
    return( strcmp(string, ".foo") );

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

如果以".foo"结尾,则返回0.

  • 返回值应该反转,因为零为假且非零为真,并且函数的名称表示布尔返回. (4认同)

Bas*_*ard 7

我现在无法访问编译器,所以有人可以告诉我这是否有效吗?

#include <stdio.h>
#include <string.h>

int EndsWithFoo(const char* s);

int
main(void)
{
  printf("%d\n", EndsWithFoo("whatever.foo"));

  return 0;
}

int EndsWithFoo(const char* s)
{
  int ret = 0;

  if (s != NULL)
  {
    size_t size = strlen(s);

    if (size >= 4 &&
        s[size-4] == '.' &&
        s[size-3] == 'f' &&
        s[size-2] == 'o' &&
        s[size-1] == 'o')
    {
      ret = 1;
    }
  }

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

无论如何,请确保将参数限定为const,它告诉所有人(包括编译器)您不打算修改字符串.

  • 只是一个提示:如果你有互联网连接,你可以在codepad.org上找到一个C编译器 (3认同)

小智 5

这是使用 memcmp() 返回与 Python str.endswith() 相同的值的通用解决方案。不检查 str / 后缀是否为 NULL 是有意的,其他 libc str 函数也不检查 NULL:

int ends_with(const char *str, const char *suffix) {
  size_t str_len = strlen(str);
  size_t suffix_len = strlen(suffix);

  return (str_len >= suffix_len) &&
         (!memcmp(str + str_len - suffix_len, suffix, suffix_len));
}
Run Code Online (Sandbox Code Playgroud)

测试C:

printf("%i\n", ends_with("", ""));
printf("%i\n", ends_with("", "foo"));
printf("%i\n", ends_with("foo", ""));
printf("%i\n", ends_with("foo", "foo"));
printf("%i\n", ends_with("foo", "foobar"));
printf("%i\n", ends_with("foo", "barfoo"));
printf("%i\n", ends_with("foobar", "foo"));
printf("%i\n", ends_with("barfoo", "foo"));
printf("%i\n", ends_with("foobarfoo", "foo"));
Run Code Online (Sandbox Code Playgroud)

结果C:

1
0
1
1
0
0
0
1
1
Run Code Online (Sandbox Code Playgroud)

测试Python:

print("".endswith(""))
print("".endswith("foo"))
print("foo".endswith(""))
print("foo".endswith("foo"))
print("foo".endswith("foobar"))
print("foo".endswith("barfoo"))
print("foobar".endswith("foo"))
print("barfoo".endswith("foo"))
print("foobarfoo".endswith("foo"))
Run Code Online (Sandbox Code Playgroud)

结果Python:

True
False
True
True
False
False
False
True
True
Run Code Online (Sandbox Code Playgroud)


dir*_*tly 2

sstrlen(".foo")不是必需的。如果你真的想让它灵活,你可以使用sizeof ".foo" - 1-- 编译时间常量。

另外,空字符串检查也很好。