تخطَّ إلى المحتوى

qsort

الترتيب العام عبر مؤشر دالة qsort

qsort من stdlib.h تفرز أي مصفوفة من أي نوع بيانات، بالاعتماد على دالة مقارنة تزوّدها أنت تحدّد الترتيب.

بما أن C لا تدعم القوالب العامة (generics) مثل C++، تعتمد qsort على void* لقبول مصفوفة من أي نوع، وعلى مؤشر دالة (comparator) لمعرفة كيف تقارن عنصرين دون معرفة نوعهما مسبقًا. المعاملات الأربعة: مؤشر بداية المصفوفة، عدد العناصر، حجم العنصر الواحد بالبايت (عبر sizeof)، ومؤشر دالة المقارنة.

داخل دالة المقارنة، المعاملان يصلان كـ const void* ويجب تحويلهما (cast) للنوع الحقيقي قبل قراءة القيمة. يجب أن تُرجع الدالة قيمة سالبة إذا كان العنصر الأول يجب أن يسبق الثاني، صفرًا إذا كانا متساويين بالترتيب، وموجبة إذا كان يجب أن يأتي بعده.

الصياغة

void qsort(void *base, size_t nitems, size_t size,
            int (*compar)(const void*, const void*));

📄 مثال

#include <stdlib.h>

int compareInts(const void *a, const void *b) {
    int x = *(const int *)a;
    int y = *(const int *)b;
    return x - y;
}

int nums[] = {5, 2, 8, 1};
qsort(nums, 4, sizeof(int), compareInts);
// nums الآن: {1, 2, 5, 8}

أهم النقاط

العنصرالوظيفة
baseمؤشر لأوّل عنصر بالمصفوفة (void*)
nitemsعدد عناصر المصفوفة
sizeحجم العنصر الواحد بالبايت، عادة sizeof(النوع)
comparمؤشر دالة مقارنة بتوقيع int(*)(const void*, const void*)

💡 نصائح عملية

  • لترتيب تنازلي فقط اعكس نتيجة دالة المقارنة (أرجع y - x بدل x - y)
  • استخدم نفس فكرة مؤشر الدالة لكتابة دوالك العامة الخاصة بدل تكرار الكود لكل نوع

⚠️ أخطاء شائعة

  • نسيان تحويل المعاملات من const void* للنوع الحقيقي قبل قراءتها
  • توقيع خاطئ لدالة المقارنة لا يطابق int(*)(const void*, const void*) بالضبط

خصائص ذات صلة

🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار C الكامل بالعربي.