ما هو تعريف الوظيفة غير الصحيح للغة C. وظائف في لغة البرمجة C. تمرير المعلمات إلى الوظيفة الرئيسية

25.11.2023

الوظيفة هي مجموعة من العوامل التي لها اسم. في جميع الدروس السابقة كان كود برامجنا يقع في وظيفة واحدة - رئيسية. تتيح لك الوظائف تقسيم البرنامج إلى أجزاء صغيرة، يؤدي كل منها مهمة صغيرة. انظر إلى رمز المعركة البحرية الكامل (القسم - القوائم). يحتوي على أكثر من 500 سطر من التعليمات البرمجية. بدون وظائف سيكون من الصعب كتابة هذا البرنامج. ويستخدم 11 وظيفة، أطولها 50 سطرًا من التعليمات البرمجية.

تتطلب الوظيفة مكونين: التعريف والمكالمات.

تعريف الوظيفة

يجب أن يكون تعريف الوظيفة في النطاق العالمي، قبل بدء الوظيفة الرئيسية. دعونا نلقي نظرة على مثال لتعريف بسيط:

الكود بلغة c++

يتكون تعريف الدالة من رأس ونص. يتضمن رأس الوظيفة ما يلي:
نوع الإرجاع

يجب أن تقوم جميع الوظائف تقريبًا بإرجاع قيمة. تتم الإشارة إلى نوع هذه القيمة في الرأس قبل اسم الوظيفة. فيما يلي بعض الأمثلة على رؤوس الوظائف:

إنت simple_function ()
تعويم وظيفة بسيطة ()
شار simple_function()

في الحالة الأولى، يجب أن تقوم الدالة بإرجاع عدد صحيح (int)، في الحالة الثانية - رقم حقيقي (تعويم)، وفي الحالة الثالثة - حرف (char).

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

يتم تحديد معرف الوظيفة (الاسم) بنفس طريقة تحديد أي معرف آخر. في في هذا المثاللقد أنشأنا وظيفة بالمعرف simple_function (بسيط).
قائمة الوسائط أو المعلمات

تتم كتابة قائمة وسائط الوظيفة بين قوسين بعد اسم الوظيفة. في هذا المثال، قائمة الوسائط فارغة.

تتم كتابة قائمة الوسائط مفصولة بفواصل. يتكون كل عنصر في القائمة من نوع ومعرف. دعونا نلقي نظرة على مثال لرأس الدالة مع قائمة من الوسيطتين:

كثافة العمليات بسيطة (كثافة العمليات أ، تعويم ب)

لقد كتبنا حجتين بين قوسين: أ و ب. الوسيطة a من النوع int والوسيطة b من النوع float.

يتم استخدام الوسائط عندما يلزم تمرير بعض البيانات من بيئة الاتصال إلى الوظيفة.
هيئة الوظيفة

يقع نص الدالة مباشرة أسفل الرأس ومحاط بأقواس متعرجة. يمكن أن يحتوي نص الدالة على أي عدد من العوامل. لكن بيان الإرجاع يجب أن يكون حاضرا. تقوم عبارة الإرجاع بإرجاع القيمة:

الكود بلغة c++ int simple_function () (إرجاع 0؛)

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

الكود بلغة c++ int sum (int a, int b) ( int c; c = a + b; return c; )

يتم تمرير وسيطتين إلى الدالة: a وb من النوع int. في نص الدالة يتم استخدامها كمتغيرات عادية (وهي متغيرات عادية). دعونا نتفق: خارج الدالة، سنستدعي المتغيرات التي تم تمريرها إليها بالوسيطات، وستسمى نفس المتغيرات الموجودة في نص الدالة بالمعلمات.

يحدد جسم الوظيفة المتغير c. وبعد ذلك، نضع في هذا المتغير قيمة مجموع المعلمتين.

يقوم السطر الأخير بإرجاع قيمة المتغير c إلى البيئة الخارجية.

بعد الكلمة الرئيسية return تحتاج إلى تحديد القيمة التي سيتم إرجاعها. يمكنك إرجاع قيم ومتغيرات وحتى تعبيرات بسيطة. على سبيل المثال:

العودة 32؛
العودة أ؛
العودة ب؛
العودة أ+ب؛

في الحالة الأخيرة، سيتم إرجاع نتيجة مجموع المتغيرات a و b إلى بيئة الاستدعاء.

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

العودة أ؛
ج = أ+ب; // لن يتم تنفيذ هذا البيان

بفضل هذا، يعد استخدام return مناسبًا لتهيئة الظروف للخروج من الوظائف:

الكود بلغة c++إذا (أ> 0) (إرجاع 0؛) وإلا إذا (أ< 0) { return 1 }

هنا، ستعيد الدالة رقمًا اعتمادًا على قيمة المتغير a: إذا كانت a أكبر من الصفر، فسيتم إرجاع 0، وإلا - 1.
استدعاء وظيفة

بمجرد إنشاء تعريف الدالة، يمكن استدعاؤه.

