Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

تبديل عام

جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 51 من 61.

من العمليات الشائعة في البرمجة تبديل قيمتين. عادةً، ستكتب دالة تبديل منفصلة لكل نوع: واحدة لـ int، وأخرى لـ double، وهكذا. لكن باستخدام void* وmemcpy، يمكننا كتابة دالة واحدة تبدّل أي متغيرين.

الفكرة الأساسية هي أن التبديل ليس سوى تحريك وحدات البايت. إذا كنت تعرف حجم البيانات، فيمكنك نسخ وحدات البايت دون معرفة النوع الفعلي. يبدو توقيع الدالة كما يلي:

void generic_swap(void* a, void* b, size_t size);

يُخبر المَعَلَمة size الدالة بعدد وحدات البايت التي يجب نقلها. في الداخل، نستخدم مخزنًا مؤقتًا وmemcpy من <string.h> لتبديل وحدات البايت:

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // مخزن مؤقت
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

الآن تعمل هذه الدالة الوحيدة مع أي نوع:

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x أصبح الآن 10، y أصبح الآن 5
double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p أصبح الآن 2.71، q أصبح الآن 3.14

هذا النمط، الذي يستخدم void* مع size_t، هو الطريقة التي تنفّذ بها المكتبة القياسية للغة C دوال عامة مثل qsort وbsearch.

challenge icon

التحدي

سهل

لنَبْنِ أداة generic_swap عامة يمكنها تبديل قيم أي متغيرين، بغضّ النظر عن نوعهما، باستخدام قوة مؤشرات void* وmemcpy.

ستنظّم شفرتك عبر ثلاثة ملفات:

  • swap.h: Declare دالة generic_swap التي تستقبل مؤشري void* ومعامل size_t يحدد حجم البيانات المراد تبديلها. لا تنسَ حواجز التضمين!
  • swap.c: Implement دالة generic_swap. استخدم مخزنًا مؤقتًا وmemcpy لنقل bytes بين موقعي الذاكرة. Remember نمط swap ذي الخطوات الثلاث: انسخ القيمة الأولى إلى temp، وانسخ الثانية إلى الأولى، ثم انسخ temp إلى الثانية.
  • main.c: اعرض عمل swap العام مع أنواع بيانات مختلفة. اقرأ مؤشر type (i للأعداد الصحيحة، وd للقيم double) متبوعًا بقيمتين. أنشئ متغيرين من النوع المناسب، وبدّلهما باستخدام دالة generic_swap، ثم اطبع القيمتين بعد التبديل.

سيستقبل برنامجك ثلاثة مدخلات:

  1. مؤشر type: i للأعداد الصحيحة أو d للقيم double
  2. القيمة الأولى
  3. القيمة الثانية

بعد التبديل، اطبع القيمتين في سطرين منفصلين. بالنسبة إلى double، استخدم منزلتين عشريتين.

مثال على المخرجات عند كون المدخلات هي i و5 و10:

10
5

مثال على المخرجات عند كون المدخلات هي d و3.14 و2.71:

2.71
3.14

مثال على المخرجات عند كون المدخلات هي i و-7 و42:

42
-7

مثال على المخرجات عند كون المدخلات هي d و99.99 و0.01:

0.01
99.99

يكمن جمال هذا الأسلوب في أن دالة generic_swap لا تعرف شيئًا عن الأنواع التي تجري عليها swap. فهي تنقل bytes فقط. تعمل الدالة نفسها مع الأعداد الصحيحة وdouble وstructs أو أي نوع بيانات آخر. ستحتاج إلى include <string.h> من أجل memcpy وإلى <stddef.h> أو <stdlib.h> من أجل size_t.

جرّب بنفسك

#include <stdio.h>
#include "swap.h"

int main() {
    char type;
    scanf("%c", &type);
    
    if (type == 'i') {
        int a, b;
        scanf("%d", &a);
        scanf("%d", &b);
        
        // TODO: استدعِ generic_swap لتبديل a و b
        // تلميح: استخدم &a و &b و sizeof(int)
        
        printf("%d\n", a);
        printf("%d\n", b);
    } else if (type == 'd') {
        double a, b;
        scanf("%lf", &a);
        scanf("%lf", &b);
        
        // TODO: استدعِ generic_swap لتبديل a و b
        // تلميح: استخدم &a و &b و sizeof(double)
        
        printf("%.2f\n", a);
        printf("%.2f\n", b);
    }
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C عبر الإنترنت