تابع strncmp() در PHP
تابع strncmp() در PHP برای مقایسه بایت به بایتِ دو رشته تا حداکثر تعداد مشخصی از کاراکترها استفاده میشود. این تابع binary-safe است و به صورت حساس به حروف (case-sensitive) عمل میکند. برای مقایسه کامل رشتهها یا بررسی پیشوندها (prefix) کاربرد بسیار معمولی دارد.
امضای تابع
تعریف تابع به شکل زیر است:
int strncmp ( string $str1 , string $str2 , int $len )سه آرگومان: رشته اول، رشته دوم و تعداد بایت/کاراکترهایی که باید مقایسه شوند (len).
مقدار بازگشتی
| مقدار بازگشتی | معنی |
|---|---|
| < 0 | str1 کوچکتر از str2 در مقایسهی اولین len بایت |
| 0 | اولین len بایت هر دو رشته برابر هستند |
| > 0 | str1 بزرگتر از str2 در همان محدوده |
نکات کلیدی
- عملیات byte-wise است؛ بنابراین در رشتههای UTF-8 ممکن است کاراکترهای چندبایتی به درستی تقسیم نشوند.
- حساس به حروف است؛ برای مقایسه بدون حساسیت از strncasecmp() استفاده کنید.
- برای مقایسه رمزنگاریای (محافظت در برابر timing attack) از hash_equals() استفاده کنید، نه strncmp.
- اگر len برابر صفر باشد، تابع مقدار 0 برمیگرداند (هیچ بایتی مقایسه نشده است).
مثالهای کاربردی
1. بررسی پیشوند (prefix)
<?php
$haystack = 'applepie';
$needle = 'app';
if (strncmp($haystack, $needle, strlen($needle)) === 0) {
echo "پیشوند مطابقت دارد";
} else {
echo "مطابقت ندارد";
}
?>در این مثال با استفاده از strncmp و طول needle بررسی میکنیم که آیا رشته اول با needle شروع میشود یا خیر. استفاده از === 0 ضروری است تا از برابری دقیق عددی اطمینان حاصل شود.
2. مقایسه جزئی (اولین n کاراکتر)
<?php
$a = "HelloWorld";
$b = "HelloMars";
$result = strncmp($a, $b, 5); // فقط 5 کاراکتر اول مقایسه میشود
if ($result === 0) {
echo "پنج کاراکتر اول برابرند";
} elseif ($result < 0) {
echo "a کمتر است";
} else {
echo "a بزرگتر است";
}
?>این کد اولین 5 کاراکتر را مقایسه میکند و نتیجه را براساس مقدار عددی بازگشتی تفسیر میکند.
مقایسه با توابع دیگر و انتخاب درست
- strcmp/strncmp: بایت به بایت و حساس به حروف.
- strncasecmp: مشابه strncmp اما حساسیت به حروف را حذف میکند (case-insensitive).
- substr_compare: امکانات بیشتری مانند مشخص کردن offset و case-insensitive را فراهم میکند.
- strstr/strpos: برای پیدا کردن وجود یک زیررشته (یا موقعیت) کاربردیتر و در برخی موارد سریعترند؛ اما برای تعیین ترتیب lexicographic مناسب نیستند.
جایگزین ایمن برای مقایسههای رمزنگاری
<?php
// مقایسه کلیدها یا توکنها — نبايد از strncmp برای مقایسه امن استفاده کرد
$a = hash('sha256', 'secret1');
$b = hash('sha256', 'secret2');
if (hash_equals($a, $b)) {
echo "برابرند";
} else {
echo "مخالفند";
}
?>برای مقایسه مقادیر هش یا توکنها که نیاز به مقاومت در برابر حملات زمانبندی دارند، از hash_equals استفاده کنید. strncmp بهدلیل رفتار زمانی وابسته به محتوای رشته، مناسب حملات timing نیست.
ملاحظات مربوط به Unicode و UTF-8
از آنجا که strncmp بر پایه بایت عمل میکند، در کار با رشتههای چندبایتی (مانند UTF-8) ممکن است مرزهای کاراکتر شکسته شوند و نتیجهی غیرمنتظره بدهد. برای کار ایمن با متنهای UTF-8 از توابع multibyte (mb_*) استفاده کنید یا پیش از مقایسه از mb_substr استفاده کنید تا کاراکترها حفظ شوند.
<?php
// نسخهای سازگار با UTF-8 برای بررسی پیشوند
$haystack = 'سلامدنیا';
$needle = 'سلام';
$len = mb_strlen($needle, 'UTF-8');
if (mb_substr($haystack, 0, $len, 'UTF-8') === $needle) {
echo "پیشوند UTF-8 مطابقت دارد";
} else {
echo "مطابقت ندارد";
}
?>در این نمونه از mb_substr و mb_strlen برای برش و مقایسه کاراکتر-محور استفاده شده است تا اشکال ناشی از بایتشکنی در UTF-8 رخ ندهد. هرچند این روش نسبت به strncmp هزینه پردازشی بیشتری دارد اما برای متنهای چندبایتی صحیحتر است.
نمونه بهینه برای بررسی پیشوند (میان کارایی و درستی)
اگر رشتهها ASCII باشند و کارایی مهم باشد، استفاده از strncmp بهترین انتخاب است. اما برای UTF-8 یا رشتههای کاراکتر-محور، از mb_* یا substr_compare با پارامترهای مناسب استفاده کنید.
<?php
// استفاده از substr_compare برای بررسی پیشوند (حساس یا غیرحساس به حروف)
$haystack = 'ExampleString';
$needle = 'example';
if (substr_compare($haystack, $needle, 0, strlen($needle), true) === 0) {
echo "پیشوند بدون حساسیت به حروف برابر است";
} else {
echo "مطابقت ندارد";
}
?>substr_compare این امکان را میدهد که از offset استفاده کنید و همچنین با پارامتر آخر، مقایسه را case-insensitive کنید. برای رشتههای ASCII این روش راحت و کاربردی است.
جمعبندی و توصیههای عملی
- از strncmp برای مقایسه سریع بایتبهبایت تا n کاراکتر استفاده کنید، مخصوصاً برای رشتههای ASCII یا دادههای باینری.
- برای مقایسهای بدون حساسیت به حروف از strncasecmp بهره ببرید.
- در کار با UTF-8 و متنهای چندبایتی از توابع mb_* یا راهکارهای مبتنی بر کاراکتر استفاده کنید.
- برای مقایسه امنِ توکنها یا هشها از hash_equals استفاده کنید تا در برابر حملات timing مقاوم باشید.
- همیشه در بررسی پیشوند از === 0 استفاده کنید تا اشتباهات ناشی از تبدیل نوع پیش نیاید.
با رعایت این نکات میتوانید از strncmp بهدرستی و با کارایی مناسب در پروژههای PHP استفاده کنید و از تلههای مربوط به کاراکترهای چندبایتی و امنیت جلوگیری نمایید.
آیا این مطلب برای شما مفید بود ؟