الكود بلغة c++ int sum (int a, int b) ( int c; c = a + b; return c; ) int main() ( int s; s = sum(2,2); // استدعاء الدالة cout<< s; return 0; }

نتيجة لتنفيذ البرنامج سيظهر على الشاشة ما يلي: 4.

يتكون استدعاء الدالة من معرف الدالة وقائمة من الوسائط بين قوسين. فيما يلي بعض الاستدعاءات للدالة sum:

كثافة العمليات س = 5؛
كثافة العمليات ص = 4؛
كثافة العمليات ض؛

مجموع(0,1); // 1
مجموع(س,2); // 7
مجموع(س,ص); // 9
ض = مجموع (س، ص)؛ // ض = 9

بيئة الدعوة

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

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

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

الكود بلغة c++ int بسيط (int a) (return 1;) int main () (int b; b = simple(0.5); return 0;)

في قائمة الوسائط، حددنا النوع int، وتم تمرير القيمة الحقيقية 0.5 إلى الوظيفة. لا يمكنك أن تفعل ذلك.

دعونا نلقي نظرة على مثال أكثر فائدة: لنكتب دالة لتحريك الحرف:

الكود بلغة c++كثافة العمليات س؛ // المتغير العام int move_x (int dx) ( x = x + dx; return x; ) int main () ( int ch; char act; while (1) ( act = _getch(); ch = static_cast(act); if (ch == 75) // تم الضغط على السهم الأيسر move_x(-1); else if (ch == 77) // تم الضغط على السهم الأيمن move_x(1) // end while return 0;

يرجى ملاحظة أنه لا توجد أقواس لنص if و else if. يمكن حذف الأقواس الفرعية إذا كان هناك عبارة واحدة فقط في النص الفرعي.

تعمل وظيفة move_x على نقل الحرف وحدة واحدة إلى اليسار أو اليمين اعتمادًا على المفتاح الذي ضغط عليه المستخدم.

لنقم بإنشاء دالة أخرى، وفي نفس الوقت نزيل جزءًا من الكود من main:

الكود بلغة c++كثافة العمليات س؛ // المتغير العام int move_x (int dx) ( x = x + dx; return x; ) void move (int ch) ( if (ch == 75) // تم الضغط على السهم الأيسر move_x(-1); else if ( ch == 77) // تم الضغط على السهم الأيمن move_x(1) int main () ( int ch; char act; while (1) ( act = _getch(); ch = static_cast(act); move(ch) // استدعاء وظيفة النقل) // النهاية أثناء العودة 0) // النهاية الرئيسية

يرجى ملاحظة أنه في وظيفة النقل يكون نوع الإرجاع باطلاً، ولا يوجد بيان إرجاع في نص النقل.

إعلانات الوظائف (النماذج الأولية)

في المثال الأخير، يجب أن يظهر تعريف الدالة move_x أعلى تعريف الحركة (ويجب أن يظهر تعريفي move_x و move قبل main)، حيث تستدعي الدالة move move_x.

عادة، توجد تعريفات جميع الوظائف المعرفة من قبل المستخدم بعد التعريف الرئيسي. يستخدم هذا إعلانات الوظائف (النماذج الأولية). لنقم بإجراء تغييرات على البرنامج السابق:

الكود بلغة c++كثافة العمليات س؛ // المتغير العام void move(int); // النموذج الأولي (الإعلان) لوظيفة النقل int move_x(int); // النموذج الأولي للوظيفة move_x int main () ( int ch; char act; while (1) ( act = _getch(); ch = static_cast(act); move(ch); // call move ) return 0; ) void move (int ch) ( if (ch == 75) // تم الضغط على السهم الأيسر move_x(-1); وإلا إذا (ch == 77) // تم الضغط على السهم الأيمن move_x(1); ) int move_x (int دكس) ( س = س + دكس؛ إرجاع س؛ )

النموذج الأولي للوظيفة هو نفس رأس التعريف، لكن النموذج الأولي يمكنه حذف أسماء المتغيرات من قائمة الوسائط. التصريحات التالية متكافئة:

int move_x(int ​​​​dx);
int move_x(int);

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

يمكن أن يظهر إعلان الوظيفة في أي مكان في البرنامج (خارج تعريفات وظائف البرنامج أو في أي تعريف)، طالما أنه يظهر قبل استدعاء الوظيفة الأول. إذا كنت لا تستخدم الإعلانات، فيجب أن يكون هناك تعريف قبل استدعاء الوظيفة الأول، والذي يمكن أن يكون موجودًا أيضًا في أي مكان في البرنامج.
العودة فارغة
بدلاً من نوع الإرجاع، في التعريف (وفي الإعلان) لوظيفة النقل توجد الكلمة الأساسية باطلة (باطلة - فارغة، فارغة). هذا يعني أن الدالة لا تُرجع أي قيمة. لذلك، بيان الإرجاع غير مطلوب، نظرًا لأن الدالة ليس لديها ما يمكن إرجاعه إلى بيئة الاستدعاء.

العلامات: الوظائف في لغة C، النموذج الأولي، الوصف، التعريف، الاتصال. المعلمات الرسمية والمعايير الفعلية. وسيطات الدالة، التمرير بالقيمة، التمرير بالمؤشر. قيمة الإرجاع.

مقدمة

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

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

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

نحن بالفعل على دراية بالعديد من الوظائف ونعرف كيفية استدعائها - هذه هي وظائف المكتبات stdio وstdlib وstring وconio وما إلى ذلك. علاوة على ذلك، main هي أيضًا وظيفة. وهو يختلف عن الآخرين فقط في أنه نقطة الدخول عند تشغيل التطبيق.
يتم تعريف الوظيفة في لغة C في سياق عالمي. بناء جملة الدالة: (، ...) ( )

أبسط مثال هو الدالة التي تأخذ رقمًا عائمًا وترجع مربع هذا الرقم

#يشمل #يشمل float sqr(float x) ( float tmp = x*x; return tmp; ) void main() ( printf("%.3f", sqr(9.3f)); getch(); )

داخل الدالة sqr، أنشأنا متغيرًا محليًا تم تعيين قيمة الوسيطة له. تم تمرير الرقم 9.3 كوسيطة للدالة. تقوم إرجاع كلمة الخدمة بإرجاع قيمة المتغير tmp. يمكنك إعادة كتابة الدالة على النحو التالي:

تعويم sqr(تعويم x) (إرجاع x*x;)

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

طباعة باطلة (تعويم x) ( printf("%d"، x*x); return; )

في هذه الحالة، العودة تعني الخروج من الوظيفة. إذا لم تُرجع الدالة أي شيء، فلن تحتاج إلى كتابة الإرجاع. ثم تكتمل الوظيفة اكتمالها وسيعود التحكم إلى وظيفة الاستدعاء.

طباعة فارغة (float x) ( printf("%d", x*x); )

إذا كانت الدالة لا تأخذ أية وسائط، فسيتم ترك الأقواس فارغة. يمكنك أيضًا كتابة كلمة فارغة:

باطل printHelloWorld() ( printf("Hello World"); )

مقابل

طباعة باطلةHelloWorld(void) ( printf("Hello World"); )

المعلمات الرسمية والفعلية

عند الإعلان عن دالة، يتم تحديد المعلمات الرسمية، والتي يتم استخدامها بعد ذلك داخل الوظيفة نفسها. عندما نستدعي دالة، نستخدم المعلمات الفعلية. يمكن أن تكون المعلمات الفعلية متغيرات من أي نوع أو ثوابت مناسبة.

على سبيل المثال، لنفترض أن هناك دالة تُرجع مربع رقم ودالة تجمع رقمين.

#يشمل #يشمل // المعلمات الرسمية لها أسماء a و b // باستخدامها يمكننا الوصول إلى الوسائط التي تم تمريرها داخل الوظيفة int sum(int a, int b) ( return a+b; ) float Square(float x) ( return x*x; ) void main() ( // يمكن أن يكون للمعلمات الفعلية أي اسم، بما في ذلك عدم وجود اسم int one = 1; float two = 2.0; // تمرير المتغيرات، يتم تحويل المتغير الثاني إلى النوع المطلوب printf("%d\n" , sum(one, two)); // تمرير الثوابت الرقمية printf("%d\n", sum(10, 20)); // تمرير الثوابت الرقمية من النوع الخاطئ، يتم تحويلها تلقائيًا إلى الثوابت المطلوبة printf ("%d\n ", sum(10, 20.f)); // يتم تحويل متغير النوع الصحيح إلى نوع الفاصلة العائمة printf("%.3f\n", Square(one)); يمكن أيضًا استخدام استدعاء دالة كوسيطة تُرجع القيمة المطلوبة printf("%.3f\n", Square(sum(2 + 4, 3)));

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

#يشمل #يشمل void main() ( char c; do ( // احفظ القيمة المرجعة في متغير c = getch(); printf("%c", c); ) while(c != "q"); // الإرجاع لم يتم حفظ القيمة getch();

تمرير الحجج

عند تمرير الوسائط، يتم نسخها. هذا يعني أن أي تغييرات تجريها الدالة على المتغيرات تحدث داخل الدالة فقط. على سبيل المثال

#يشمل #يشمل تغيير باطل(int a) ( a = 100; printf("%d\n", a); ) void main() ( int d = 200; printf("%d\n", d); تغيير(d) printf("%d", d);

سيتم عرض البرامج
200
100
200
من الواضح لماذا. داخل الدالة نعمل مع المتغير x وهو نسخة من المتغير d. نقوم بتغيير النسخة المحلية، ولكن المتغير d نفسه لا يتغير. بعد خروج الدالة، سيتم تدمير المتغير المحلي. المتغير d لن يتغير بأي شكل من الأشكال.
فكيف يمكنك تغيير المتغير؟ للقيام بذلك، تحتاج إلى تمرير عنوان هذا المتغير. لنعد كتابة الدالة بحيث تقبل مؤشرًا من النوع int

#يشمل #يشمل تغيير باطل(int *a) ( *a = 100; printf("%d\n", *a); ) void main() ( int d = 200; printf("%d\n", d); تغيير (&d);

الآن مخرجات البرنامج
200
100
100
هنا تم أيضًا إنشاء متغير محلي، ولكن منذ تمرير العنوان، قمنا بتغيير قيمة المتغير d باستخدام عنوانه في ذاكرة الوصول العشوائي.

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

#يشمل #يشمل #يشمل void init(int *a, unsigned size) ( a = (int*) malloc(size * sizeof(int)); ) void main() ( int *a = NULL; init(a, 100); if (a = = NULL) ( printf("ERROR"); ) else ( printf("OKAY..."); free(a); ) getch();

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

لتغيير كائن، يجب عليك تمرير مؤشر إليه، في هذه الحالة مؤشر إلى مؤشر.

#يشمل #يشمل #يشمل void init(int **a, unsigned size) ( *a = (int*) malloc(size * sizeof(int)); ) void main() ( int *a = NULL; init(&a, 100); if ( a == NULL) ( printf("ERROR"); ) else ( printf("OKAY..."); free(a); ) getch();

الآن كل شيء يعمل كما ينبغي.
مثال آخر مماثل. لنكتب دالة تأخذ سلسلة كوسيطة وترجع مؤشرًا إلى منطقة الذاكرة التي تم نسخ هذه السلسلة إليها.

#يشمل #يشمل #يشمل #يشمل char* initByString(const char *str) ( char *p = (char*) malloc(strlen(str) + 1); strcpy(p, str); return p; ) void main() ( char *test = initByString( "مرحبا بالعالم!");

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

إعلان الوظيفة وتعريف الوظيفة. إنشاء مكتبتك الخاصة

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

#يشمل #يشمل // النماذج الأولية للوظيفة. لا يلزم كتابة أسماء الوسيطات intod(int); int حتى(int); باطلة الرئيسية () ( printf ("إذا %d غريب؟ %d\n"، 11، غريب (11))؛ printf ("إذا %d غريب؟ %d \ n"، 10، غريب (10))؛ getch (); - -a ) ) else ( return 0; ) )

هذا تكرار مختلط - ترجع الدالة الفردية 1 إذا كان الرقم فرديًا و0 إذا كان زوجيًا.

عادةً ما يتم وضع إعلان الدالة بشكل منفصل، في ملف .h، وتعريفات الدالة في ملف .c. وبالتالي فإن ملف الرأس يمثل واجهة المكتبة ويوضح كيفية العمل معها دون الخوض في محتوى الكود.

لنقم بإنشاء مكتبة بسيطة. للقيام بذلك، ستحتاج إلى إنشاء ملفين - أحدهما بالامتداد .h ووضع النماذج الأولية للوظيفة هناك، والآخر بالامتداد .c ووضع تعريفات هذه الوظائف هناك. إذا كنت تعمل باستخدام IDE، فيجب إنشاء الملف ‎.h في مجلد Header Files، وملفات التعليمات البرمجية في مجلد Source Code Files. دع الملفات تسمى File1.h وFile1.c
دعونا نعيد كتابة الكود السابق. هذا هو الشكل الذي سيبدو عليه ملف الرأس File1.h

#ifndef _FILE1_H_ #define _FILE1_H_ intodd(int); int حتى(int); #endif

محتويات ملف التعليمات البرمجية المصدر File1.c

#include "File1.h" int Even(int a) ( if (a) (odd(--a); ) else ( return 1; ) ) int الغريب(int a) ( if (a) ( حتى(-- أ) ) آخر (إرجاع 0؛ ) )

وظيفتنا الرئيسية

#يشمل #يشمل #include "File1.h" void main() ( printf("if %dodod? %d\n", 11,odd(11)); printf("if %dodod? %d\n", 10, غريب (10))؛

دعونا نلقي نظرة على ميزات كل ملف. يتضمن ملفنا، الذي يحتوي على الوظيفة الرئيسية، المكتبات التي يحتاجها، بالإضافة إلى ملف الرأس File1.h. يعرف المترجم الآن النماذج الأولية للوظيفة، أي أنه يعرف نوع الإرجاع وعدد الوسائط ونوعها وأسماء الوظائف.

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

#pragma مرة واحدة intod(int); int حتى(int);

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

تمرير مصفوفة كوسيطة

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

#يشمل #يشمل void printArray(int *arr, unsigned size) ( unsigned i; for (i = 0; i< size; i++) { printf("%d ", arr[i]); } } void main() { int x = {1, 2, 3, 4, 5}; printArray(x, 10); getch(); }

في هذا المثال، قد تبدو الدالة بهذا الشكل

Void printArray(int arr, unsigned size) ( unsigned i; for (i = 0; i< size; i++) { printf("%d ", arr[i]); } }

دعني أذكرك أيضًا أن قاعدة استبدال المصفوفة بمؤشر ليست متكررة. وهذا يعني أنه من الضروري تحديد أبعاد المصفوفة ثنائية الأبعاد عند الإرسال

#يشمل #يشمل void printArray(int arr, unsigned size) ( unsigned i, j; for (i = 0; i< size; i++) { for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void main() { int x = { { 1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10}}; printArray(x, 2); getch(); }

أو يمكنك الكتابة

#يشمل #يشمل void printArray(int (*arr), unsigned size) ( unsigned i, j; for (i = 0; i< size; i++) { for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void main() { int x = { { 1, 2, 3, 4, 5}, { 6, 7, 8, 9, 10}}; printArray(x, 2); getch(); }

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

#يشمل #يشمل #يشمل #يشمل #define SIZE 10 unsigned* getLengths(const char **words, unsigned size) ( unsigned * lengths = NULL; unsigned i; lengths = (unsigned*) malloc(size * sizeof(unsigned)); for (i = 0; i< size; i++) { lengths[i] = strlen(words[i]); } return lengths; } void main() { char **words = NULL; char buffer; unsigned i; unsigned *len = NULL; words = (char**) malloc(SIZE * sizeof(char*)); for (i = 0; i < SIZE; i++) { printf("%d. ", i); scanf("%127s", buffer); words[i] = (char*) malloc(128); strcpy(words[i], buffer); } len = getLengths(words, SIZE); for (i = 0; i < SIZE; i++) { printf("%d ", len[i]); free(words[i]); } free(words); free(len); getch(); }

بدلاً من إرجاع المؤشر إلى مصفوفة، يمكنك تمرير مصفوفة تحتاج إلى ملؤها

#يشمل #يشمل #يشمل #يشمل #define SIZE 10 void getLengths(const char **words, unsigned size, unsigned *out) ( unsigned i; for (i = 0; i< size; i++) { out[i] = strlen(words[i]); } } void main() { char **words = NULL; char buffer; unsigned i; unsigned *len = NULL; words = (char**) malloc(SIZE * sizeof(char*)); for (i = 0; i < SIZE; i++) { printf("%d. ", i); scanf("%127s", buffer); words[i] = (char*) malloc(128); strcpy(words[i], buffer); } len = (unsigned*) malloc(SIZE * sizeof(unsigned)); getLengths(words, SIZE, len); for (i = 0; i < SIZE; i++) { printf("%d ", len[i]); free(words[i]); } free(words); free(len); getch(); }

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

آخر تحديث: 22/09/2017

تعريف الوظيفة

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

التعريف الرسمي للوظيفة هو كما يلي:

اكتب function_name(parameters) (تعليمات)

يمثل السطر الأول رأس الوظيفة. أولا، يتم تحديد نوع الإرجاع للوظيفة. إذا لم تُرجع الدالة أي قيمة، فسيتم استخدام النوع void.

بعد ذلك يأتي اسم الوظيفة، الذي يمثل معرفًا عشوائيًا. تنطبق نفس القواعد على تسمية الوظائف كما تنطبق على تسمية المتغيرات.

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

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

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

على سبيل المثال تعريف الوظيفة الرئيسية والتي يجب أن تكون موجودة في أي برنامج C++ والتي يبدأ منها تنفيذها:

إنت الرئيسي () (إرجاع 0؛)

نوع الإرجاع للدالة هو int، لذلك يجب أن تستخدم الدالة عبارة إرجاع وترجع بعض القيمة التي تطابق النوع int. يتم وضع قيمة الإرجاع بعد بيان الإرجاع.

لكن إذا كانت الدالة من النوع void، فلا تحتاج إلى إرجاع أي شيء. على سبيل المثال، يمكننا تحديد الوظيفة التالية:

باطلة مرحبا () ( std::cout<< "hello\n"; }

تنفيذ وظيفة

لتنفيذ دالة، يجب أن يتم استدعاؤها. يتم استدعاء الدالة على الشكل:

function_name(arguments);

بعد اسم الوظيفة توجد أقواس تسرد الوسائط - قيم معلمات الوظيفة.

على سبيل المثال، دعونا نحدد وننفذ أبسط وظيفة:

#يشمل باطلة مرحبا () ( std::cout<< "hello\n"; } int main() { hello(); hello(); return 0; }

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

إعلان الوظيفة

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

#يشمل int main() ( hello(); hello(); return 0; ) باطلة hello() ( std::cout<< "hello\n"; }

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

اكتب function_name(parameters);

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

مرحبا باطلة ()؛

نستخدم إعلان الدالة:

#يشمل مرحبا باطلة ()؛ int main() ( hello(); hello(); return 0; ) باطلة hello() ( std::cout<< "hello\n"; }

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

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

بالإضافة إلى حقيقة أن C++ توفر الإعلان عن وظائفها، يمكنك أيضًا استخدام الوظائف المحددة في ملفات الرأس القياسية للغة برمجة C++. لاستخدام الوظيفة المحددة في ملف الرأس، يجب عليك تضمينها. على سبيل المثال، لاستخدام دالة ترفع رقمًا معينًا إلى قوة، تحتاج إلى تضمين ملف رأس وقم بتشغيل الدالة pow() في نص البرنامج. لنقم بتطوير برنامج نقوم من خلاله بتشغيل الدالة pow().

// inc_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #include "stdafx.h" // الإجراء 1 - تضمين ملف الرأس

// الكود Code::Blocks

// كود Dev-C++

// inc_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. // الإجراء 1 - تضمين ملف الرأس الذي يحتوي على نماذج أولية للوظائف الرياضية الأساسية #تتضمن int main(int argc, char* argv) ( float power = pow(3.14,2); // الإجراء 2 - تشغيل وظيفة رفع الرقم إلى قوة إرجاع 0; )

يتم تضمين ملفات الرأس كما هو موضح في السطر 5، أي يتم الإعلان عن توجيه المعالج المسبق #include، وبعد ذلك داخل الأحرف<>تتم كتابة اسم ملف الرأس. عندما يتم تضمين ملف الرأس، يمكنك استخدام الوظيفة، وهو ما يتم القيام به السطر 9.تقوم الدالة pow() برفع رقم 3.14 تربيع ويعين النتيجة الناتجة لمتغير الطاقة، حيث
الأسرى - اسم الوظيفة؛
الأرقام 3.14 و2 هي وسيطات دالة؛

يتبع اسم الوظيفة دائمًا أقواس، يتم من خلالها تمرير الوسائط إلى الوظيفة، وإذا كان هناك عدة وسائط، يتم فصلها عن بعضها البعض بفواصل. هناك حاجة إلى الحجج للوظائف لتمرير المعلومات. على سبيل المثال، لتربيع الرقم 3.14 باستخدام الدالة pow()، عليك أن تخبر هذه الدالة بطريقة أو بأخرى ما هو الرقم وإلى أي قوة ترفعه. هذا هو بالضبط سبب اختراع الوسائط الوظيفية، ولكن هناك وظائف لا يتم تمرير الوسائط فيها؛ يتم استدعاء هذه الوظائف بأقواس فارغة. لذلك، من أجل استخدام وظيفة من ملف الرأس القياسي C++، تحتاج إلى تنفيذ خطوتين:

  1. قم بتضمين ملف الرأس المطلوب؛
  2. قم بتشغيل الوظيفة المطلوبة.

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

  1. الوظائف التي لا ترجع القيم
  2. الوظائف التي ترجع قيمة

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

// هيكل إعلان الوظائف التي لا تُرجع قيمًا باطلة /*اسم الوظيفة*/(/*معلمات الوظيفة*/) // رأس الوظيفة ( // نص الوظيفة)

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

<= numb; i++) // цикл вычисления значения n! rezult *= i; // накапливаем произведение в переменной rezult cout << numb << "! = " << rezult << endl; // печать значения n! } int main(int argc, char* argv) { int digit; // переменная для хранения значения n! cout << "Enter number: "; cin >> رقم؛

