ویژگی تصویر

تابع strncasecmp() در PHP

  /  PHP   /  تابع strncasecmp() در PHP
بنر تبلیغاتی الف
آموزش 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 عمل کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: