گرانبار کردن توابع (استفاده از يک نام برای چند تابع)

++C استفاده از يک نام را برای چند تابع ، هنگامی که توابع از نظر نوع آرگومان ها ، تعداد آرگومان ها يا ترتيب قرار گرفتن نوع آرگومان ها با هم متفاوت باشند را امکان پذير کرده است اين قابليت ، گرانبار کردن توابع ناميده می شود . هنگامی که يک تابع گرانبار شده فراخوانی می شود کامپايلر با مقايسه نوع ، تعداد و ترتيب آرگومان ها تابع درست را انتخاب می کند . معمولاً از توابع گرانبار شده برای ايجاد چند تابع با نامهای يکسان که کار يکسانی را بر روی انواع داده ای متفاوتی انجام می دهند استفاده می شود . به عنوان مثال اکثر توابع رياضی زبان ++C برای انواع داده ای متفاوت گرانبار شده اند . گرانبار کردن توابعی که کار يکسانی را انجام می دهند برنامه را قابل فهم تر و خواناتر می سازد . برنامه زير نحوه به کار گيری توابع گرانبار شده را نشان می دهد .

#include

 

int square( int );

double square( double );

 

void main()

{

  // calls int version

  int intResult = square( 7 );

  // calls double version

  double doubleResult = square( 7.5 );

 

  cout << "\nThe square of integer 7 is "

       << intResult

       << "\nThe square of double 7.5 is "

       << doubleResult

       << endl;

 

} // end main

 

// function square for int values

int square( int x )

{

  cout <<"Called square with int argument: "

       << x << endl;

  return x * x;

} // end int version of function square

 

// function square for double values

double square( double y )

{

  cout <<"Called square with double argument: "

       << y << endl;

  return y * y;

} // end double version of function square

 

 

خروجی برنامه به صورت زير می باشد .

Called square with int argument: 7

Called square with double argument: 7.5

 

The square of integer 7 is 49

The square of double 7.5 is 56.25

برنامه فوق برای محاسبه مربع يک عدد صحيح (int) و يک عدد اعشاری (double) از تابع گرانبارشده square استفاده می کند .هنگامی که دستور:

int intResult = square (7) ;

اجرا می گردد تابع square با پيش تعريف :

int square (int) ;

فراخوانی می شود و هنگامی که دستور :

double doubleResult = square (7.5) ;

اجرا می گردد تابع square با پيش تعريف :

double square (double );

فراخوانی می شود .

نکته : توجه داشته باشيد که توابع گرانبار شده الزامی ندارند که وظيفه يکسانی را انجام دهند . و ممکن است کاملاً با هم تفاوت داشته باشند ، ولی توصيه می شود که توابعی را گرانبار کنيد که يک کار را انجام می دهند .

 

 

اعلان آرايه ها

يک آرايه مجموعه ای از خانه ها متوالی حافظه می باشد که دارای يک نام و يک نوع می باشند . به هر يک از اين خانه ها يک عنصر آرايه گفته می شود . برای دستيابی به يک عنصر آرايه ، بايد نام آرايه و شمارنده آن خانه را مشخص کنيم . لذا عناصر آرايه توسط متغيری به نام انديس مشخص می شوند به همين دليل، آرايه ها را متغيرهای انديس دار نيز می گويند . نام آرايه ، از قواعد نام گذاری متغيرها پيروی می کند . نوع آرايه نيز يکی از انواع داده ذکر شده در مبحث مفاهيم حافظه و انواع داده ای می باشد . اعلان آرايه ها به صورت زير است :

 طول آرايه] نام آرايه   نوع داده آرايه];

به عنوان مثال دستور زير آرايه ای به طول 6 ، با نام num را از نوع int ايجاد می کند .

int num [6];

توجه داشته باشيد که تمام عناصر دارای نام يکسانی می باشند و تنها با انديس از هم تفکيک می شوند . به عنوان مثال عنصر با انديس 2 دارای مقدار 23560- می باشد ، ضمناً انديس عناصر از 0 شروع می شود .

استفاده از يک عبارت محاسباتی به جای انديس عناصر امکان پذير می باشد ، به عنوان مثال با فرض اينکه متغير a حاوی 2 و متغير b حاوی 3 باشد ، دستور زير:

num [a+b] + = 3;

سه واحد به عنصر num [5] اضافه خواهد کرد و اين عنصر حاوی عدد 3 می گردد . برای چاپ مجموع سه عنصر اول آرايه می توانيد از دستور زير استفاده کنيد :

cout << num[0] + num[1] + num[2] << endl;

برای تقسيم عنصر چهارم آرايه بر 2 و قرار دادن حاصل در متغير x از دستور زير می توانيد استفاده کنيد :

x = num[3]/2;

نکته : توجه داشته باشيد که عنصر چهارم آرايه با عنصر شماره چهار ( با انديس چهار ) متفاوت می باشد . همانطور که در دستور فوق ديديد عنصر شماره چهار دارای انديس سه می باشد ، دليل اين امر اينست که انديس گذاری از صفر شروع می شود . در آرايه فوق عنصر چهارم آرايه num[3]=-50 می باشد ولی عنصر شماره چهار ( با انديس چهار ) num[4]=32500 می باشد .

همانند متغيرها چند آرايه را نيز می توان توسط يک دستور تعريف کرد :

int b[100] , x[27] ;

دستور فوق 100 خانه از نوع عدد صحيح را برای آرايه با نام b و 27 خانه از نوع عدد صحيح را برای آرايه با نام x در نظر می گيرد .

برای مقدار دهی اوليه به هر يک از عناصر آرايه می توانيد از شيوه زير استفاده کنيد :

int n[5] = {32 , 27 , 64 , 18 , 95 }

دستور فوق عناصر آرايه n را به صورت زير مقدار دهی می کند .

اگر طول آرايه هنگام تعريف آرايه تعيين نشده باشد و ليست مقدار عناصر نوشته شود ، همانند دستور زير :

int n[] = { 1 , 2 , 3 , 4 , 5 }

در اين صورت کامپايلر به تعداد عناصر ليست ، خانه حافظه برای آرايه در نظر می گيرد ، مثلاً در دستور فوق 5 خانه حافظه برای آرايه n در نظر گرفته می شود .

راه ديگری که برای مقدار دهی اوليه به عناصر آرايه وجود دارد استفاده از روش زير است :

int num[10] = {0}

دستور فوق 10 خانه حافظه برای آرايه num در نظر می گيرد و مقادير همه آنها را صفر می کند . توجه داشته باشيد که اگر از دستور زير استفاده کنيم :

int num[10] = {1}

تمامی عناصر مقدار 1 را نمی گيرند بلکه عنصر اول آرايه يک می شود و بقيه عناصر مقدار صفر را می گيرند .

در تعريف آرايه ديديد که طول آرايه را با عدد صحيح ثابتی تعيين می کنيم . هر جا که از عدد ثابتی استفاده می شود ، متغير ثابت نيز می توان به کار برد . متغيرهای ثابت به صورت زير تعريف می شوند :

const   مقدار متغير = نام متغير ثابت     نوع داده متغير ;

به عنوان مثال :

const  int  arraySize = 10;

دستور فوق عدد 10 را به متغير arraySize ثابت انتساب می دهد . توجه داشته باشيد که مقدار يک متغير ثابت را در طول برنامه نمی توان تغيير داد و نيز متغير ثابت در هنگام تعريف شدن ، مقدار اوليه اش نيز بايد تعيين گردد . به متغيرهای ثابت ، متغيرهای فقط خواندنی نيز گفته می شود . کلمه "متغير ثابت" يک کلمه مرکب ضد و نقيض می باشد چون کلمه متغير متضاد ثابت می باشد و اين اصطلاحی است که برای اينگونه متغيرهای در اکثر زبانهای برنامه نويسی به کار می رود . برنامه زير نحوه تعريف يک متغير ثابت را نشان می دهد :

#include

 

void main()

{

   const int x = 7;

 

   cout << "The value of constant variable x is: "

        << x << endl;

 

}

