إمرار المصفوفات للدوال

c

إمرار المصفوفات للدوال

يمكن أن تمرر المصفوفات كمعاملات بين الدوال . وفي المثال التالي سوف نعدل البرنامج saleinit.cpp لكي يتضمن دالتين , الفرعية فيهما هي التي تتولي إظهار القيم , وتمرر المصفوفة كمعامل من الدالة الأصلية للدالة الفرعية .

salefunc.cpp


 


// salefunc.cpp


// passes array as argument


// UCS Laboratories


#include <iostream.h>


#include <iomanip.h>        // for setprecision, etc.


#include <conio.h>


 


const int DISTRICTS = 4;    // array dimensions


const int MONTHS = 3;


 


void display( float[DISTRICTS][MONTHS] );  // prototype


 


void main()


   {                        // initialize two-dimensional array


   float sales[DISTRICTS][MONTHS]


          = {  {  1432.07,   234.50,   654.01 },


               {   322.00, 13838.32, 17589.88 },


               {  9328.34,   934.00,  4492.30 },


               { 12838.29,  2332.63,    32.93 }  };


 


   display(sales);          // call function, array as argument


   getche();


}  // end main


 


// display()


// function to display 2-d array passed as argument


void display( float funsales[DISTRICTS][MONTHS] )


   {


   int d, m;


 


   cout << "\n\n";


   cout << "                        Month\n";


   cout << "                1         2         3";


 


   for(d=0; d<DISTRICTS; d++)


      {


      cout <<"\nDistrict " << d+1;


      for(m=0; m<MONTHS; m++)


     cout << setiosflags(ios::fixed) << setw(10)


          << setiosflags(ios::showpoint) << setprecision(2)


          << funsales[d][m];   // array element


      }  // end for(d)


   }  // end display




الإعلان عن الدالة ذات مصفوفة كمعامل



جاء سطر الإعلان عن الدالة كالتالي :



Void display (float[DISTRICTS][MONTHS];



وليس في هذه الصورة غرابة , ولكن الغرابة في أن الإعلان يمكن أن يأتي علي الصورة :



Void display( float[][MONTHS);



وفيها بم يذكر حجم المصفوفة الأولي , فلماذا ليس هذا البيان مهما في الإعلان ؟ نتذكر هنا مرة أخري أن المصفوفة ثنائية الأبعاد هي مصفوفة لمصفوفة , فالدالة تنظر في البدء للمصفوفة علي أنها مصفوفة للمناطق , وليس مهما لها أن تعرف عددها الأن , ولكنها تريد أن تعرف حجم كل عنصر من عناصر المصفوفة (كل منطقة) , لكي تحسب موضع أي عنصر بها (بضرب عدد البايتات لكل عنصر في الدليل ) . فعلينا إذن أن نخبر الدالة بحجم كل عنصر , ولكن ليس مهما أن نخبرها بعدد العناصر .



وبنفس المنطق يمكننا أن نعلن عن مصفوفة وحيدة البعد بالشكل التالي :



Void somefunc( int elem[] );



الاستدعاء بالمصفوفة كمعامل



يكون إستدعاء الدالة الفرعية عن طريق إمرار المصفوفة كمعامل لها بمجرد ذكر اسمها علي النحو التالي :



Display(sales);



حيث يمثل الاسم عنوان المصفوفة ( عنوان أول عنصر بها ) . وسوف نتحدث باستفاضة عن موضوع العناوين في الفصل الثاني عشر , ولكننا نعطي هنا لمحة عن الموضوع .



إن استخدام العنوان في إمرار المصفوفة معامل بشبه الإمرار بإسلوب الإشارة ( التعامل المباشر) reference argument  , من حيث كون الدالة لا تنسخ نسخة من قيم المصفوفة المحالة إليها , بل تتعامل معها عن طريق عناوين عناصرها . والعبرة في ذلك هي أن المصفوفة قد تحتوي علي عدد ضخم من العناصر , ونسخها يكلف من الوقت والذاكرة الشئ الكثير .



علي أن التعامل عن طريق العناوين يختلف عن الإمرار بإسلوب التعامل المباشر , فنحن لم نستخدم المؤثر & , وإلي أن نبحث الأمر في موضوع المؤشرات , عليك فقط أن تثق بأن الدالة تمرر عن طريق المصفوفة بالفعل , وليس نسخة لها .



تعريف الدالة ذات المصفوفة كمعامل



يكون التعريف بالدالة الفرعية كالتالي :



Void display( float funcsales([DISTRICTS][MONTHS])



فحددنا في التعريف نوع بيان المصفوفة , واسم المصفوفة , وحجم كل بعد لها . فالدالة تحتاج كلا الحجمين لكي يمكنها الوصول لكل عنصر في المصفوفة . ويمكن أن يختلف اسم المصفوفة في الدالة الفرعية عنه في الدالة المستدعية , كما فعلنا في المثال , ولكن الاسمين يشيران لنفس الشئ .



وتكون الإشارة لعناصر المصفوفة عن طريق الدليلين المعبرين عن موضعها , كالتالي :



Funsales[d][m];

التسميات: