要檢查一個字串 $str1 是否包含另一個字串 $str2,我們可以使用 PHP 內建的 strpos() 函數。然而,strpos() 存在一個常見的「陷阱」:如果子字串 $str2 在 $str1 的開頭(也就是索引 0)被找到,strpos() 會返回 0。在布林上下文中,0 會被評估為 false,這可能導致判斷錯誤。
strpos() 的潛在陷阱與修正
讓我們看看這個潛在的陷阱:
PHP
<?php
$str1 = 'yabadabadoo';
$str2 = 'yaba';
// 錯誤的檢查方式:
if (strpos($str1, $str2) == FALSE) { // 或者 !strpos($str1, $str2)
echo "'$str1' 不包含 '$str2' (錯誤判斷)\n";
} else {
echo "'$str1' 包含 '$str2'\n";
}
// 修正後的檢查方式:
if (strpos($str1, $str2) !== FALSE) {
echo "'$str1' 包含 '$str2' (正確判斷)\n";
} else {
echo "'$str1' 不包含 '$str2'\n";
}
?>
在上面的例子中,strpos($str1, $str2) 會返回 0,因為 'yaba' 就在 'yabadabadoo' 的開頭。
- 當我們使用
== FALSE進行比較時,0 == FALSE為true,導致程式誤判為不包含。 - 正確的修正方法是使用嚴格比較運算符
!== FALSE(或=== 0進行精確匹配,但!== FALSE更通用於任何位置的查找),這樣就能區分子字串不存在(返回false)和子字串在開頭(返回0)。
完整的程式碼範例
以下是如何正確檢查 $str1 是否包含 $str2 的程式碼:
PHP
<?php
function containsString(string $haystack, string $needle): bool
{
/**
* 檢查一個字串是否包含另一個字串。
*
* @param string $haystack 搜尋的原始字串。
* @param string $needle 要搜尋的子字串。
* @return bool 如果包含則返回 true,否則返回 false。
*/
// 使用 !== FALSE 進行嚴格比較,避免 strpos 返回 0 時的誤判
return strpos($haystack, $needle) !== FALSE;
}
// 範例 1: 子字串在開頭
$str1_a = 'yabadabadoo';
$str2_a = 'yaba';
if (containsString($str1_a, $str2_a)) {
echo "案例 1: '$str1_a' 包含 '$str2_a'\n"; // 預期輸出:包含
} else {
echo "案例 1: '$str1_a' 不包含 '$str2_a'\n";
}
// 範例 2: 子字串在中間
$str1_b = 'hello world';
$str2_b = 'world';
if (containsString($str1_b, $str2_b)) {
echo "案例 2: '$str1_b' 包含 '$str2_b'\n"; // 預期輸出:包含
} else {
echo "案例 2: '$str1_b' 不包含 '$str2_b'\n";
}
// 範例 3: 子字串不存在
$str1_c = 'programming';
$str2_c = 'code';
if (containsString($str1_c, $str2_c)) {
echo "案例 3: '$str1_c' 包含 '$str2_c'\n";
} else {
echo "案例 3: '$str1_c' 不包含 '$str2_c'\n"; // 預期輸出:不包含
}
// 範例 4: 空字串作為子字串
$str1_d = 'abc';
$str2_d = '';
if (containsString($str1_d, $str2_d)) {
echo "案例 4: '$str1_d' 包含 '$str2_d' (空字串通常被認為是包含的)\n"; // 預期輸出:包含
} else {
echo "案例 4: '$str1_d' 不包含 '$str2_d'\n";
}
?>
其他考慮
除了 strpos(),PHP 還提供了其他函數來檢查字串包含性,例如:
strstr(): 這個函數會在$haystack中查找$needle,如果找到,則返回$needle及其之後的部分;如果找不到,則返回FALSE。它的行為與strpos()類似,也需要使用嚴格比較 (!== FALSE)。str_contains()(PHP 8+ 引入): 這是 PHP 8 及更高版本中引入的一個專門用於檢查字串包含性的函數。它直接返回布林值true或false,因此沒有strpos()的陷阱,使用起來更直觀、安全。如果您的環境允許,強烈建議使用此函數。
使用 str_contains() 的範例:
PHP
<?php
// 僅適用於 PHP 8 及更高版本
$str1 = 'yabadabadoo';
$str2 = 'yaba';
if (str_contains($str1, $str2)) {
echo "使用 str_contains(): '$str1' 包含 '$str2'\n";
} else {
echo "使用 str_contains(): '$str1' 不包含 '$str2'\n";
}
?>
總之,當使用 strpos() 時,務必記住使用嚴格比較運算符 !== FALSE 來避免因子字串在索引 0 導致的判斷錯誤。如果您的 PHP 版本是 8 或更高,那麼 str_contains() 則是更簡潔、更安全的選擇。
沒有留言:
張貼留言