// الكود Code::Blocks

// كود Dev-C++

faktorial(digit);// ابدأ وظيفة البحث عن العامل system("pause");<= numb; i++) // цикл вычисления значения n! rezult *= i; // накапливаем произведение в переменной rezult cout << numb << "! = " << rezult << endl; // печать значения n! } int main(int argc, char* argv) { int digit; // переменная для хранения значения n! cout << "Enter number: "; cin >العودة 0؛ )

باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ // إعلان دالة لإيجاد n! void faktorial(int numb) // رأس الدالة ( int rezult = 1; // تهيئة المتغير الناتج بالقيمة 1 for (int i = 1; i > رقم؛ faktorial(digit);// تشغيل وظيفة العثور على المضروب return 0; ) بعد تضمين جميع ملفات الرأس الضرورية، يمكنك إعلان دالة للعثور على المضروب. بالإعلان عن دالة، نعني اختيار اسم الدالة، وتحديد معلمات الدالة، وكتابة الخوارزمية التي تمثل نص الدالة. . بعد الانتهاء من هذه الخطوات يمكن استخدام الوظيفة في البرنامج. بما أن الدالة لا يجب أن تُرجع قيمة، فيجب أن يكون نوع الإرجاع فارغًا. اسم الدالة هو faktorial، داخل الأقواس يتم الإعلان عن المتغير numb من النوع int. هذا المتغير هو معلمة للدالة faktorial(). وهكذا، فإن جميع الإعلانات فيالسطر 8 معًا يشكلون رأس الوظيفة. تشكل الأسطر 9 - 14 نص الدالة factorial(). داخل النص، السطر 10 يعلن عن المتغير rezult، الذي سيخزن نتيجة العثور على n! وبعد ذلك، فيالخطوط 11-12 تم الإعلان عن مشغل حلقة for للعثور على المضروب. فيالسطر 13

يتم الإعلان عن عامل التشغيل cout، والذي سيتم من خلاله طباعة قيمة المضروب على الشاشة. الآن بعد أن تم الإعلان عن الوظيفة، يمكنك استخدامها. في

فبعد تشغيل البرنامج تم إدخال الرقم 5، وقام البرنامج بحساب أن القيمة 120 هي 5!.

تقوم وظائف إرجاع القيمة بإرجاع نتيجة محددة عند الانتهاء من عملها. يمكن لهذه الوظائف إرجاع قيمة من أي نوع بيانات. سيكون هيكل الوظائف التي تُرجع قيمة مختلفًا قليلاً عن هيكل الوظائف التي تمت مناقشتها سابقًا.

// هيكل إعلان الوظائف التي تُرجع القيم /*نوع بيانات الإرجاع*/ /*اسم الوظيفة*/(/*معلمات الوظيفة*/) // رأس الوظيفة ( // إرجاع نص الوظيفة /*قيمة الإرجاع*/; )

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

// struct_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #تتضمن "stdafx.h" #تتضمن <= numb; i++) // цикл вычисления значения n! rezult *= i; // накапливаем произведение в переменной rezult return rezult; // передаём значение факториала в главную функцию } int main(int argc, char* argv) { int digit; // переменная для хранения значения n! cout << "Enter number: "; cin >> رقم؛<< digit << "! = " << faktorial(digit) << endl;// запуск функции нахождения факториала system("pause"); return 0; }

// الكود Code::Blocks

// كود Dev-C++

cout // struct_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #يشمل<= numb; i++) // цикл вычисления значения n! rezult *= i; // накапливаем произведение в переменной rezult return rezult; // передаём значение факториала в главную функцию } int main(int argc, char* argv) { int digit; // переменная для хранения значения n! cout << "Enter number: "; cin >> رقم؛<< digit << "! = " << faktorial(digit) << endl;// запуск функции нахождения факториала return 0; }

باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ // إعلان دالة لإيجاد n! int faktorial(int numb) // رأس الدالة ( int rezult = 1; // تهيئة المتغير الناتج بالقيمة 1 for (int i = 1; i معًا يشكلون رأس الوظيفة. تشكل الأسطر 9 - 14 نص الدالة factorial(). داخل النص، السطر 10 يعلن عن المتغير rezult، الذي سيخزن نتيجة العثور على n! وبعد ذلك، فيتحتوي الدالة faktorial() الآن على نوع بيانات إرجاع int لأن n! هو عدد صحيح تم الإعلان عن مشغل حلقة for للعثور على المضروب. فيتم الإعلان عن عبارة الإرجاع التي تُرجع القيمة الموجودة في المتغير الناتج. في نقوم بتشغيل الدالة faktorial()، والتي يتم إرسال القيمة المرجعة منها إلى دفق الإخراج باستخدام عامل التشغيل cout. يمكن كتابتها على النحو التالي: int fakt = faktorial(digit); - نوع المتغيركثافة العمليات

