تابع strncasecmp() در PHP
تابع strncasecmp() در PHP برای مقایسهٔ دو رشته بهصورت غیرحساس به حروف بزرگ/کوچک استفاده میشود؛ اما تنها تا n کاراکتر (یا بایت) اول را بررسی میکند. این تابع در مواردی که میخواهیم پیشوندها یا اولین بخشهای رشتهها را با هم مقایسه کنیم و فرق حروف بزرگ و کوچک اهمیت نداشته باشد، بسیار کاربردی است.
سینتکس و مقدار بازگشتی
سینتکس:
int strncasecmp ( string $str1 , string $str2 , int $len )مقدار بازگشتی:
| مقدار | معنی |
|---|---|
| < 0 | $str1 کوچکتر از $str2 است (در ترتیب بایت/کاراکتر) |
| 0 | تا n کاراکتر اول برابراند (بدون توجه به حروف بزرگ/کوچک) |
| > 0 | $str1 بزرگتر از $str2 است |
پارامترها
- $str1: رشتهٔ اول برای مقایسه.
- $str2: رشتهٔ دوم برای مقایسه.
- $len: تعداد کاراکتر (یا بایت) اول که باید مقایسه شوند. مقدار منفی معنی ندارد.
مثال پایهای
<?php
$a = "Apple";
$b = "apricot";
// مقایسهٔ سه کاراکتر اول (A-p-p vs a-p-r)
$result = strncasecmp($a, $b, 3);
if ($result === 0) {
echo "first 3 chars equal (case-insensitive)";
} elseif ($result < 0) {
echo "$a is less than $b";
} else {
echo "$a is greater than $b";
}
?>توضیح: در این مثال ابتدا سه کاراکتر اول دو رشته مقایسه میشوند. چون “App” و “apr” در کاراکتر سوم تفاوت دارند، مقدار بازگشتی نشاندهندهٔ ترتیب مقایسه است. تابع به حروف بزرگ/کوچک توجه نمیکند.
موارد کاربرد واقعی
- چک کردن پیشوند URL یا مسیرها بدون توجه به حروف: مثلاً بررسی اینکه آیا مسیر با “HTTP” یا “http” شروع میشود یا خیر.
- مقایسهٔ پروتکلها، هدرها یا کلمات کلیدی که حروف بزرگ/کوچک ندارند یا اهمیت ندارند.
- فیلتر کردن آرایهها بر اساس پیشوند (در ترکیب با array_filter).
نمونه: فیلتر کردن آرایه بر اساس پیشوند بیحساس به کیس
<?php
$words = ['Apple', 'application', 'apricot', 'banana'];
$prefix = 'app';
$len = strlen($prefix);
$filtered = array_filter($words, function($w) use ($prefix, $len) {
return strncasecmp($w, $prefix, $len) === 0;
});
print_r($filtered);
?>توضیح: در این قطعه کد، آرایهٔ کلمات را فیلتر میکنیم تا فقط آنهایی که با “app” (بدون توجه به بزرگ/کوچک بودن) شروع میشوند باقی بمانند. مقدار strlen برای n استفاده شده است.
هشدارها و نکات مربوط به رشتههای چندبایتی (UTF-8)
نکتهٔ مهم: توابع strcasecmp و strncasecmp بر پایهٔ عملیات بایتی عمل میکنند و برای رشتههای چندبایتی مانند UTF-8 ایمن نیستند. بهعبارت دیگر، وقتی رشتهها شامل نویسههای غیر-ASCII باشند (مثل حروف فارسی یا کاراکترهای ترکی)، مقایسهٔ بایتی میتواند منجر به نتایج نادرست یا تقسیمبندی در داخل یک کاراکتر مولتیبایت شود.
راهکارهای پیشنهادی برای پشتیبانی از UTF-8:
- استفاده از توابع mb_* برای نرمالسازی و برش (mb_substr و mb_strtolower) و سپس strcmp یا مشابه آن.
- استفاده از Normalizer در افزونهٔ intl برای همگنسازی ترکیب/تفکیک (composed/decomposed) در یونیکد.
مثال صحیح برای UTF-8 (نسخهٔ چندبایتی)
<?php
// مقایسهٔ n کاراکتر اول بهصورت case-insensitive در UTF-8
function mb_strncasecmp($a, $b, $n, $enc='UTF-8') {
$pa = mb_substr($a, 0, $n, $enc);
$pb = mb_substr($b, 0, $n, $enc);
// نرمالسازی و تبدیل به حالت بدون توجه به حروف
$pa = mb_strtolower($pa, $enc);
$pb = mb_strtolower($pb, $enc);
return strcmp($pa, $pb);
}
// استفاده
echo mb_strncasecmp('آب', 'آبان', 2); // مقایسهٔ دو کاراکتر اول
?>توضیح: این تابع کمکی ابتدا با mb_substr دو پیشوند به طول n را استخراج میکند، سپس هر دو را به حروف کوچک تبدیل میکند (با توجه به encoding) و در نهایت strcmp را اجرا میکند. این روش برای رشتههای UTF-8 امنتر و دقیقتر است.
بهینهسازی و نکات عملکردی
- strncasecmp معمولاً از تبدیل کامل رشتهها به حروف کوچک جلوگیری میکند و برای مقایسهٔ پیشوندها از نظر عملکرد بهتر از ترکیب strtolower + substr است؛ مگر اینکه رشتهها چندبایتی باشند.
- برای مقایسههای زیاد با دادهٔ ASCII، strncasecmp سریع و مناسب است. برای UTF-8 باید هزینهٔ mb_* را در نظر گرفت.
- اگر نیاز به حساسیتهای محلی (locale) دارید، مطمئن شوید LC_CTYPE یا سایر تنظیمات locale تنظیم شدهاند؛ اما توجه داشته باشید که باز هم برای یونیکد پیچیده ممکن است intl بهتر باشد.
مثال استفاده در مرتبسازی سفارشی (usort)
<?php
$words = ['banana', 'Apple', 'apricot', 'apple'];
usort($words, function($a, $b) {
return strncasecmp($a, $b, max(strlen($a), strlen($b)));
});
print_r($words);
?>توضیح: در این مثال از usort و strncasecmp برای مرتبسازی بدون توجه به حروف بزرگ/کوچک استفاده شده. max(strlen(…)) برای اینکه تمام طول رشتهها مقایسه شود بهعنوان n قرار داده شده؛ ولی میتوان به جای این کار از strcasecmp استفاده کرد چون مقایسهٔ کامل رشته نیاز به n ندارد.
نکات نهایی و بهترین شیوهها
- برای دادههای ASCII یا زمانی که مطمئنید رشتهها تکبایتی هستند، از strncasecmp استفاده کنید؛ سریع و ساده است.
- برای UTF-8 یا زبانهایی با کاراکترهای چندبایتی، از روشهای mb_* یا کتابخانههای مرتبط با یونیکد استفاده کنید تا خطاهای مقایسهای و برش داخل یک کاراکتر رخ ندهد.
- اگر فقط میخواهید بدانید آیا یک رشته با دیگری شروع میشود (بدون توجه به حروف)، میتوانید strncasecmp را با strlen(prefix) ترکیب کنید یا معادل mb را برای UTF-8 بسازید.
- همیشه در هنگام پردازش رشتهها encoding را مشخص کنید و در صورت نیاز آن را در ابتدای برنامه تنظیم کنید (mb_internal_encoding).
نتیجهگیری: strncasecmp تابعی ساده و موثر برای مقایسهٔ پیشوندها و بخشهایی از رشتهها بدون توجه به حروف بزرگ/کوچک است، ولی مانند بسیاری از توابع رشتهای PHP، هنگام کار با یونیکد و UTF-8 باید با احتیاط و بهکمک توابع multibyte عمل کنید.
آیا این مطلب برای شما مفید بود ؟