برنامه فوق عدد 7 را در متغير ثابت x قرار می دهد و توسط دستور cout آنرا چاپ می کند . همانطور که گفتيم مقدار متغير ثابت در هنگام تعريف بايد تعيين گردد و نيز ثابت قابل تغيير نمی باشد ، به برنامه زير توجه کنيد .

#include

 

void main()

{

   const int x; 

 

   x=7;

}

برنامه فوق هنگام کامپايل شدن دو پيغام خطا خواهد داد ، چون متغير ثابت هنگام تعريف مقدار دهی نشده و نيز در برنامه دستوری برای تغيير مقدار آن آورده نشده است .

 Compiling C:\TCP\BIN\CONST1.CPP:

Error : Constant variable 'x' must be initialized

Error : Cannot modify a const object

مثال : در برنامه زير طول آرايه توسط متغير ثابتی تعيين می گردد و عناصر آرايه توسط حلقه for مقدار دهی شده و سپس توسط حلقه for ديگری ، مقدار عناصر آرايه چاپ می گردد .

#include

 

void main()

{

   const int arraySize = 10;

 

   int s[ arraySize ];

 

   for ( int i = 0; i < arraySize; i++ )

   s[ i ] = 2 + 2 * i;

 

   cout << "Element Value" << endl;

 

   for ( int j = 0; j < arraySize; j++ )

       cout << j << "\t " << s[ j ] << endl;

 

}

خروجی برنامه فوق به صورت زير می باشد :

Element  Value

0        2

1        4

2        6

3        8

4        10

5        12

6        14

7        16

8        18

9        20

 

  

 

 چند مثال از آرايه ها و کاربرد آنها

مثال : برنامه ای بنويسيد که 10 عدد صحيح را ورودی دريافت کرده و در آرايه ای قرار داده سپس مجموع عناصر آرايه را محاسبه کرده و درخروجی چاپ نمايد .

#include

 

void main()

{

  const int arraySize = 10;

  int total = 0,i;

  int a[ arraySize ];

 

  for (i = 0; i < arraySize; i++)

    {

     cout << "Enter number " << i << " : ";

     cin >> a[ i ];

    }

 

  for (i = 0; i < arraySize; i++ )

     total += a[ i ];

 

  cout << "Total of array element values is "

       << total << endl;

 

}

خروجی برنامه به صورت زير می باشد :

Enter number 0 : 12

Enter number 1 : 3

Enter number 2 : 4

Enter number 3 : 654

Enter number 4 : 34

Enter number 5 : 2

Enter number 6 : 123

Enter number 7 : 794

Enter number 8 : 365

Enter number 9 : 23

Total of array element values is 2014

مثال : برنامه ای بنويسيد که توسط آرايه ، نمودار ميله ای افقی برای اعداد {1 و17 و5 و13 و9 و11 و7 و15 و3 و19 } رسم کند .

#include

 

int main()

{

  const int arraySize = 10;

  int n[ arraySize ] = { 19, 3, 15, 7, 11,

                         9, 13, 5, 17, 1 };

 

  cout << "Element" << " Value" << endl;

 

  for ( int i = 0; i < arraySize; i++ ) {

     cout << i << "\t " << n[ i ] << "\t";

 

     for ( int j = 0; j < n[ i ]; j++ )

        cout << '*';

     cout << endl;

  }

 

return 0;

 

}

خروجی برنامه به صورت زير می باشد :

 

Element  Value

0        19     *******************

1        3      ***

2        15     ***************

3        7      *******

4        11     ***********

5        9      *********

6        13     *************

7        5      *****

8        17     *****************

9        1      *

مثال : برنامه ای بنويسيد که يک تاس را 6000 بار پرتاب کرده و توسط آرايه ای تعداد دفعات آمدن هر وجه را حساب کند .( تعداد دفعات آمدن هر وجه را يک عنصر آرايه ای در نظر بگيريد )

#include

#include

#include

 

void main()

{

  const int arraySize = 7;

  int frequency[ arraySize ] = { 0 };

 

  srand( time( 0 ) );

 

  for ( int roll = 1; roll <= 6000; roll++ )

     ++frequency[ 1 + rand() % 6 ];

 

  cout << "Face Frequency" << endl;

 

  for ( int face = 1; face < arraySize; face++ )

     cout << face << "\t" << frequency[face] << endl;

 

}

خروجی برنامه به صورت زير می باشد :

 

Face  Frequency

1       1023

2       990

3       1008

4       971

5       1025

6       983

دستور ++frequency [rand()%6 + 1]; ، مقدار عنصر مربوط به هر وجه را يک واحد اضافه می کند ، زيرا rand()%6 + 1 عددی بين 1 تا 6 توليد می کند ، پس هر بار به طور تصادفی تنها مقدار عنصر مربوط به يکی از وجوه افزايش می يابد .

يکی از کار برد های آرايه ها ، استفاده از آنها برای ذخيره رشته ای از حروف می باشد . تا به حال متغيرهايی که از ورودی دريافت می کرديم و يا آرايه هايی که تا به اينجا ديديد تنها شامل اعداد می شدند در اينجا به عنوان مثال نحوه دريافت يک نام از ورودی و چاپ آن در خروجی را بررسی می کنيم .(در فصل بعد يعنی اشاره گرها و رشته ها ، به طور مفصل تر راجع به رشته ها صحبت خواهيم کرد )

يک عبارت رشته ای مانند: "hello" در واقع آرايه ای از حروف می باشد.

char string1[]="hello";

دستور فوق آرايه ای به نام string1 را با کلمه hello مقدار دهی می کند. طول آرايه فوق برابر است با طول کلمه hello يعنی 5 بعلاوه يک واحد که مربوط است به کاراکتر پوچ که انتهای رشته را مشخص می کند. لذا آرايه string1 دارای طول 6 می باشد. کاراکتر پوچ در زبان ++C توسط '\0' مشخص می گردد. انتهای کليه عبارات رشته ای با اين کاراکتر مشخص می شود.

char string1[]={'h','e','l','l','o','\0'}