نقوم بتعيين القيمة المرجعة للدالة faktorial()، وبعد ذلك سيقوم المتغير fakt بتخزين القيمة n! . ولم تتغير نتيجة البرنامج (انظر الشكل 2).

أدخل الرقم: 5 5! = 120 للمتابعة، اضغط على أي مفتاح. . .

لقد نظرنا إلى نوعين من الوظائف، وتم تنفيذ إعلان الوظائف في منطقة البرنامج، بعد تضمين ملفات الرأس، ولكن قبل بدء الوظيفة main(). هناك عدة طرق لإعلان الوظائف (انظر الشكل 3).

الشكل 3 - الوظائف في لغة C++

على الشكل 3يعرض 4 طرق للإعلان عن الوظائف في لغة البرمجة C++. دعونا نلقي نظرة على بنية إعلانات الوظائف في ملف واحد، مع الوظيفة الرئيسية. يمكن الإعلان عن الدالات في منطقتين، قبل الدالة main()، وبعد الدالة main(). لقد قمنا حتى الآن بإعلان الوظائف في ملف واحد، قبل الوظيفة main() - وهذه هي أبسط طريقة.

// struct_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #include "stdafx.h" /*المنطقة 1 - إعلان الوظائف قبل بدء main()، مكان للإعلان عن الوظائف في هذه المنطقة لا يحتاج إلى نماذج أولية */ int main(int argc, char* argv) (العودة 0؛)

إذا تم الإعلان عن الوظائف في المنطقة 1، قبل الوظيفة الرئيسية، فلن تكون هناك حاجة إلى نماذج أولية لهذه الوظائف. إنه أسلوب برمجة جيد للإعلان عن الوظائف بعد main() . دعونا نلقي نظرة على هيكل إعلان الوظيفة هذا.

// struct_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #include "stdafx.h" // مكان للإعلان عن النماذج الأولية للوظائف int main(int argc, char* argv) ( return 0; ) /*المنطقة 2 - إعلان الوظائف بعد المكان الرئيسي () لإعلان الوظائف */

// الكود Code::Blocks

// كود Dev-C++

// struct_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. // مكان للإعلان عن النماذج الأولية للوظائف int main(int argc, char* argv) ( return 0; ) /*المنطقة 2 - إعلان الوظائف بعد المكان الرئيسي () لإعلان الوظائف */

