Strncmp: примеры (PHP)

Сравнение строк в PHP: работа с функцией strncmp
Раздел: Работа со строками
strncmp(string string1, string string2, int length): int
Функция strncmp в PHP: сравнение строк с ограничением длины

Функция strncmp сравнивает две строки в бинарном режиме с учетом регистра, но с возможностью ограничить количество проверяемых символов. Она применяется, когда требуется сравнить не всю строку, а только ее начальную часть (префикс). Это полезно для проверки начала строк, сравнения идентификаторов с общим префиксом или при работе с данными фиксированной длины.

Синтаксис функции: int strncmp(string $string1, string $string2, int $length).

Аргументы функции:

  • string1: первая сравниваемая строка.
  • string2: вторая сравниваемая строка.
  • length: максимальное количество символов для сравнения. Функция сравнит первые $length байтов каждой строки.

Возвращаемое значение:

  • 0, если первые $length символов строк идентичны.
  • Число меньше 0, если строка $string1 в начале меньше строки $string2.
  • Число больше 0, если строка $string1 в начале больше строки $string2.
Практическое применение strncmp
Базовое сравнение префиксов
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 "Префикс первой строки больше";
}
Префиксы совпадают
Альтернативные функции для сравнения строк в PHP
  • 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.
Распространенные ошибки при работе с 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); // Предупреждение и результат как для 0
0
Warning: strncmp(): Length must be greater than or equal to 0
Проблемы с многобайтовыми кодировками (UTF-8)
// Функция работает с байтами, а не символами
echo strncmp("Привет", "Привет", 6); // Сравнивает 6 байт, а не 6 символов!
0 (может быть не 0, если 6 байт - это часть многобайтового символа)

Для многобайтовых строк следует использовать mb_strncmp из расширения mbstring, если такая функция эмулируется, или работать через mb_substr и strcmp.

История изменений функции strncmp
  • В PHP 7.0 не было специфичных изменений для strncmp, но общее строгое отношение к типам могло косвенно повлиять на передачу нестроковых аргументов.
  • В PHP 8.0 функция стала более строгой к типам передаваемых аргументов. Передача аргументов не строкового типа теперь вызывает предупреждение TypeError, тогда как ранее они преобразовывались в строки.
  • С PHP 8.2 явных изменений в поведении strncmp не внесено.

Рекомендуется всегда передавать в функцию строки (string).

Расширенные примеры использования strncmp
Проверка типа строки по префиксу
Пример php
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
Сравнение строк с автоматическим определением длины
Пример php
// Сравнение по длине более короткой строки
$str1 = "short";
$str2 = "longer_string";
$len = min(strlen($str1), strlen($str2), 10); // Ограничение максимум 10 символов
$result = strncmp($str1, $str2, $len);
echo $result;
-11 (или другое ненулевое значение, так как строки разные)
Использование в сортировке по префиксу
Пример php
$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
)
Эмуляция strncasecmp с помощью strncmp
Пример php
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"))  # 0
True
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, 1
0

Strncmp в MySQL

-- Функция STRCMP сравнивает строки полностью.
-- Для сравнения префиксов можно использовать LEFT() или оператор LIKE.
SELECT STRCMP(LEFT('Hello', 3), LEFT('Hel', 3)); -- 0
0

Основное отличие PHP-функции в её бинарной безопасности и чётком возврате целого числа, указывающего на отношение порядка строк, а не просто факт совпадения.

PHP strncmp function comments

En
Strncmp Binary safe string comparison of the first n characters