---
title: Functions
localeTitle: المهام
---
# وظائف في C

أحيانًا يكون لديك جزء من الشفرة تحتاج إلى استخدامه مرارًا وتكرارًا ، ولكن في أوقات وأماكن مختلفة في شفرتك. يمكنك نسخها ولصقها مرارًا وتكرارًا ، ولكن هذا ليس حلاً رائعًا ، حيث يصبح حجم ملفك أكبر ، وتصعب تصحيح التعليمات البرمجية ، ومن الصعب قراءة التعليمات البرمجية. بدلاً من ذلك ، استخدم وظيفة: الدوال تشبه البرامج المصغرة الموجودة داخل شفرتك. يمكنك تمريرها للمتغيرات لاستخدامها ، ويمكن أن يعيد البيانات.

## مثال

إليك مثال بسيط على وظيفة تقسم رقمين. انها ليست مفيدة جدا لأن لدينا `/` ، لكنه يظهر أجزاء مختلفة من وظيفة.

 `#include <stdio.h> 
 
 int divides(int a, int b) { 
    return a / b; 
 } 
 
 int main(void) { 
    int first = 5; 
    int second = 10; //MUST NOT BE ZERO; 
 
    int result = divides(first, second); 
 
    printf("first divided by second is %i\n", result); 
 
    return 0; 
 } 
` 

لاحظ أنه مثل `main` ، فإن `divides` لها تنسيق مشابه. ذلك لأن `main` هي أيضاً دالة- إنها خاصة فقط لأن C تبحث عنها أولاً. `divides` كما يأتي قبل `main` . هذا أمر مهم لأن `divides` النداءات `main` . استدعاء دالة يعني أنه يتم استخدام الرمز الخاص به. يجب أن يتم تجميع الكود قبل أن يتم استخدامه ، و C يجمع سطرًا سطحيًا من أعلى ، لذا لكي يتم استدعاء دالة ، يجب كتابتها قبل استدعاءها في هذا المثال. إذا جاءت `divides` بعد `main` ، فإنها ستفشل لأن المجمع لا يعرف أن `divides` موجودة حتى الآن. يمكنك أيضا استخدام النموذج الأولي وظيفة قبل الرئيسي للسماح لك بوضع `divides` بعد الرئيسي. النموذج الأولي للدالة متطابق مع الوظيفة التي لها نفس المتغيرات ونوع الإرجاع ، إلا أنه يتم حذف الأقواس واستبدالها بفاصلة منقوطة مثل:

 `int divides(int a, int b); 
` 

لاحظ أيضًا أن `divides` `main` لا تتقاسم الأقواس ولا توجد بين قوسين. من المفترض أن تكون منفصلة ، على الرغم من أن واحد يدعو الآخر.

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

## كسر إعلان الدالة

 `int divides(int a, int b) 
` 

يبدأ تعريف الدالة بنوع بيانات ، وهو في هذه الحالة `int` . مهما كان نوع البيانات الذي تريد إرجاعه ، يجب عليك وضعه هنا. يمكنك الحصول على أي نوع من أنواع البيانات ، أو لا يمكن أن يكون نوع البيانات من خلال وضع `void` هنا.

التالي هو اسم الوظيفة. كلما كنت تريد استدعاء الدالة ، هذا هو الاسم الذي ستستخدمه. حاول أن تكون شيئًا وصفيًا ، بحيث يمكنك بسهولة تحديد ما يفعله.

بعد اسم يأتي زوج من قوسين. في هذه الأقواس ، يمكنك استخدام معلمات الدالة الخاصة بنا ، والتي هي المتغيرات التي ستأخذها هذه الوظيفة وتستخدم عند تشغيل التعليمات البرمجية. في هذه الحالة ، هناك نوعان. كلاهما نوع البيانات `int` ، وسيتم تسمية `a` و `b` . من الناحية المثالية ، سيكون هناك أسماء أفضل لاستخدامها هنا ، ولكنك ستجد ذلك للأساليب البسيطة والسريعة وغالباً ما تستخدم أسماء المتغيرات المؤقتة.

الآن دعونا نلقي نظرة على ما هو داخل الأقواس:

 `return a / b; 
` 

هذا واضح جدا ، لأن هذه هي وظيفة بسيطة. `a` مقسومة على `b` ، ويتم إرجاع هذه القيمة. كنت قد رأيت `return` قبل في المهمة `main` ، ولكن الآن بدلا من إنهاء برنامجنا ، فإنه ينهي الطريقة ويعطي قيمة لما يطلق عليه.

لذا ، لنلخص ما تقوم به هذه الوظيفة ، فهو يحصل على رقمين صحيحين ، ويقسمهما ، ويعيدهما إلى ما يطلق عليه.

### معلمات دالة

تستخدم المعلمات لتمرير الحجج إلى الوظيفة. هم نوعان من المعلمات: يسمى المعلمة المكتوبة في الدالة التعريف "المعلمة الرسمية". اﻟﻤﻌﻠﻢ اﻟﻤﻜﺘﻮب ﻓﻲ اﻟﺪاﻟﺔ ﻳﺴﻤﻰ اﻟﻤﻜﺎﻟﻤﺔ "اﻟﻤﻌﻠﻢ اﻟﻔﻌﻠﻲ". وﻳُﻌﺮف أﻳﻀًﺎ ﺑﺎﺳﻢ اﻟﺤﺠﺞ. وﻳﺘﻢ ﺗﺤﻮﻳﻠﻪ إﻟﻰ ﺗﻌﺮﻳﻒ اﻟﻮﻇﻴﻔﺔ وﻳﺘﻢ إﻧﺸﺎء ﻧﺴﺨﺔ ﻓﻲ ﺷﻜﻞ ﻣﻌﻠﻤﺎت رﺳﻤﻴﺔ.

## مثال أكثر تعقيدًا

كان هذا واحد وظيفة خط واحد. ستراهم عندما تكون هناك عملية بسيطة جدًا يجب إجراؤها مرارًا وتكرارًا ، أو عملية تنتهي بكونها سطرًا واحدًا طويلًا. من خلال جعلها وظيفة ، ينتهي الرمز ليكون أكثر قابلية للقراءة ويمكن التحكم فيه.

ومع ذلك ، فإن معظم الوظائف لن تكون سطرًا واحدًا من التعليمات البرمجية. دعونا نلقي نظرة على مثال آخر أكثر تعقيدًا قليلاً يختار أكبر رقمين.

 `int choose_bigger_int(int a, int b) { 
    if(a > b) 
        return a; 
 
    if(b > a) 
        return b; 
 
    return a; 
 } 
` 

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

يبدأ هذا الرمز مع بيان إذا أن يتحقق إذا `a` أكبر من `b` . في حالة ما هو عليه، فإنه سيعود `a` . إذا تم ذلك ، تنتهي الوظيفة هنا - لا يتم تقييم بقية الشفرة. إذا لم يتم الوصول إلى بيان الإرجاع هذا ، فسيتم تقييم العبارة التالية. إذا كان صحيحًا ، سيتم إرجاع `b` وتنتهي الدالة هنا.

مع ذلك ، تم اعتبار الظروف لكون أكبر من b ، و b أكبر من a. ومع ذلك ، إذا كان يساوي b ، فإن الدالة ما زالت لن تعيد أي شيء. ولهذا السبب ، نعيد (أ) تساوي b ، لذا يمكننا العودة أيضًا).

## كلمة حول "النطاق"

النطاق هو شيء يجب أن تدركه. يشير إلى المناطق في التعليمات البرمجية الخاصة بك حيث يمكن الوصول إلى متغير. عند تمرير متغير إلى وظيفة ، تحصل الدالة على النسخة الخاصة بها لاستخدامها. وهذا يعني أن ضبط المتغير في الوظيفة لن يتم ضبطه في أي مكان آخر. وبالمثل ، إذا لم تكن قد اجتازت متغيرًا إلى وظيفة ، فلا يوجد به ولا يمكنه استخدامه.

ربما تكون قد لاحظت مشكلة مشابهة مع أشياء مثل العبارات و أي من الحلقات. إذا قمت بتعريف متغير داخل أقواس ، فلن يمكن الوصول إليه خارج تلك الأقواس. ينطبق هذا على الوظائف بنفس الطريقة ، ولكن هناك بعض الطرق للالتفاف عليها:

*   قم بعمل متغير عالمي عن طريق التصريح به خارج أي وظائف
*   هذا يجعل رمزك messier وعموما لا ينصح به. يجب تجنبه كلما أمكن ذلك
*   استخدم المؤشرات ، التي ستقرأها عن التالي
*   هذا يمكن أن تجعل التعليمات البرمجية الخاصة بك أكثر صعوبة في القراءة والتصحيح
*   انتقل إلى وظائفك كما يفترض
*   هذه هي أفضل طريقة للقيام بذلك ، إذا كان ذلك هو خيار

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

التكرار في C عندما يتم استدعاء الدالة داخل نفس الوظيفة ، فإنها تُعرف باسم التكرار في C. تُعرف الدالة التي تستدعي نفس الوظيفة ، باسم الدالة العودية.

 `int factorial (int n) 
 { 
    if ( n < 0) 
        return -1; /*Wrong value*/ 
    if (n == 0) 
        return 1; /*Terminating condition*/ 
    return (n * factorial (n -1)); 
 } 
` 

# قبل أن تذهب ...

## مراجعة

*   تعد الدوال جيدة الاستخدام لأنها تجعل نظافة الرمز وأسهل في التصحيح.
*   يجب الإعلان عن الوظائف قبل استدعائها.
*   يجب أن يكون للبيانات نوع بيانات للعودة ، إذا لم يتم إرجاع أي شيء ، فاستخدم `void` .
*   تأخذ الدالات معلمات للعمل بها ، إذا لم تأخذ شيئًا ، استخدم `void` .
*   ينتهي `return` وظيفة ويعطي قيمة. يمكن أن يكون لديك عدة وظائف في وظيفة واحدة ، ولكن بمجرد أن تصل إلى واحدة تنتهي الوظيفة هناك.
*   عندما تقوم بتمرير متغير إلى إحدى الوظائف ، يكون له نسخة خاصة به لاستخدامها - تغيير شيء ما في إحدى الوظائف لا يؤدي إلى تغييره خارج الوظيفة.
*   تظهر المتغيرات المعلنة داخل إحدى الوظائف فقط داخل هذه الوظيفة ، ما لم يتم اعتبارها متغيرة.