انتقلت منطقة إعلان الدالة إلى نهاية البرنامج، بعد main() . أما طريقة إعلان الوظائف نفسها فلم تتغير. ولكن نظرًا لأنه تم الإعلان عن الوظائف بعد main() ، فلن يكون من الممكن استخدامها، نظرًا لأن ترتيب الإعلانات قد تغير ولن تتمكن الوظيفة main() ببساطة من رؤية الوظائف المعلنة بعد ذلك. لذا، لكي تكون هذه الوظائف مرئية في main()، هناك مفهوم النموذج الأولي. النموذج الأولي للوظيفة هو رأس الوظيفة الذي تم الإعلان عنه قبل الوظيفة الرئيسية (). وإذا قمت بالإعلان عن نموذج أولي للوظيفة، فيمكن رؤية الوظيفة في main() .

// بناء جملة إعلان النموذج الأولي /*نوع بيانات إرجاع الوظيفة*/ /*اسم الوظيفة*/(/*معلمات الوظيفة*/);

يشبه هيكل إعلان النموذج الأولي إلى حد كبير هيكل إعلان الوظيفة. لنقم بتطوير برنامج يحدد ما إذا كان الرقم المكون من خمسة أرقام الذي تم إدخاله هو متناظر أم لا. المتناظر هو رقم أو نص يُقرأ بنفس الطريقة على اليسار واليمين: 93939؛ 49094؛ 11311.

// palindrom_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #تتضمن "stdafx.h" #تتضمن << "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >> << "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<

// الكود Code::Blocks

// كود Dev-C++

// palindrom_func.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #يشمل باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ منطقي متناظر5(int); // النموذج الأولي للوظيفة لإيجاد متناظر من الأعداد المكونة من خمسة أرقام int main(int argc, char* argv) ( cout<< "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >>in_number;<< "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<

out_number = in_number; // قم بتخزين الرقم المُدخل في المتغير out_number if (palindrom5(in_number)) // إذا كانت الدالة ترجع صحيحًا، فإن الشرط صحيح، وإلا فسترجع الدالة false - false cout فيالسطر 7 تم الإعلان عن وظيفة نموذجية للعثور على متناظرة مكونة من خمسة أرقام. يرجى ملاحظة أن النموذج الأولي يجب أن يتطابق تمامًا مع رأس الوظيفة، ولكن لا تزال هناك بعض الاختلافات. على سبيل المثال، لا يحتاج النموذج الأولي إلى إدراج أسماء المعلمات؛ يكفي الإعلان عن أنواع البيانات الخاصة بها. يجب عليك دائمًا وضع فاصلة منقوطة في نهاية إعلان النموذج الأولي. وبخلاف ذلك، فإن إعلان النموذج الأولي هو نفس إعلان رأس دالة واحدة. يجب الإعلان عن النموذج الأولي لكل وظيفة على حدة. يتم استخدام المتغير out_number لتخزين الرقم الذي تم إدخاله مؤقتًا. فيالسطر 16 حالة عبارة التحديد إذا كانت تقوم بتشغيل وظيفة palindrom5(). الوسيطة الخاصة به هي المتغير in_number. ستُرجع الدالة قيمة من النوع bool، وإذا أعادت الدالة صحيحًا، فسيكون الشرط صحيحًا، وإلا فسيكون خطأ. سيكون من الممكن أولاً تعيين القيمة التي ترجعها الدالة إلى متغير ما، ثم استبدال هذا المتغير في حالة عبارة الاختيار if، ولكن هذا من شأنه أن يزيد كود البرنامج بمقدار سطر واحد. فيالأسطر 23 - 40 تم الإعلان عن الدالة palindrom5()، بمعلمة واحدة يتم من خلالها تمرير رقم مكون من خمسة أرقام إلى الدالة. تم الإعلان عن المتغيرات Balance1، Balance2، Balance4، Balance5، وهي ضرورية لتخزين أرقام رقم مكون من خمسة أرقام: الأول والثاني والرابع والخامس (الترقيم - من اليمين إلى اليسار). في الأسطر 26، 29، 32، 35 يتم تنفيذ نفس العملية - باقي القسمة. تقوم عملية قسمة الباقي بقطع بت واحد من اليمين إلى اليسار وتخزينه في المتغيرات Balance1، Balance2، Balance4، Balance5، على التوالي. علاوة على ذلك، فإن عملية باقي القسمة تتناوب مع عملية القسمة العادية. تتم عملية التقسيم في الخطوط 27, 30 , 33 ، وتقليل الرقم المكون من خمسة أرقام الذي تم إدخاله في الخطوات بمقدار رقم واحد. في السطر 30تقوم عملية القسمة بتقليل الرقم المدخل بمقدار رقمين مرة واحدة، لأن الرقم مكون من خمسة أرقام والرقم الأوسط لا يهمنا، يمكن أن يكون أي شيء. في الأسطر 36 - 39يتم الإعلان عن عامل التحديد if ، الذي يقارن أرقام عدد مكون من خمسة أرقام، وإذا كانت متساوية، فستعود الدالة صحيحًا، وإلا فستعود كاذبة. نتيجة البرنامج (انظر الشكل 4).

أدخل رقم 5zn-e: 12321 الرقم 12321 - Palendrom للمتابعة، اضغط على أي مفتاح. . .

الشكل 4 - الوظائف في لغة C++

لقد أعلنا حتى الآن عن وظائف في نفس الملف مثل البرنامج الرئيسي، أي حيث توجد الوظيفة الرئيسية (). في لغة C++، من الممكن وضع إعلانات الوظائف في ملف منفصل، ثم ستحتاج إلى تضمين الملف مع الوظائف، كما هو الحال مع تضمين ملفات الرأس القياسية. هناك طريقتان:

  1. إنشاء ملف *.cpp يتم فيه الإعلان عن الوظائف؛
  2. إنشاء ملفات *.cpp و*.h.