دستور فوق عناصر آرايه string1 را جداگانه مقدار دهی می کند. توجه داشته باشيد که عناصر آرايه در دستور فوق داخل (') قرار گرفتند و نيز انتهای رشته با '\0' تعيين شد. نتيجه همانند دستور char string1[]="hello"; می باشد.

چون عبارت رشته ای، آرايه ای از حروف می باشند، لذا به هر يک از حروف رشته، توسط انديس عنصری که شامل آن حرف می باشد، می توان دسترسی پيدا کرد. به عنوان مثال string1[0] شامل 'h' و string1[3] شامل 'l' و string1[5] شامل '\0' می باشد.

توسط دستور cin نيز می توان به طور مستقيم کلمه وارد شده از صفحه کليد را در آرايه ای رشته ای قار داد.

char string2[20];

دستور فوق يک آرايه رشته ای که قابليت دريافت کلمه ای با طول 19 به همراه کاراکتر پوچ را دارا می باشد.

cin >> string2;

دستور فوق رشته ای از حروف را از صفحه کليد خوانده و در string2 قرار می دهدو کاراکتر پوچ را به انتهای رشته وارد شده توسط کاربر اضافه می کند. به طور پيش فرض دستور cin کاراکتر ها را از صفحه کليد تا رسيدن به اولين فضای خالی در يافت می کند. به عنوان مثال اگر هنگام اجرای دستور cin >> string2; کاربر عبارت "hello there" را وارد کند، تنها کلمه hello در string2 قرار می گيرد. چون عبارت وارد شده شامل کاراکتر فاصله است. برنامه زير نحوه به کار گيری آرايه های رشته ای را نشان می دهد.

#include

 

void main()

{

  char name[ 20 ];

 

  cout << "Please Enter your name : ";

  cin >> name;

 

  cout << "Welcome, " << name

       << " to this program. \n" ;

 

  cout << "Your separated name is\n";

 

  for ( int i = 0; name[ i ] != '\0'; i++ )

       cout << name[ i ] << ' ';

 

}

خروجی برنامه به صورت زير می باشد :

 

Please Enter your name : Mohammad

Welcome, Mohammad to this program.

Your separated name is

M o h a m m a d

در برنامه فوق حلقه for ، حروف نام وارد شده توسط کاربر را جدا جدا در خروجی چاپ می کند. ضمنا شرط حلقه name[ i ] != '\0' می باشد و تا وقتی اين شرط برقرار است که حلقه به انتهای رشته نرسيده باشد.

در مبحث قوانين حوزه ديديد که اگر بخواهيم يک متغير محلی تابع، مقدار خود را حفظ کرده و برای دفعات بعدی فراخوانی تابع نيز نگه دارد، از کلمه static استفاده کرديم. نوع static را برای آرايه ها نيز می توان به کار برد و از همان قوانين گفته شده در مبحث مذکور پيروی می کند. به برنامه زير و خروجی آن توجه کنيد.

#include

 

void staticArrayInit( void );

void automaticArrayInit( void );

 

int main()

{

  cout << "First call to each function:\n";

  staticArrayInit();

  automaticArrayInit();

 

  cout << "\n\nSecond call to each function:\n";

 

  staticArrayInit();

  automaticArrayInit();

  cout << endl;

 

return 0;

 

}

 

// function to demonstrate a static local array

void staticArrayInit( void )

{

  // initializes elements to 0

  // first time function is called

  static int array1[ 3 ]={0};

 

  cout << "\nValues on entering staticArrayInit:\n";

 

  // output contents of array1

  for ( int i = 0; i < 3; i++ )

     cout << "array1[" << i << "] = "

          << array1[ i ] << " ";

 

  cout << "\nValues on exiting staticArrayInit:\n";

 

  // modify and output contents of array1

  for ( int j = 0; j < 3; j++ )

     cout << "array1[" << j << "] = "

          << ( array1[ j ] += 5 ) << " ";

 

} // end function staticArrayInit

 

// function to demonstrate an automatic local array

void automaticArrayInit( void )

{

  // initializes elements each time function is called

  int array2[ 3 ] = { 1, 2, 3 };

 

  cout << endl << endl;

  cout << "Values on entering automaticArrayInit:\n";

 

  // output contents of array2

  for ( int i = 0; i < 3; i++ )

     cout << "array2[" << i << "] = "

          << array2[ i ] << " ";

 

  cout << "\nValues on exiting automaticArrayInit:\n";

 

  // modify and output contents of array2

  for ( int j = 0; j < 3; j++ )

    cout << "array2[" << j << "] = "

         << ( array2[ j ] += 5 ) << " ";

 

}

خروجی برنامه به صورت زير می باشد :

 

First call to each function:

 

Values on entering staticArrayInit:

array1[0] = 0  array1[1] = 0  array1[2] = 0

Values on exiting staticArrayInit:

array1[0] = 5  array1[1] = 5  array1[2] = 5

 

Values on entering automaticArrayInit:

array2[0] = 1  array2[1] = 2  array2[2] = 3

Values on exiting automaticArrayInit:

array2[0] = 6  array2[1] = 7  array2[2] = 8

 

Second call to each function:

 

Values on entering staticArrayInit:

array1[0] = 5  array1[1] = 5  array1[2] = 5

Values on exiting staticArrayInit:

array1[0] = 10  array1[1] = 10  array1[2] = 10

 

Values on entering automaticArrayInit:

array2[0] = 1  array2[1] = 2  array2[2] = 3

Values on exiting automaticArrayInit:

array2[0] = 6  array2[1] = 7  array2[2] = 8

در برنامه فوق عناصر آرايه array1 در اولين بار فراخوانی تابع staticArrayInit مقدار صفر را می گيرند ولی در دفعات بعدی فراخوانی اين تابع، آخرين مقدار قبلی خود را حفظ می کنند . اما آرايه array2 در هر بار فراخوانی تابع automaticArrayInit مقدار دهی اوليه می شود و با خروج از تابع مقدار خود را از دست می دهد.