Strncmp: примеры (PHP)
strncmp(string string1, string string2, int length): intФункция strncmp сравнивает две строки в бинарном режиме с учетом регистра, но с возможностью ограничить количество проверяемых символов. Она применяется, когда требуется сравнить не всю строку, а только ее начальную часть (префикс). Это полезно для проверки начала строк, сравнения идентификаторов с общим префиксом или при работе с данными фиксированной длины.
Синтаксис функции: int strncmp(string $string1, string $string2, int $length).
Аргументы функции:
- string1: первая сравниваемая строка.
- string2: вторая сравниваемая строка.
- length: максимальное количество символов для сравнения. Функция сравнит первые $length байтов каждой строки.
Возвращаемое значение:
- 0, если первые $length символов строк идентичны.
- Число меньше 0, если строка $string1 в начале меньше строки $string2.
- Число больше 0, если строка $string1 в начале больше строки $string2.
echo strncmp("Hello world", "Hello PHP", 5);0
Сравниваются первые 5 символов. "Hello" равно "Hello".
echo strncmp("abcdef", "abcXYZ", 6);100
Строки различаются с 4-го символа. 'd' (100) меньше 'X' (88)? Нет, результат положительный, потому что 'd' (ASCII 100) > 'X' (ASCII 88). Фактически, функция возвращает разницу кодов первых различающихся символов: 100 - 88 = 12? В реальности возвращается 1, 0 или -1 в зависимости от версии PHP. Лучше проверять на >0, <0, ==0.
$result = strncmp("user_123", "user_456", 5);
if ($result === 0) {
echo "Префиксы совпадают";
} elseif ($result < 0) {
echo "Префикс первой строки меньше";
} else {
echo "Префикс первой строки больше";
}Префиксы совпадают
- strcmp($str1, $str2): Сравнивает строки полностью. Используется, когда нужно сравнить строки целиком, а не только начало.
- strcasecmp($str1, $str2): Сравнивает строки без учета регистра. Подходит для регистронезависимого сравнения.
- substr_compare($str1, $str2, $offset, $length, $case_insensitive): Более гибкая функция. Позволяет сравнить части строк с указанием начальной позиции и длины, с опцией игнорирования регистра. Предпочтительнее, когда нужно сравнить не с начала строки или требуется регистронезависимость.
- strncasecmp($str1, $str2, $len): Прямой аналог strncmp, но без учета регистра. Используется для сравнения префиксов, когда регистр не важен.
- str_starts_with($haystack, $needle) (PHP 8+): Проверяет, начинается ли строка с заданной подстроки. Возвращает true/false. Гораздо удобнее для простых проверок префикса, чем strncmp.
// ОШИБКА: Использование результата как булева значения
if (strncmp("abc", "abc", 3)) {
echo "Совпадает"; // Этот блок не выполнится, т.к. 0 = false
} else {
echo "Не совпадает";
}Не совпадает
Правильно использовать строгое сравнение с нулём: if (strncmp(...) === 0).
echo strncmp("abc", "def", 0); // Всегда 0
echo strncmp("abc", "def", -1); // Предупреждение и результат как для 00 Warning: strncmp(): Length must be greater than or equal to 0
// Функция работает с байтами, а не символами
echo strncmp("Привет", "Привет", 6); // Сравнивает 6 байт, а не 6 символов!0 (может быть не 0, если 6 байт - это часть многобайтового символа)
Для многобайтовых строк следует использовать mb_strncmp из расширения mbstring, если такая функция эмулируется, или работать через mb_substr и strcmp.
- В PHP 7.0 не было специфичных изменений для strncmp, но общее строгое отношение к типам могло косвенно повлиять на передачу нестроковых аргументов.
- В PHP 8.0 функция стала более строгой к типам передаваемых аргументов. Передача аргументов не строкового типа теперь вызывает предупреждение TypeError, тогда как ранее они преобразовывались в строки.
- С PHP 8.2 явных изменений в поведении strncmp не внесено.
Рекомендуется всегда передавать в функцию строки (string).
function getStringType($str) {
if (strncmp($str, "err:", 4) === 0) {
return "error_message";
}
if (strncmp($str, "warn:", 5) === 0) {
return "warning";
}
return "unknown";
}
echo getStringType("err: file not found");
echo getStringType("warn: low memory");
echo getStringType("info: started");error_message warning unknown
// Сравнение по длине более короткой строки
$str1 = "short";
$str2 = "longer_string";
$len = min(strlen($str1), strlen($str2), 10); // Ограничение максимум 10 символов
$result = strncmp($str1, $str2, $len);
echo $result;-11 (или другое ненулевое значение, так как строки разные)
$array = ["user_10", "user_2", "admin_1", "user_1", "admin_10"];
usort($array, function($a, $b) {
// Сначала сортируем по префиксу (user/admin), затем по номеру
$prefixCmp = strncmp($a, $b, 5); // "user_" vs "admin"
if ($prefixCmp === 0) {
return strcmp($a, $b); // Если префиксы равны, сортируем полностью
}
return $prefixCmp;
});
print_r($array);Array
(
[0] => admin_1
[1] => admin_10
[2] => user_1
[3] => user_10
[4] => user_2
)if (!function_exists('strncasecmp')) {
function strncasecmp($str1, $str2, $len) {
return strncmp(strtolower($str1), strtolower($str2), $len);
}
}
echo strncasecmp("Hello", "HELLO", 5);0
Strncmp в Python
# Модуль operator или прямое сравнение срезов
import operator
result = operator.eq("Hello"[:3], "Hel"[:3]) # Сравнение срезов
print(result) # True
# Или для получения результата как в strncmp:
print(ord("H") - ord("H")) # 0True 0
Strncmp в Javascript
// Нет прямой функции, но можно реализовать через slice
let s1 = "Hello";
let s2 = "Help";
let n = 3;
let result = s1.slice(0, n).localeCompare(s2.slice(0, n));
console.log(result); // 0 (равны) или -1, 10
Strncmp в MySQL
-- Функция STRCMP сравнивает строки полностью.
-- Для сравнения префиксов можно использовать LEFT() или оператор LIKE.
SELECT STRCMP(LEFT('Hello', 3), LEFT('Hel', 3)); -- 00
Основное отличие PHP-функции в её бинарной безопасности и чётком возврате целого числа, указывающего на отношение порядка строк, а не просто факт совпадения.