الطريقة الثانية هي أسلوب برمجة جيد. وبالتالي، إذا قمت بتعريف وظائف في ملف آخر، فقم بذلك وفقًا للطريقة الثانية. دعونا نعيد صياغة برنامج إيجاد المتناظر بحيث يكون الإعلان عن الدالة palindrom5() في ملف *.cpp منفصل. الملف *.h مطلوب لإخفاء تنفيذ الوظائف، أي أن الملف *.h سيحتوي على نماذج أولية للوظائف. باستخدام MVS Solution Explorer، قم بإنشاء ملف *.h وقم بتسميته Palendrom.

// رمز الملف Palendrom.h #ifndef Palendrom #define Palendrom bool palindrom5(int); // النموذج الأولي لوظيفة البحث عن متناظر من الأعداد المكونة من خمسة أرقام #endif

توجيهات في الخطوط 2،3،5يجب دائمًا التصريح عنها في ملفات النموذج الأولي للدالة، كما يتم دائمًا التصريح عن النماذج الأولية للوظيفة في ملفات *.h. بعد التوجيهات المكتوبة في الخطوط 2،3، ولكن يتم الإعلان عن النماذج الأولية للوظيفة قبل التوجيه #endif. يوضح السطر الرابع النموذج الأولي للدالة palindrom5(). يوجد إعلان هذه الوظيفة في الملف Palendrom.cpp، والذي تم إنشاؤه أيضًا مسبقًا باستخدام MVS Solution Explorer.

// محتويات الملف Palendrom.cpp #include "stdafx.h" #include "palendrom.h" bool palindrom5(int number) // وظيفة للعثور على متناظر الأرقام المكونة من خمسة أرقام ( int Balance1, Balance2, Balance4, Balance5 // المتغيرات التي تخزن النتائج المتوسطة Balance1 = الرقم % 10; // يتم تعيين الرقم المتبقي الأول للمتغير Balance1 = الرقم / 10; // تقليل الرقم المدخل بمقدار رقم واحد Balance2 = الرقم % 10; الرقم المتبقي الثاني = الرقم / 100؛ يتم تعيين المتغير Balance5 للباقي الخامس إذا ((balance1 == Balance5) && (balance2 == Balance4)) تُرجع القيمة الصحيحة // تُرجع الدالة القيمة الحقيقية وإلا تُرجع الدالة قيمة خاطئة)

// الكود Code::Blocks

// كود Dev-C++

// محتويات الملف Palendrom.cpp #include "palendrom.h" bool palindrom5(int number) // وظيفة للعثور على متناظر الأرقام المكونة من خمسة أرقام ( int Balance1, Balance2, Balance4, Balance5; // المتغيرات التي تخزن النتائج المتوسطة Balance1 = number % 10; // تم تخصيص الرقم المتبقي الأول للمتغير Balance1 = الرقم / 10; // تقليل الرقم المُدخل بمقدار رقم واحد Balance2 = العدد % 10; // تم تعيين الرقم المتبقي الثاني للمتغير Balance2 = الرقم / 100 // تقليل الرقم المدخل بمقدار رقمين Balance4 = الرقم % 10; // يتم تعيين الرقم المتبقي الرابع للمتغير Balance4 = الرقم / 10; // تقليل الرقم المدخل بمقدار رقم واحد Balance5 = الرقم % 10; يتم تعيين الباقي الخامس إذا ((balance1 == Balance5) && (balance2 == Balance4)) تُرجع القيمة الصحيحة // تُرجع الدالة القيمة الحقيقية وإلا تُرجع الدالة قيمة خاطئة)

يحتوي ملف Palendrom.cpp على إعلان الدالة palindrom5(). نظرًا لأن ملف Palendrom.cpp هو ملف قابل للتنفيذ (*.cpp عبارة عن ملفات قابلة للتنفيذ)، فمن الضروري تضمين الحاوية "stdafx.h" فيه، كما في السطر 2. لربط الملف الذي تم الإعلان عن الدالة palindrom5() فيه والملف مع النموذج الأولي الخاص به، فلنقم بتضمين ملف الرأس (الملف مع النموذج الأولي)، ويتم ذلك في السطر 3. يرجى ملاحظة أنه عند ربط الملف الذي أنشأناه، يتم استخدام علامات الاقتباس المزدوجة، وليس أكبر من أو أقل من العلامات. كل ما تبقى هو تشغيل الدالة palindrom5() في الملف الرئيسي القابل للتنفيذ func_palendrom.cpp .

// func_palendrom.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #تتضمن "stdafx.h" #تتضمن << "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >>in_number;<< "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<

// الكود Code::Blocks

// كود Dev-C++

// func_palendrom.cpp: يحدد نقطة الدخول لتطبيق وحدة التحكم. #يشمل // تضمين ملف الرأس، مع النموذج الأولي للوظيفة palindrom5() #include "palendrom.h" باستخدام مساحة الاسم std؛ int main(int argc, char* argv) (cout<< "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >>in_number;<< "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<

out_number = in_number; // قم بتخزين الرقم المُدخل في المتغير out_number if (palindrom5(in_number)) // إذا كانت الدالة ترجع صحيحًا، فإن الشرط صحيح، وإلا فسترجع الدالة false - false cout السطر 6لقد قمنا بتضمين ملف يحتوي على نموذج أولي للدالة palindrom5()، وبعد ذلك يمكننا استخدام هذه الوظيفة. لذلك قمنا بتقسيم البرنامج إلى ثلاثة ملفات:

  • ملف المشروع: func_palendrom.cpp
  • رأس الملف Palendrom.h
  • الملف القابل للتنفيذ Palendrom.cpp

نقوم بربط ملف المشروع بملف الرأس، ونربط ملف الرأس بالملف القابل للتنفيذ، وفي هذه الحالة سيرى ملف المشروع وظيفة palindrom5() وسيكون قادرًا على تشغيلها.