C语言 如何检查一个字符串是否以C中的另一个字符串开头?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4770985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a string starts with another string in C?
提问by thejh
Is there something like startsWith(str_a, str_b)in the standard C library?
startsWith(str_a, str_b)标准 C 库中有类似的东西吗?
It should take pointers to two strings that end with nullbytes, and tell me whether the first one also appears completely at the beginning of the second one.
它应该使用指向以空字节结尾的两个字符串的指针,并告诉我第一个字符串是否也完全出现在第二个字符串的开头。
Examples:
例子:
"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc" -> true
采纳答案by T.J. Crowder
Apparently there's no standard C function for this. So:
显然,这没有标准的 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;
}
Note that the above is nice and clear, but if you're doing it in a tight loop or working with verylarge strings, it does not offer the best performance, as it scans the full length of both strings up front (strlen). Solutions like wj32'sor Christoph'smay offer better performance (although this commentabout vectorization is beyond my ken of C). Also note Fred Foo's solutionwhich avoids strlenon str(he's right, it's unnecessary if you use strncmpinstead of memcmp). Only matters for (very) large strings or repeated use in tight loops, but when it matters, it matters.
请注意,上面的内容很好且清晰,但是如果您在紧密循环中执行此操作或使用非常大的字符串,则它不会提供最佳性能,因为它会预先扫描两个字符串的全长 ( strlen)。wj32或Christoph 之类的解决方案可能会提供更好的性能(尽管这个关于矢量化的评论超出了我对 C 的理解)。还要注意Fred Foo 的解决方案,它避免了strlenon str(他是对的,如果您使用strncmp而不是,则没有必要memcmp)。仅对于(非常)大的字符串或在紧密循环中重复使用很重要,但是当它很重要时,它很重要。
回答by Fred Foo
There's no standard function for this, but you can define
对此没有标准功能,但您可以定义
bool prefix(const char *pre, const char *str)
{
return strncmp(pre, str, strlen(pre)) == 0;
}
We don't have to worry about strbeing shorter than prebecause according to the C standard (7.21.4.4/2):
我们不必担心str比pre因为根据 C 标准 (7.21.4.4/2)更短:
The
strncmpfunction compares not more thanncharacters (characters that follow a null character are not compared) from the array pointed to bys1to the array pointed to bys2."
该
strncmp函数比较不超过n字符(不比较空字符后面的字符)从 指向的数组到s1指向的数组s2。”
回答by Christoph
I'd probably go with strncmp(), but just for fun a raw implementation:
我可能会使用strncmp(),但只是为了好玩一个原始实现:
_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
while(*prefix)
{
if(*prefix++ != *string++)
return 0;
}
return 1;
}
回答by wj32
I'm no expert at writing elegant code, but...
我不是编写优雅代码的专家,但是......
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;
}
回答by gscott
Use strstr()function. Stra == strstr(stra, strb)
使用strstr()功能。 Stra == strstr(stra, strb)
回答by Zloten
Optimized (v.2. - corrected):
优化(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;
}
回答by shpc
Or a combination of the two approaches:
或者两种方法的组合:
_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));
}
}
EDIT:The code below does NOTwork because if strncmp returns 0 it is not known if a terminating 0 or the length (block_size) was reached.
编辑:下面的代码做NOT工作,因为如果STRNCMP返回0,如果终止0或长度(BLOCK_SIZE)达到它是未知的。
An additional idea is to compare block-wise. If the block is not equal compare that block with the original function:
另一个想法是逐块比较。如果块不相等,则将该块与原始函数进行比较:
_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);
string += block_size;
prefix += block_size;
if ( block_size < 4096 )
block_size *= 2;
}
}
The constants 13, 64, 4096, as well as the exponentiation of the block_sizeare just guesses. It would have to be selected for the used input data and hardware.
常数13、64、4096以及 的取幂block_size只是猜测。必须为使用的输入数据和硬件选择它。
回答by Jordan
Because I ran the accepted version and had a problem with a very long str, I had to add in the following logic:
因为我运行了接受的版本并且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;
}

