標準C庫中是否有類似startsWith(str_a, str_b)
的東西?如何檢查一個字符串是否以C中的另一個字符串開頭?
它應該指向以nullbytes結尾的兩個字符串,並告訴我第一個字符串是否也完全出現在第二個字符串的開頭。
例子:
"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc" -> true
標準C庫中是否有類似startsWith(str_a, str_b)
的東西?如何檢查一個字符串是否以C中的另一個字符串開頭?
它應該指向以nullbytes結尾的兩個字符串,並告訴我第一個字符串是否也完全出現在第二個字符串的開頭。
例子:
"abc", "abcdef" -> true
"abcdef", "abc" -> false
"abd", "abdcef" -> true
"abc", "abc" -> true
顯然有對此不存在標準的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's或Christoph's之類的解決方案可能會提供更好的性能(儘管關於矢量化的this comment超出了我對C的評價)。還請注意Fred Foo's solution,它在str
上避免了strlen
(他是對的,這是不必要的)。只對(非常)大的琴絃或在緊密環路中重複使用很重要,但重要時,它很重要。
我應該提到*通常*的事情是將字符串作爲第一個參數,並將其作爲前綴。但我像上面一樣保留它們,因爲這似乎是你的問題是如何構建的......順序完全取決於你,但我真的應該以另一種方式完成它 - 大多數字符串函數都採用完整字符串作爲第一個參數,子字符串作爲第二個參數。 – 2011-01-22 22:31:03
這是一個優雅的解決方案,但確實有一些性能問題。一個優化的實現永遠不會從每個字符串中查看超過min(strlen(pre),strlen(str))字符,也不會超越第一個不匹配。如果琴絃很長,但早期的不匹配很常見,它會非常輕便。但是由於這個實現將兩個字符串的全部長度都放在前面,所以即使字符串在第一個字符中不同,它也會強制最差情況下的性能。這是否真的取決於具體情況,但這是一個潛在的問題。 – 2018-01-06 11:33:02
@TomKarzes:當然,我被字符串長度是一個已知值的語言/環境所迷惑,而不是我們必須弄清楚的。 :-) [wj32的解決方案](https://stackoverflow.com/a/4771055/157247)提供更好的性能。只對(非常)大字符串或緊密循環很重要,但重要時,它很重要。 – 2018-01-06 11:38:00
有這個沒有標準的功能,但你可以定義
bool prefix(const char *pre, const char *str)
{
return strncmp(pre, str, strlen(pre)) == 0;
}
我們不必擔心str
因爲根據C標準是小於pre
(7.21.4.4/2):
strncmp
函數不超過n
字符(即跟隨一個空字符的字符不進行比較)從陣列比較指向s1
到陣列由s2
指向。」
爲什麼答案不是?顯然,答案是肯定的,它被稱爲`strncmp`。 – Jasper 2017-02-13 00:39:39
我在寫優雅的代碼專家,但...
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;
}
使用strstr()
功能。 Stra == strstr(stra, strb)
這似乎有點倒退 - 如果strb是一個前綴,那麼即使它應該從非常短的初始段中清楚,您仍然會穿過整個stra。 – StasM 2011-01-22 23:02:04
我可能會用strncmp()
去,但只是爲了好玩原始的實現:
_Bool starts_with(const char *restrict string, const char *restrict prefix)
{
while(*prefix)
{
if(*prefix++ != *string++)
return 0;
}
return 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;
}
優化(第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;
}
優化:
boolean StartsWith(char *s1, char *s2)
{
while (*s1++ == *s2++)
{
}
return *s2 == 0;
}
我認爲你的第三個例子應該有一個真實的結果。 – 2011-01-23 06:19:50
@Burr:是的,沒錯。 – thejh 2011-01-23 11:24:42