ایران سرفراز- نرم افزار وپروژهای دانشجویی


نرم افزار وپروژهای دانشجویی

فصل ششم آرایه ها در ++C

<!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

 

فصل ششم

++C در « آرایه ها »

6 مقدمه ‐1

یک متغیر بخشی از حافظه است که یک نام دارد و می توان مقداری را در آن

ذخیره کرد. با استفاده از متغیرها می توان به پردازش داده ها پرداخت. در برنامه های

کوچک ممکن است بتوانیم کل پردازش را با استفاده از متغیرها عملی کنیم ولی در

برنامه هایی که داده های فراوانی را پردازش می کنند استفاده از متغیرهای معمولی کار

صورت می گیرد به « پردازش دست های » عاقلانه ای نیست زیرا در بسیاری از این برنامه ها

این معنی که مجموعه ای از داد ههای مرتبط با هم در حافظه قرار داده می شود و پس از

پردازش، کل این مجموعه از حافظه خارج می شود و مجموعۀ بعدی در حافظه

بارگذاری می شود. اگر قرار باشد برای این کار از متغیرهای معمولی استفاده شود بیشتر

وقت برنامه نویس صرف پر و خالی کردن انبوهی از متغیرها می شود. به همین دلیل در

تدارک دیده شده اند. آرایه را می توان متغیری « آرایه ها 1 » بیشتر زبا نهای برنامه نویسی

تصور کرد که یک نام دارد ولی چندین مقدار را به طور هم زمان نگهداری می نماید.

1 – Arrays

فصل ششم / آرایه ها 175

چنانچه بعد خواهیم دید، ویرایش محتویات آرایه ها بسیار آسان است و پردازش داد هها

با استفاده از آرایه ها سریع تر و راحت تر صورت می گیرد.

یک آرایه، یک زنجیره از متغیرهایی است که همه از یک نوع هستند. به این

می گویند. هر عضو آرایه با یک شماره مشخص می شود که به « اعضای آرایه » متغیرها

می گویند (نام زیرنویس از نمایش ریاضی آرایه ها « زیرنویس » یا « ایندکس 2 » این شماره

اقتباس شده). ایندکس محل قرار گرفتن هر عضو آرایه را نشان می دهد. مثلا اگر نام

نام عنصری است که در موقعیت صفر آرایه قرار گرفته و a[ باشد، آنگاه [ 0 a آرایه ای

ام آرایه در محل n نام عنصری است که در موقیت 1 آرایه قرار دارد. پس عنصر a[1]

قرار دارد. می بینید که شماره گذاری عناصر آرایه از صفر شروع می شود و a[n-1]

ادامه می یابد. علت این که شماره گذاری n- عنصری این شماره تا 1 n برای یک آرایۀ

از صفر شروع می شود این است که به این روش، اندیس یک عنصر از آرایه، فاصلۀ آن

به عنصری اشاره دارد که سه خانه از a[ عنصر از عنصر اول را نشان می دهد. مثلا [ 3

فاصله دارد. این فاصله یابی بعدها به کار می آید. a[ عنصر اول یعنی [ 0

عناصر یک آرایه در خانه های پشت سر هم در حافظه ذخیره می شوند. به این

ترتیب آرایه را می توان بخشی از حافظه تصور کرد که این بخش خود به قسم تهای

مساوی تقسیم شده و هر قسمت به یک عنصر تعلق دارد. شکل

a[ که پنج عنصر دارد را نشان می دهد. عنصر [ 0 a مقابل آرایۀ

a[ حاوی 19.0 و عنصر [ 4 a[ حاوی مقدار 17.5 و عنصر [ 1

حاوی مقدار 18.0 است. این مقدارها می توانند نمرات یک

دانشجو در یک نیم سال تحصیلی را نشان دهند.

6 پردازش آرایه ها ‐2

آرایه ها را می توان مثل متغیرهای معمولی تعریف و استفاده کرد. با این تفاوت که

آرایه یک متغیر مرکب است و برای دستیابی به هر یک از خان ههای آن باید از ایندکس

استفاده نمود.

0 17.50

1 19.00

2 16.75

3 15.00

4 18.00

1 – Index

176 برنامه سازی پیشرفته

6 دستیابی مستقیم به عناصر آرایه ‐ * مثال 1

برنامۀ سادۀ زیر یک آرایۀ سه عنصری را تعریف می کند و سپس مقادیری را در

آن قرار داده و سرانجام این مقادیر را چاپ می کند:

int main()

{ int a[3];

a[2] = 55;

a[0] = 11;

a[1] = 33;

cout << "a[0] = " << a[0] << endl;

cout << "a[1] = " << a[1] << andl;

cout << "a[2] = " << a[2] << endl;

}

a[0] = 11

a[1] = 33

a[2] = 55

تعریف می کند. سه خط بعدی، مقادیری int خط دوم، یک آرایۀ سه عنصری از نوع

را به این سه عنصر تخصیص می دهد و سه خط آخر هم مقدار هر عنصر آرایه را چاپ

می کند.

6 چاپ ترتیبی عناصر یک آرایه ‐ * مثال 2

برنامۀ زیر پنج عدد را می خواند و سپس آ نها را به ترتیب معکوس چاپ می کند:

int main()

{ const int SIZE=5; // defines the size N for 5 elements

double a[SIZE]; // declares the array's elements as type double

cout << "Enter " << SIZE << " numbers:\t";

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

cin >> a[i];

cout << "In reverse order: ";

for (int i=SIZE-1; i>=0; i--)

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

}

Enter 5 numbers: 11.11 33.33 55.55 77.77 99.99

In reverse order: 99.99 77.77 55.55 33.33 11.11

 

 

فصل ششم / آرایه ها 177

تعریف می کند و مقدار 5 را int از نوع SIZE دومین خط برنامه، ثابتی به نام

float و با پنج عنصر از نوع a درون آن قرار می دهد. خط سوم یک آرایه به نام

پنج عنصر را به داخل آرایه می خواند و for تعریف می نماید. سپس اولین حلقۀ

آن پنج عنصر را به ترتیب معکوس چاپ می کند. for دومین حلقۀ

مثال فوق نشان داد که یک آرایه چطور اعلان می شود. نحو کلی برای اعلان آرایه

به شکل زیر است:

type array_name[array_size];

نام آرایه است و array_name . نوع عناصر آرایه را مشخص می کند type عبارت

تعداد عناصر آرایه را نشان می دهد. این مقدار باید یک عدد ثابت array_size

صحیح باشد و حتما باید داخل کروشه [] قرار بگیرد.

با سه عنصر اعلان شده که این a 6 آرایه ای به نام ‐ در خط دوم از مثال 1

با تعداد a 6 آرایه ای به نام ‐ هستند. در خط سوم از مثال 2 int عناصر از نوع

double مشخص می نماید اعلان شده که عناصر آن از نوع SIZE عناصری که ثابت

هستند. معمولا بهتر است تعداد عناصر آرایه را با استفاده از ثابت ها مشخص کنیم تا

آرایه را پیمایش نماییم. for بعد بتوانیم با استفاده از همان ثابت در حلقۀ

6 مقداردهی آرایه ها ‐3

می توانیم یک آرایه را با استفاده از فهرست مقداردهی، اعلان و C++ در

مقدارگذاری کنیم:

float a[] = {22.2,44.4.66.6};

به این ترتیب مقادیر داخل فهرست به همان ترتیبی که چیده شده اند

درون عناصر آرایه قرار می گیرند. اندازه آرایه نیز برابر با تعداد عناصر

موجود در فهرست خواهد بود. پس همین خط مختصر، آرایه ای از

و با تعداد سه عنصر اعلان کرده و هر سه a و با نام float نوع

عنصر را با مقدارهای درون فهرست، مقداردهی می کند.

6 مقداردهی آرایه با استفاده از فهرست مقداردهی ‐ * مثال 3

a

0 22.2

1 44.4

2 66.6

 

178 برنامه سازی پیشرفته

را مقداردهی کرده و سپس مقدار هر عنصر را چاپ می کند: a برنامۀ زیر، آرایۀ

int main()

{ float a[] = { 22.2, 44.4, 66.6 };

int size = sizeof(a)/sizeof(float);

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

cout << "\ta[" << i << "] = " << a[i] << endl;

}

a[0] = 22.2

a[1] = 44.4

a[2] = 66.6

را به همان صورتی که در بالا آمد اعلان و مقداردهی می کند. در a دومین خط، آرایۀ

استفاده شده. این تابع اندازۀ آرگومان ارسالی به آن را sizeof() خط سوم، از تابع

برابر با 4 است زیرا در این sizeof(float) بر حسب بایت برمی گرداند. مقدار

چهار بایت از حافظه را اشغال می کند. همچنین مقدار float رایانه هر متغیر

برابر با 12 است زیرا آرایۀ مذکور دوازده بایت از حافظه را اشغال sizeof(a)

نموده (سه خانه که هر کدام چهار بایت است). حاصل تقسیم این دو مقدار، تعداد

عناصر آرایه را مشخص می نماید. با استفاده از این روش همیشه می توانیم تعداد عناصر

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

قرار می گیرد تا از این مقدار size درون متغیر sizeof(a)/sizeof(float)

استفاده شود. a برای پیمایش و چاپ عناصر آرایه for در حلقۀ

هنگام استفاده از فهرست مقداردهی برای اعلان آرایه،

می توانیم تعداد عناصر آرایه را هم به طور صریح ذکر کنیم. در این

صورت اگر تعداد عناصر ذکر شده از تعداد عناصر موجود در

فهرست مقداردهی بیشتر باشد، خانه های بعدی با مقدار صفر پر

می شوند:

float a[7] = { 55.5, 66.6, 77.7 };

a

0 55.5

1 66.6

2 77.7

3 0.0

4 0.0

5 0.0

6 0.0

 

فصل ششم / آرایه ها 179

تعریف می کند. سه عنصر اول این float را با هفت عنصر از نوع a اعلان بالا آرایۀ

آرایه با استفاده از فهرست مذکور مقداردهی می شوند و در چهار عنصر باقی مانده مقدار

صفر قرار می گیرد.

6 مقداردهی یک آرایه با صفرهای متوالی ‐ * مثال 4

را اعلان و مقداردهی کرده و سپس مقدار عناصر آن a برنامۀ زیر، آرایه ای به نام

را چاپ می کند:

int main()

{ float a[6] = { 22.2, 44.4, 66.6 };

int size = sizeof(a)/sizeof(float);

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

cout << "\ta[" << i << "] = " << a[i] << endl;

}

a[0] = 22.2

a[1] = 44.4

a[2] = 66.6

a[3] = 0

a[4] = 0

a[5] = 0

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

بیشتر باشد:

float a[3] = { 22.2, 44.4, 66.6, 88.8 }; // ERROR: too many values!

یک آرایه را می توانیم به طور کامل با صفر مقداردهی اولیه کنیم. برای مثال سه

اعلان زیر با هم برابرند:

float a[ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };

float a[9] = { 0, 0 };

float a[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };

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

مثل یک متغیر معمولی، اگر یک آرایه مقداردهی اولیه نشود، عناصر آن حاوی مقادیر

زباله خواهد بود.

180 برنامه سازی پیشرفته

6 یک آرایۀ مقداردهی نشده ‐ * مثال 5

را اعلان می کند ولی مقداردهی نمی کند. با وجود این، مقادیر a برنامۀ زیر، آرایۀ

موجود در آن را چاپ می کند:

int main()

{ const int SIZE=4; // defines the size N for 4 elements

float a[SIZE]; // declares the array's elements as float

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

cout << "\ta[" << i << "] = " << a[i] << endl;

}

a[0] = 6.01838e-39

a[1] = 9.36651e-39

a[2] = 6.00363e-39

a[3] = 0

توجه کنید ک ه مقادیر درون یک آرایۀ مقداردهی نشده ممکن است صفر باشد یا نباشد،

بسته به این که در آن قسمت از حافظه قبلا چه بوده است.

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

مقدار آ نها را به یکدیگر تخصیص داد:

float a[7] = { 22.2, 44.4, 66.6 };

float b[7] = { 33.3, 55.5, 77.7 };

b = a; // ERROR: arrays cannot be assigned!

همچنین نمی توانیم یک آرایه را به طور مستقیم برای مقداردهی به آرایۀ دیگر استفاده

کنیم :

float a[7] = { 22.2, 44.4, 66.6 };

float b[7] = a; // ERROR: arrays cannot be used as

initializers!

6 ایندکس بیرون از حدود آرایه ‐4

در بعضی از زبا نهای برنامه نویسی ، ایندکس آرایه نمی تواند از محدودۀ تعریف

با تعداد پنج عنصر تعریف a شده برای آن بیشتر باشد. برای مثال در پاسکال اگر آرایۀ

دستیابی شود، برنامه از کار می افتد. این سیستم حفاظتی در a[ شده باشد و آنگاه [ 7

 

فصل ششم / آرایه ها 181

وجود ندارد. مثال بعدی نشان می دهد که ایندکس یک آرایه هنگام دستیابی C++

می تواند بیشتر از عناصر تعریف شده برای آن باشد و باز هم بدون این که خطایی

گرفته شود، برنامه ادامه یابد.

6 تجاوز ایندکس آرایه از محدودۀ تعریف شده برای آن ‐ * مثال 6

برنامۀ زیر یک خطای زمان اجرا دارد؛ به بخشی از حافظه دستیابی می کند که از

محدودۀ آرایه بیرون است:

int main()

{ const int SIZE=4;

float a[SIZE} = { 33.3, 44.4, 55.5, 66.6 };

for (int i=0; i<7; i++) // ERROR: index is out of bounds!

cout << "\ta[" << i << "] = " << a[i] << endl;

}

a[0] = 33.3

a[1] = 44.4

a[2] = 55.5

a[3] = 66.6

a[4] = 5.60519e-45

a[5] = 6.01888e-39

a[6] = 6.01889e-39

آرایه ای که در این برنامه تعریف شده، چهار عنصر دارد ولی تلاش می شود به هفت

عنصر دستیابی شود. سه مقدار آخر واقعا جزو آرایه نیستند و فقط سلو لهایی از

حافظه اند که دقیقا بعد از عنصر چهارم آرایه قرار گرفت هاند. این سلو لها دارای مقدار

زباله هستند.

اگر ایندکس آرایه از محدودۀ تعریف شده برای آن تجاوز کند، ممکن است

ناخواسته مقدار سایر متغیرها دست کاری شوند و این باعث بروز فاجعه شود. به مثال

زیر نگاه کنید.

6 اثر همسایگی ‐ * مثال 7

برنامۀ زیر از ایندکس خارج از محدوده استفاده می کند و این باعث می شود که

مقدار یک متغیر به طور ناخواسته تغییر کند:

 

182 برنامه سازی پیشرفته

int main()

{ const int SIZE=4;

float a[] = { 22.2, 44.4, 66.6 };

float x=11.1;

cout << "x = " << x << endl;

a[3] = 88.8; // ERROR: index is out of bounds!

cout << "x = " << x << endl;

}

x = 88.8

اعلان شده، پس یک a بعد از آرایۀ x متغیر

سلول چهاربایتی بلافاصله بعد از دوازده بایت

آرایه به آن تخصیص می یابد. بنابراین وقتی برنامه

قرار a[ تلاش می کند مقدار 88.8 را در [ 3

دهد (که جزو آرایه نیست) این مقدار به شکل

قرار می گیرد. شکل مقابل نشان x ناخواسته در

می دهد چطور این اتفاق در حافظه رخ می دهد.

این خطا یکی از وحشت ناک ترین خطاهای زمان اجراست زیرا ممکن است اصلا

نتوانیم منبع خطا را کشف کنیم. حتی ممکن است به این روش داده های برنامه های

دیگری که در حال کارند را خراب کنیم و این باعث ایجاد اختلال در کل سیستم شود.

می گویند. این وظیفۀ برنامه نویس است که تضمین کند « اثر همسایگی » به این خطا

ایندکس آرایه هیچ گاه از محدودۀ آن خارج نشود.

مثال بعدی نوع دیگری از خطای زمان اجرا را نشان می دهد: وقتی ایندکس آرایه

بیش از حد بزرگ باشد.

6 ایجاد استثنای مدیریت نشده 1 ‐ * مثال 8

برنامۀ زیر از کار می افتد زیرا ایندکس آرایه خیلی بزرگ است:

int main()

{ const int SIZE=4;

a

0 22.2

1 44.4

2 66.6

x 88.8

22.2

44.4

66.6فصل ششم / آرایه ها 183

float a[] = { 22.2, 44.4, 66.6 };

float x=11.1;

cout << "x = " << x << endl;

a[3333] = 88.8; // ERROR: index is out of bounds!

cout << "x = " << x << endl;

}

وقتی  این برنامه روی رایانه ای با سیستم عامل

ویندوز اجرا شود، یک صفحۀ هشدار که در

شکل نشان داده شده روی صفحه ظاهر

می شود. این پنجره بیان می کند که برنامه تلاش

0040108 از حافظه دستیابی e دارد به نشانی

کند. این مکان خارج از حافظۀ تخصیصی

است که برای این برنامه منظور شده، بنابراین سیستم عامل برنامه را متوقف می کند.

نامیده می شود « استثنای مدیریت نشده » 6 بیان شده یک ‐ خطایی که در مثال 8

می توانیم کدهایی به برنامه C++ زیرا کدی وجود ندارد که به این استثنا پاسخ دهد. در

اضافه کنیم که هنگام رخ دادن حال تهای استثنا، از توقف برنامه جلوگیری کند. به این

می گویند. « پردازش گر استثنا 1 » کدها

برخلاف بعضی از زبان های برنامه نویسی دیگر (مثل پاسکال و جاوا) آرایه ها را

نمی توان به طور مستقیم به یکدیگر تخصیص داد و ایندکس آرایه ها نیز می تواند از

محدودۀ آرایه فراتر رود. این ها باعث ایجاد خطاهای زمان کامپایل و خطاهای زمان

اجرا می شود. برای جلوگیری از بروز این خطاها، برنامه نویس باید دقت مضاعفی را در

برنامه به کار بگیرد تا بتواند کد سریع تر و مطمئ نتری تولید کند.

6 ارسال آرایه به تابع ‐5

را اعلان م یکند دو چیز را به کامپایلر م یگوید: a که آرایه float a[]; کد

نشانی a هستند. سمبل float است و این که عناصر آرایه از نوع a این که نام آرایه

1 – Exception handler

88.8

1 – Unhandled exception

 

 

184 برنامه سازی پیشرفته

حافظۀ آرایه را ذخیره می کند. لازم نیست تعداد عناصر آرایه به کامپایلر گفته شود زیرا

می توان عناصر را بازیابی نمود. به همین طریق می توان یک a از روی نشانی موجود در

آرایه را به تابع ارسال کرد. یعنی فقط نوع آرایه و نشانی حافظۀ آن به عنوان پارامتر به

تابع فرستاده می شود.

6 ارسال آرایه به تابعی که مجموع عناصر آرایه را برمی گرداند ‐ * مثال 9

int sum(int[],int);

int main()

{ int a[] = { 11, 33, 55, 77 };

int size = sizeof(a)/sizeof(int);

cout << "sum(a,size) = " << sum(a,size) << endl;

}

int sum(int a[], int n)

{ int sum=0;

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

sum += a[i];

return sum;

}

sum(a,size) = 176

است به این معنا که این (int a[], int n) فهرست پارامتر تابع فوق به شکل

دریافت می کند. به اعلان این تابع int و یک متغیر از نوع int تابع یک آرایه از نوع

نگاه کنید. نام پارامترها حذف شده است. هنگام فراخوانی تابع main() در بالای تابع

استفاده شده که فقط نام آرایه به تابع ارسال شده. نام sum(a,size) نیز از عبارت

تابع از این نشانی برای . (a[ آرایه در حقیقت نشانی اولین عنصر آرایه است (یعنی [ 0

دستیابی به عناصر آرایه استفاده می کند. همچنین تابع می تواند با استفاده از این نشانی،

محتویات عناصر آرایه را دست کاری کند. پس ارسال آرایه به تابع شبیه ارسال متغیر به

طریق ارجاع است. به مثال بعدی دقت کنید.

6 توابع ورودی و خروجی برای یک آرایه ‐ * مثال 10

استفاده می شود تا مقادیری به داخل آرایه وارد read() در این برنامه از تابع

مقادیر داخل آرایه چاپ می شوند: print() شود. سپس با استفاده از تابع

 

فصل ششم / آرایه ها 185

void read(int[],int&;)

void print(int[],int);

int main()

{ const int MAXSIZE=100;

int a[MAXSIZE]={0}, size;

read(a,size);

cout << "The array has " << size << " elements: ";

print(a,size);

}

void read(int a[], int& n)

{ cout << "Enter integers. Terminate with 0:\n";

n = 0;

do

{ cout << "a[" << n << "]: ";

cin >> a[n];

{ while (a[n++] !=0 && n < MAXSIZE);

--n; // don't count the 0

}

void print(int a[], int n)

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

cout << a[i] << " ";

}

Enter integers. Terminate with 0:

a[0]: 11

a[1]: 22

a[2]: 33

a[3]: 44

a[4]: 0

The array has 4 elements: 11 22 33 44

که تعداد عناصر آرایه n و همچنین مقدار پارامتر a مقادیر آرایۀ read() تابع

بتواند read() یک متغیر است، برای این که تابع n است را تغییر می دهد. چون

مقدار آن را تغییر دهد این متغیر باید به شکل ارجاع ارسال شود. همچنین برای این که

را تغییر دهد، آرایه نیز باید به طریق ارجاع a تابع مذکور بتواند مقادیر داخل آرایه

ارسال شود، اما ارجاع آرایه ها کمی متفاوت است.

 

 

186 برنامه سازی پیشرفته

توابع قادر نیستند تعداد عناصر آرایۀ ارسالی را تشخیص دهند. بنابراین C++ در

به منظور ارسال آرایه ها به تابع از سه مشخصه استفاده می شود: 1 – آدرس اولین خانۀ

آرایه 2 – تعداد عناصر آرایه 3 – نوع عناصر آرایه. تابع با استفاده از این سه عنصر

می تواند به تک تک اعضای آرایه دستیابی کند. شکل کار هم به این طریق است که با

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

نوع عناصر مشخص باشد، معلوم می شود که هر خانۀ آرایه چند بایت از حافظه را

اشغال می کند. پس اگر این مقدار به آدرس خانۀ اول اضافه شود، آدرس خانۀ دوم

بدست می آید. اگر مقدار مذکور به آدرس خانۀ دوم اضافه شود، خانۀ سوم معلوم

می شود و به همین ترتیب تابع می تواند به کل آرایه دستیابی داشته باشد. با استفاده از

تعداد عناصر آرایه که با یک پارامتر مجزا ارسال می شود، می توانیم مراقب باشیم که

ایندکس آرایه از حد مجاز فراتر نرود.

آدرس اولین خانۀ آرایه، همان نام آرایه است. پس وقتی نام آرایه را به تابع

بفرستیم آدرس اولین خانه را به تابع فرستاده ایم. نوع آرایه نیز در تعریف تابع اعلان

می شود. بنابراین با این دو مقدار، تابع می تواند به آرایه دسترسی داشته باشد.

با a 6 نگاه کنید. آرایه ‐ به برنامۀ مثال 10

تعریف شده است. با اجرای int 100 عنصر از نوع

آدرس اولین خانۀ آرایه که read(a,size) کد

فرستاده می شود. هر read() قرار دارد به تابع a در

اجرا شود، cin >> a[n]; بار که درون تابع کد

ام به شیوۀ بالا محاسبه می شود و مقدار n آدرس خانۀ

باشد، n= ورودی در آن قرار می گیرد. مثلا اگر 3

فاصله دارد. چون a[ سه پله از خانۀ [ 0 a[3]

چهار بایت از حافظه را اشغال می کند، پس int است و نوع int از نوع a آرایۀ

فاصله دارد. لذا به اندازه a[ 3 بایت از خانۀ [ 0 *4= به اندازۀ 12 a[ آدرس [ 3

a[ افزوده می شود تا به خانۀ [ 3 (a[ دوازده بایت به آدرس اولین خانه (یعنی [ 0

می گویند. آفست یک عنصر از آرایه، a[ عنصر [ 3 « آفست 1 » برسیم. به مقدار 12

a[0]

a[1]

a[2]

a[3]

0x0064fdbb

0x0064fdbc

0x0064fdbd

0x0064fdbe

0x0064fdbf

0x0064fdc0

0x0064fdc1

0x0064fdc2

0x0064fdc3

0x0064fdc4

0x0064fdc5

0x0064fdc6

0x0064fdc7

0x0064fdc8

0x0064fdc9

0x0064fdca

0x0064fdcb

0x0064fdcc

1 – Offset

 

فصل ششم / آرایه ها 187

عددی است که باید به نشانی خانۀ اول افزوده شود تا به خانۀ آن عنصر برسیم.

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

است نام آرایه و اندازۀ آرایه به تابع فرستاده شود. باز هم تاکید می کنیم که نام آرایه،

0x0064fdbc در آدرس a آدرس اولین عنصر آرایه را در خود دارد. مثلا اگر آرایۀ

0 قرار دارد. همچنین نام آرایه x0064fdbc مقدار a واقع شده باشد، آنگاه درون

شبیه یک ثابت عمل می کند. یعنی آدرس یک آرایه همیشه ثابت است و آرایه نمی تواند

به مکان دیگری از حافظه تغییر مکان دهد.

6 آدرس اولین خانۀ آرایه و مقدار درون آن ‐ * مثال 11

برنامۀ زیر، آدرس ذخیره شده در نام آرایه و مقدار موجود در آن خانه را چاپ

می کند:

int main()

{ int a[] = { 22, 44, 66, 88 };

cout << "a = " << a << endl; // the address of a[0]

cout << "a[0] = " << a[0]; // the value of a[0]

}

a = 0x0064fdec

a[0] = 22

این a را چاپ کند. نتیجۀ چاپ a این برنامه تلاش می کند که به طور مستقیم مقدار

است که یک آدرس به شکل شانزده دهی چاپ می شود. این همان آدرس اولین خانۀ

آدرس اولین عنصر آرایه قرار گرفته. خروجی نیز نشان a آرایه است. یعنی درون نام

مقدار اولین عنصر را. a[ آدرس اولین عنصر را دارد و [ 0 a می دهد که

6 الگوریتم جستجوی خطی 1 ‐6

آرایه ها بیشتر برای پردازش یک زنجیره از داد هها به کار می روند. اغلب لازم

است که بررسی شود آیا یک مقدار خاص درون یک آرایه موجود است یا خیر.

ساده ترین راه این است که از اولین عنصر آرایه شروع کنیم و یکی یکی همۀ عناصر

1 – Linear searching

 

188 برنامه سازی پیشرفته

آرایه را جستجو نماییم تا بفهمیم که مقدار مورد نظر در کدام عنصر قرار گرفته. به این

می گویند. « جستجوی خطی » روش

6 جستجوی خطی ‐ * مثال 12

برنامۀ زیر تابعی را آزمایش می کند که در این تابع از روش جستجوی خطی

برای یافتن یک مقدار خاص استفاده شده:

int index(int,int[],int);

int main()

{ int a[] = { 22, 44, 66, 88, 44, 66, 55};

cout << "index(44,a,7) = " << index(44,a,7) << endl;

cout << "index(50,a,7) = " << index(50,a,7) << endl;

}

int index(int x, int a[], int n)

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

if (a[i] == x) return i;

return n; // x not found

}

index(44,a,7) = 1

index(40,a,7) = 7

مقداری است که قرار است جستجو شود، x سه پارامتر دارد: پارامتر index() تابع

هم ایندکس n آرایه ای است که باید در آن جستجو صورت گیرد و پارامتر a پارامتر

عنصری است که مقدار مورد نظر در آن پیدا شده است. در این تابع با استفاده از حلقۀ

مقایسه می شود. اگر این x پیمایش شده و مقدار هر عنصر با a عناصر آرایه for

برابر باشد، ایندکس آن عنصر بازگردانده شده و تابع خاتمه می یابد. اگر x مقدار با

در هیچ یک از عناصر آرایه موجود نباشد، مقداری خارج از ایندکس آرایه x مقدار

موجود نیست. در اولین a در آرایۀ x بازگردانده می شود که به این معناست که مقدار

واقع است و در اجرای a[ اجرای آزمایشی، مشخص شده که مقدار 44 در [ 1

موجود نیست (یعنی مقدار 44 a آزمایشی دوم مشخص شده که مقدار 40 در آرایۀ

عنصر دارد، مقدار 7 نشان a[ فقط تا [ 6 a واقع است و از آ نجا که آرایۀ a[ در [ 7

می دهد که 40 در آرایه موجود نیست).

 

فصل ششم / آرایه ها 189

6 مرتب سازی حبابی 1 ‐7

جستجوی دودویی خیلی کارآمد نیست. هیچ کس برای یافتن معنی یک کلمه در

واژه نامه، همۀ کلمات را از ابتدا جستجو نمی کند زیرا کلمات در واژه نامه به ترتیب

حروف الفبا مرتب شده است و برای یافتن معنی یک کلمه کافی است به طور مستقیم

به بخشی برویم که حرف اول کلمۀ ما در آن بخش فهرست شده است. به این صورت

جستجو بسیار سریع تر صورت می گیرد و پاسخ در زمان کوتا هتری حاصل می شود. اما

شرط این جستجو آن است که همۀ عناصر مرتب باشند.

« مرتب سازی حبابی » . روش های زیادی برای مرتب کردن یک آرایه وجود دارد

یکی از ساده ترین الگوریتم های مرتب سازی است. در این روش، آرایه چندین مرتبه

پویش می شود و در هر مرتبه بزر گترین عنصر موجود به سمت بالا هدایت می شود و

سپس محدودۀ مرتب سازی برای مرتبۀ بعدی یکی کاسته می شود. در پایان همۀ

پویش ها، آرایه مرتب شده است. طریقۀ یافتن بزرگ ترین عنصر و انتقال آن به بالای

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

عنصر اول بزرگ تر بود، جای این دو با هم عوض می شود. سپس عنصر دوم با عنصر

سوم مقایسه می شود. اگر عنصر دوم بزر گتر بود، جای این دو با هم عوض می شود و

به همین ترتیب مقایسه و جابجایی زوج های همسایه ادامه می یابد تا وقتی به انتهای

آرایه رسیدیم، بزر گترین عضو آرایه در خانۀ انتهایی قرار خواهد گرفت. سپس

محدودۀ جستجو یکی کاسته می شود و دوباره زو جهای کناری یکی یکی مقایسه

می شوند تا عدد بزر گتر بعدی به مکان بالای محدوده منتقل شود. این پویش ادامه

می یابد تا این که وقتی محدوده جستجو به عنصر اول محدود شد، آرایه مرتب شده

است.

6 مرت بسازی حبابی ‐ * مثال 13

برنامۀ زیر تابعی را آزمایش می کند که این تابع با استفاده از مرتب سازی حبابی

یک آرایه را مرتب می نماید:

1 – Bobble sorting

 

190 برنامه سازی پیشرفته

void print(float[],int);

void sort(float[],int);

int main()

{ float a[] = {55.5, 22.2, 99.9, 66.6, 44.4, 88.8, 33.3, 77.7};

print(a,8);

sort(a,8);

print(a,8);

}

void sort(float a[], int n)

{ // bubble sort:

for (int i=1; i<n; i++)

// bubble up max{a[0..n-i]}:

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

if (a[j] > a[j+1]) swap (a[j],a[j+1]);

//INVARIANT: a[n-1-i..n-1] is sorted

}

55.5, 22.2, 99.9, 66.6, 44.4, 88.8, 33.3, 77.7

22.2, 33.3, 44.4, 55.5, 66.6, 77.7, 88.8, 99.9

داخلی زوج های همسایه for از دو حلقۀ تودرتو استفاده می کند. حلقه sort() تابع

را با هم مقایسه می کند و اگر آن ها خارج از ترتیب باشند، جای آن دو را با هم عوض

داخلی به پایان رسید، بزرگ ترین عنصر موجود در محدودۀ فعلی به for می کند. وقتی

بیرونی محدودۀ جستجو را یکی کم for انتهای آن هدایت شده است. سپس حلقۀ

داخلی را راه می اندازد تا بزر گترین عنصر بعدی به سمت بالای for می کند و دوباره

آرایه هدایت شود.

6 الگوریتم جستجوی دودویی 1 ‐8

در روش جستجوی دودویی به یک آرایۀ مرتب نیاز است. هنگام جستجو آرایه

از وسط به دو بخش بالایی و پایینی تقسیم می شود. مقدار مورد جستجو با آخرین

عنصر بخش پایینی مقایسه می شود. اگر این عنصر کوچ کتر از مقدار جستجو بود،

مورد جستجو در بخش پایینی وجود ندارد و باید در بخش بالایی به دنبال آن گشت.

1 - Binary searching

 

فصل ششم / آرایه ها 191

دوباره بخش بالایی به دو بخش تقسیم می گردد و گا مهای بالا تکرار می شود. سرانجام

محدودۀ جستجو به یک عنصر محدود می شود که یا آن عنصر با مورد جستجو برابر

است و عنصر مذکور یافت شده و یا این که آن عنصر با مورد جستجو برابر نیست و

لذا مورد جستجو در آرایه وجود ندارد. این روش پیچیده تر از روش جستجوی خطی

است اما در عوض بسیار سریع تر به جواب می رسیم. البته به شرطی به جواب می رسیم

که آرایه مرتب شده باشد.

6 جستجوی دودویی ‐ * مثال 14

6 یکی است اما تابعی که در زیر ‐ برنامۀ آزمون زیر با برنامۀ آزمون مثال 12

آمده از روش جستجوی دودویی برای یافتن مقدار درون آرایه استفاده می کند:

int index(int, int[],int);

int main()

{ int a[] = { 22, 33, 44, 55, 66, 77, 88 };

cout << "index(44,a,7) = " << index(44,a,7) << endl;

cout << "index(60,a,7) = " << index(60,a,7) << endl;

}

int index(int x, int a[], int n)

{ // PRECONDITION: a[0] <= a[1] <= ... <= a[n-1];

// binary search:

int lo=0, hi=n-1, i;

while (lo <= hi)

{ i = (lo + hi)/2; // the average of lo and hi

if (a[i] == x) return i;

if (a[i] < x) lo = i+1; // continue search in a[i+1..hi]

else hi = i-1; // continue search in a[0..i-1]

}

return n; // x was not found in a[0..n-1]

}

index(44,a,7) = 2

index(60,a,7) = 7

 

 

192 برنامه سازی پیشرفته

دقت کنید که آرایه، قبل از به کارگیری جستجوی دودویی باید مرتب باشد. این

پیش شرط به شکل توضیح در برنامۀ اصلی قید شده است.

را index(44,a, برای این که بفهمیم تابع چطور کار می کند، فراخوانی ( 7

است. hi= و 6 lo= و 0 n= و 7 x= دنبال می کنیم. وقتی حلقه شروع می شود، 44

عنصر وسط آرایۀ a[i] 0) را می گیرد.پس عنصر +6)/2 = مقدار 3 i ابتدا

x بزرگ تر است. پس x برابر با 55 است که از مقدار a[ است. مقدار [ 3 a[0..6]

یعنی 2 i- با 1 hi در نیمۀ بالایی نیست و جستجو در نیمۀ پایینی ادامه می یابد. لذا

است و دوباره عنصر lo= و 0 hi= مقداردهی می شود و حلقه تکرار می گردد. حالا 2

برابر با 33 است که a[ مقایسه می شود. [ 1 x با a[ یعنی [ 1 a[0.. وسط آرایۀ [ 2

یعنی 2 می شود. در سومین i+ برابر با 1 lo می باشد. پس این دفعه x کوچک تر از

که همان a[2.. است. پس عنصر وسط آرایۀ [ 2 lo= و 2 hi= دور حلقه، 2

a[ مقایسه می شود. [ 2 x است با a[2]

برابر است. پس x برابر با 44 است که با

x مقدار 2 بازگشت داده می شود؛ یعنی

وجود دارد. a[ مورد نظر در [ 2

را دنبال می کنیم. وقتی حلقه شروع index(60,a, حال فراخوانی ( 7

a[0.. است. عنصر وسط آرایۀ [ 6 hi= و 6 lo= و 0 n= و 7 x= می شود، 60

می شود و i+1= برابر با 4 lo کوچک تر است. پس x است که از a[3]= عنصر 55

است . عنصر وسط آرایۀ lo= و 4 hi= حلقه دوباره تکرار می شود. این دفعه 6

i-1= به 4 hi می باشد. پس x است که بزرگ تر از a[5]= عنصر 77 a[4..6]

است و عنصر lo= و 4 hi= تغییر می یابد و دوباره حلقه تکرار می شود. این بار 4

به hi می باشد. لذا x است که بزرگ تر از a[4]= عنصر 66 a[4.. وسط آرایۀ [ 4

کاهش می یابد. اکنون شرط حلقه i-1=3

است. بنابراین hi<lo غلط می شود زیرا

تابع مقدار 7 را برمی گرداند یعنی عنصر

مورد نظر در آرایه موجود نیست.

lo hi i a[i] ?? x

0 6 3 55 > 44

2 1 33 < 44

2 2 44 == 44

lo hi i a[i] ?? x

0 6 3 55 < 60

4 5 77 > 60

4 4 66 > 60

 

 

فصل ششم / آرایه ها 193

در تابع فوق هر بار که حلقه تکرار می شود، محدودۀ جستجو 50 % کوچک تر

مقایسه log2 n + عنصری، روش جستجوی دودویی حداکثر به 1 n می شود. در آرایۀ

مقایسه نیاز n نیاز دارد تا به پاسخ برسد. حال آن که در روش جستجوی خطی به

است. برای مثال در یک آرایه 100 عنصری برای مشخص شدن این که مقدار مورد

log2100 +1 = نظر در آرایه هست یا خیر در روش جستجوی دودویی به 7.64

مقایسه نیاز است. یعنی حداکثر با 8 مقایسه به پاسخ می رسیم ولی در روش جستجوی

خطی روی همین آرایه به حداکثر 100 مقایسه نیاز داریم. پس جستجوی دودویی

سریع تر از جستجوی خطی است. دومین تفاوت در این است که اگر چند عنصر دارای

مقادیر یکسانی باشند، آنگاه جستجوی خطی همیشه کوچک ترین ایندکس را

برمی گرداند ولی در مورد جستجوی دودویی نمی توان گفت که کدام ایندکس

بازگردانده می شود. سومین فرق در این است که جستجوی دودویی فقط روی

آرایه های مرتب کارایی دارد و اگر آرایه ای مرتب نباشد، جستجوی دودویی پاسخ غلط

می دهد ولی جستجوی خطی همیشه پاسخ صحیح خواهد داد.

6 مشخص کردن این که آیا آرایه مرتب است یا خیر ‐ * مثال 15

برنامۀ زیر یک تابع بولی را آزمایش می کند. این تابع مشخص می نماید که آیا

آرایۀ داده شده غیر نزولی است یا خیر:

bool isNondecreasing(int a[], int n);

int main()

{ int a[] = { 22, 44, 66, 88, 44, 66, 55 };

cout << "isNondecreasing(a,4) = " << isNondecreasing(a,4)

<< endl;

cout << "isNondecreasing(a,7) = " << isNondecreasing(a,7)

<< endl;

}

bool isNondecreasing(int a[], int n)

{ // returns true iff a[0] <= a[1] <= ... <= a[n-1]:

for (int i=1; i<n; i++)

if (a[i]<a[i-1]) return false;

return true;

}

 

194 برنامه سازی پیشرفته

isNondecreasing(a,4) = 1

isNondecreasing(a,7) = 0

را مقایسه a[i] و a[i- این تابع یک بار کل آرایه را پیمایش کرده و زو جهای [ 1

را بر false باشد، مقدار a[i]<a[i- می کند. اگر زوجی یافت شود که در آن [ 1

به false و true می گرداند به این معنی که آرایه مرتب نیست. ببینید که مقادیر

شکل اعداد 1 و 0 در خروجی چاپ می شوند زیرا مقادیر بولی در حقیقت به شکل

اعداد صحیح در حافظه ذخیره می شوند.

6 یعنی مرتب بودن آرایه رعایت نشود، جستجوی ‐ اگر پیش شرط 1 مثال 14

دودویی پاسخ درستی نمی دهد. به این منظور ابتدا باید این پیش شرط بررسی شود. با

می توان اجرای یک برنامه را به یک شرط وابسته کرد. این assert() استفاده از تابع

باشد، برنامه را خاتمه false تابع یک آرگومان بولی می پذیرد. اگر مقدار آرگومان

باشد، true داده و موضوع را به سیستم عامل گزارش می کند. اگر مقدار آرگومان

تعریف <cassert> در سرفایل asset() برنامه بدون تغییر ادامه می یابد. تابع

شده است.

برای رعایت کردن یک پیش شرط assert() 6 استفاده از تابع ‐ * مثال 16

6 را آزمایش ‐ مثال 14 search() برنامۀ زیر نسخۀ بهبودیافته ای از تابع

6 استفاده شده ‐ مثال 15 isNonDecreasing() می کند. در این نسخه، از تابع

ارسال assert() تا مشخص شود آرایه مرتب است یا خیر. نتیجه این تابع به تابع

می گردد تا اگر آرایه مرتب نباشد برنامه به بیراهه نرود:

#include <cassert> // defines the assert() function

#include <iostream> // defines the cout object

using namespace std;

int index(int x, int a[], int n);

int main()

{ int a[] = { 22, 33, 44, 55, 66, 77, 88, 60 };

cout << "index(44,a,7) = " << index(44,a,7) << endl;

cout << "index(44,a,8) = " << index(44,a,8) << endl;

1 – Precondition

 

 

فصل ششم / آرایه ها 195

cout << "index(60,a,8) = " << index(60,a,8) << endl;

}

bool isNondecreasing(int a[], int n);

int index(int x, int a[], int n)

{ // PRECONDITION: a[0] <= a[1] <= ... <= a[n-1];

// binary search:

assert(isNondecreasing(a,n));

int lo=0, hi=n-1, i;

while (lo <= hi)

{ i = (lo + hi)/2;

if (a[i] == x) return i;

if (a[i] < x) lo = i+1; // continue search in a[i+1..hi]

else hi = i-1; // continue search in a[0..n-1]

}

return n; // x was not found in a[0..n-1]

}

index(44,a,7) = 2

که  در این برنامه استفاده شده کاملا مرتب نیست اما هفت عنصر اول آن a[] آرایۀ

را به true تابع بولی مقدار index(44,a, مرتب است. بنابراین در فراخوانی ( 7

ارسال می کند و برنامه ادمه می یابد. اما در دومین فراخوانی assert()

مقدار isNondecreasing() باعث می شود که تابع index(44,a,8)

را به تابع false

ارسال کند که assert()

در این صورت برنامه

متوقف می شود و ویندوز

پنجرۀ هشدار مقابل را

نمایش می دهد.

6 استفاده از انواع شمارشی در آرایه ‐9

انواع شمارشی در فص ل دوم توضیح داده شده اند. با استفاده از انواع شمارشی نیز

می توان آرایه ها را پردازش نمود.

196 برنامه سازی پیشرفته

6 شمارش با استفاده از روزهای هفته ‐ * مثال 17

تعریف float با هفت عنصر از نوع high[] این برنامه یک آرایه به نام

می کند ک ه هر عنصر حداکثر دما در یک روز هفته را نشان می دهد:

int main()

{ enum Day { SUN, MON, TUE, WED, THU, FRI, SAT };

float high[SAT+1] = {28.6, 29.1, 29.9, 31.3, 30.4, 32.0, 30.7};

for (int day = SUN; day <= SAT; day++)

cout << "The high temperature for day " << day << " was "

<< high[day] << endl;

}

The high temperature for day 0 was 28.6

The high temperature for day 1 was 29.1

The high temperature for day 2 was 29.9

The high temperature for day 3 was 31.3

The high temperature for day 4 was 30.4

The high temperature for day 5 was 32.0

The high temperature for day 6 was 30.7

به خاطر بیاورید که انواع شمارشی به شکل مقادیر عددی ذخیره می شوند. اندازۀ

مقدار صحیح 6 را دارد و آرایه به هفت عنصر نیازمند SAT است زیرا SAT+ آرایه، 1

را به آن تخصیص داد. Day است پس می توان مقادیر int از نوع day است. متغیر

« خود استناد » استفاده از انواع شمارشی در برخی از برنامه ها باعث می شود که کد برنامه

6 کنترل حلقه به شکل ‐ شود. مثلا در مثال 17

for (int day = SUN; day <= SAT; day++)

بالا را به خوبی درک کند. for باعث می شود که هر بیننده ای حلقۀ

6 تعریف انواع ‐10

انواع شمارشی یکی از را ههایی است که کاربر می تواند نوع ساخت خودش را

تعریف کند. برای مثال دستور زیر :

enum Color { RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET };

 

 

 

 

فصل ششم / آرایه ها 197

تعریف می کند که متغیرهایی از این نوع می توانند مقادیر Color یک نوع جدید به نام

را داشته باشند. پس VIOLET یا BLUE یا GREEN یا YELLOW یا ORANGE یا RED

با استفاده از این نوع می توان متغیرهایی به شکل زیر تعریف نمود:

Color shirt = BLUE;

Color car[] = { GREEN, RED, BLUE, RED };

float wavelength[VIOLET+1] = {420, 480, 530, 570, 600, 620};

مقداردهی شده. BLUE است و با مقدار Color متغیری از نوع shirt در این جا

و RED و GREEN یک آرایۀ چهار عنصری است و مقدار عناصر آن به ترتیب car

است که float آرایه ای از نوع wavelength می باشد. همچنین RED و BLUE

5 عنصر است. +1= عنصر یعنی 6 VIOLET+ دارای 1

یک typedef می توان نام انواع استاندارد را تغییر داد. کلمۀ کلیدی C++ در

نام مستعار برای یک نوع استاندارد موجود تعریف می کند. نحو استفاده از آن به شکل

زیر است:

typedef type alias;

نام مستعار برای آن است . برای مثال کسانی alias یک نوع استاندارد و type که

استفاده Integer از عبارت long که با پاسکال برنامه می نویسند به جای نوع

استفاده می نمایند. این افراد Real از عبارت double می کنند و به جای نوع

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

typedef long Integer;

typedef double Real;

و پس از آن کدهای زیر معتبر خواهند بود:

Integer n = 22;

const Real PI = 3.141592653589793;

Integer frequency[64];

را به شکل زیر بکار ببریم می توانیم آرایه ها را بدون علامت typedef اگر دستور

براکت تعریف کنیم:

typedef element-type alias[];

 

 

198 برنامه سازی پیشرفته

مثل تعریف زیر :

typedef float sequence[];

را به شکل زیر اعلان کنیم: a سپس می توانیم آرایۀ

sequence a = {55.5, 22.2, 99.9};

نوع جدیدی را اعلان نمی کند، بلکه فقط به یک نوع موجود typedef دستور

را نشان typedef نام مستعاری را نسبت می دهد. مثال بعدی نحوۀ به کارگیری

می دهد.

6 دوباره مرتب سازی حبابی ‐ * مثال 18

استفاده typedef 6 است با این فرق که از ‐ برنامۀ زیر همان برنامۀ مثال 13

به عنوان یک نوع استفاده کرد. سپس این نوع sequrnce شده تا بتوان از نام مستعار

به کار رفته است: main() در تابع a در فهرست پارامترها و اعلان

typedef float Sequence[];

void sort(Sequence,int);

void print(Sequence,int);

int main()

{ Sequence a = {55.5, 22.2, 99.9, 66.6, 44.4, 88.8, 33.3, 77.7};

print(a,8);

sort(a,8);

print(a,8);

}

void sort(Sequence a, int n)

{ for (int i=n-1; i>0; i--)

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

if (a[j] > a[j+1]) swap(a[j],a[j+1]);

}

نگاه کنید: typedef دوباره به دستور

typedef float Seguence[];

 

فصل ششم / آرایه ها 199

Sequence علامت براکت ها [] نشان می دهند که هر چیزی که از نوع

نیز بیان می کند که این آرایه از نوع float تعریف شود، یک آرایه است و عبارت

است. float

6 آرایه های چند بعدی ‐11

همۀ آرایه هایی که تاکنون تعریف کردیم، یک بعدی هستند، خطی هستند،

رشته ای هستند. می توانیم آرایه ای تعریف کنیم که از نوع آرایه باشد، یعنی هر خانه از

آن آرایه، خود یک آرایه باشد. به این قبیل آرایه ها، آرایه های چندبعدی 1 می گوییم. یک

آرایۀ دو بعدی آرایه ای است که هر خانه از آن، خود یک آرایۀ یک بعدی باشد. یک

آرایۀ سه بعدی آرایه ای است که هر خانه از آن یک آرایۀ دو بعدی باشد.

تعریف می کند. این یک int آرایه ای با پنج عنصر از نوع int a[ دستور ;[ 5

آرایه ای با سه عنصر تعریف int a[3][ آرایۀ یک بعدی است. دستور ;[ 5

است. این یک آرایۀ int می کند که هر عنصر، خود یک آرایۀ پنج عنصری از نوع

int a[2][3][ دو بعدی است که در مجموع پانزده عضو دارد. دستور ;[ 5

آرایه ای با دو عنصر تعریف می کند که هر عنصر، سه آرایه است که هر آرایه پنج عضو

دارد. این یک آرایۀ سه بعدی است که در مجموع سی عضو دارد. به int از نوع

همین ترتیب می توان آرایه های چند بعدی تعریف نمود.

شکل دستیابی به عناصر در آرایه های چند بعدی مانند آرایه های یک بعدی است.

مثلا دستور

a[1][2][3] = 99;

مقدار 99 را در عنصری قرار می دهد که ایندکس آن عنصر( 1,2,3 ) است.

آرایه های چند بعدی مثل آرایه های یک بعدی به توابع فرستاده می شوند با این

تفاوت که هنگام اعلان و تعریف تابع مربوطه، باید تعداد عناصر بعد دوم تا بعد آخر

حتما ذکر شود.

1 – Multi dimensional arrays

 

 

200 برنامه سازی پیشرفته

6 نوشتن و خواندن یک آرایۀ دو بعدی ‐ * مثال 19

برنامۀ زیر نشان می دهد که یک آرایۀ دوبعدی چگونه پردازش می شود:

void read(int a[][5]);

void print(int a[][5]);

int main()

{ int a[3][5];

read(a);

print(a);

}

void read(int a[][5])

{ cout << "Enter 15 integers, 5 per row:\n";

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

{ cout << "ROW " << i << ": ";

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

cin >> a[i][j];

}

}

void print(const int a[][5])

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

{ for (int j=0; j<5; j++)

cout << " " << a[i][j];

cout << endl;

}

}

Enter 15 integers, 5 per row:

row 0: 44 77 33 11 44

row 1: 60 50 30 90 70

row 2: 65 25 45 45 55

44 77 33 11 44

60 50 30 90 70

65 25 45 45 55

دقت کنید که در فهرست پارامترهای توابع بالا، بعد اول نامشخص است اما بعد دوم

در حقیقت آرایه ای a[][] مشخص شده. علت هم این است که آرایۀ دو بعدی

یک بعدی از سه آرایۀ پنج عنصری است. کامپایلر نیاز ندارد بداند که چه تعداد از این

آرایه های پنج عنصری موجود است، اما باید بداند که آ نها پنج عنصری هستند.

فصل ششم / آرایه ها 201

وقتی یک آرایۀ چند بعدی به تابع ارسال می شود، بعد اول مشخص نیست اما

همۀ ابعاد دیگر باید مشخص باشند.

6 پردازش یک آرایۀ دوبعدی از نمرات امتحانی ‐ * مثال 20

const NUM_STUDENTS = 3;

const NUM_QUIZZES = 5;

typedef int Score[NUM_STUDENTS][NUM_QUIZZES];

void read(Score);

void printQuizAverages(Score);

void printClassAverages(Score);

int main()

{ Score score;

cout << "Enter " << NUM_QUIZZES

<< " quiz scores for each student:\n";

read(score);

cout << "The quiz averages are:\n";

printQuizAverages(score);

cout << "The class averages are:\n";

printClassAverages(score);

}

void read(Score score)

{ for (int s=0; s<NUM_STUDENTS; s++)

{ cout << "Student " << s << ": ";

for (int q=0; q<NUM_QUIZZES; q++)

cin >> score[s][q];

}

}

void printQuizAverages(Score score)

{ for (int s=0; s<NUM_STUDENTS; s++)

{ float sum = 0.0;

for (int q=0; q<NUM_QUIZZES; q++)

sum += score[s][q];

cout << "\tStudent " << s << ": " << sum/NUM_QUIZZES

<< endl;

}

202 برنامه سازی پیشرفته

}

void printClassAverages(Score score)

{ for (int q=0; q<NUM_QUIZZES; q++)

{ float sum = 0.0;

for (int s=0; s<NUM_STUDENTS; s++)

sum += score[s][q];

cout << "\tQuiz " << q << ": " << sum/NUM_STUDENTS

<< endl;

}

}

Enter 5 quiz scores for each student:

student 0: 8 7 9 8 9

student 1: 9 9 9 9 8

student 2: 5 6 7 8 9

The quize averages are:

student 0: 8.2

student 1: 8.8

student 2: 7

The class averages are:

Quiz 0: 7.33333

Quiz 1: 7.33333

Quiz 2: 8.33333

Quiz 3: 8.33333

Quiz 4: 8.66667

3 نام * برای آرایه های دوبعدی 5 typedef در برنامۀ فوق با استفاده از دستور

انتخاب شده. این باعث می شود که توابع خواناتر باشند. هر تابع از دو Score مستعار

تودرتو استفاده کرده که حلقۀ بیرونی، بعد اول را پیمایش می کند و حلقۀ for حلقۀ

درونی بعد دوم را پیمایش می نماید.

میانگین هر سطر از نمرات را محاسبه و printQuizAverages() تابع

میانگین هر ستون از نمره ها را printClassAverages() چاپ می نماید و تابع

چاپ می کند.

6 پردازش یک آرایۀ سه بعدی ‐ * مثال 21

این برنامه تعداد صفرها را در یک آرایۀ سه بعدی می شمارد:

 

 

 

فصل ششم / آرایه ها 203

int numZeros(int a[][4][3], int n1, int n2, int n3);

int main()

{ int a[2][4][3] = { { {5,0,2}, {0,0,9}, {4,1,0}, {7,7,7} },

{ {3,0,0}, {8,5,0}, {0,0,0}, {2,0,9} } };

cout << "This array has " << numZeros(a,2,4,3)

<< " zeros:\n";

}

int numZeros(int a[][4][3], int n1, int n2, int n3)

{ int count = 0;

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

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

for (int k = 0; k < n3; k++)

if (a[i][j][k] == 0) ++count;

return count;

}

This array has 11 zeros:

توجه کنید که آرایه چگونه مقداردهی شده است. این قالب مقداردهی به خوبی نمایان

می کند که آرایۀ مذکور یک آرایه دو عنصری است که هر عنصر، خود یک آرایۀ

چهار عضوی است که هر عضو شامل آرایه ای سه عنصری می باشد. پس این آرایه در

مجموع 24 عنصر دارد. آرایۀ مذکور را به شکل زیر نیز می توانیم مقداردهی کنیم:

int a[2][4][3]={5,0,2,0,0,9,4,1,0,7,7,7,3,0,0,8,5,0,0,0,0,2,0,9};

و یا مانند این :

int a[2][4][3] =

{{5,0,2,0,0,9,4,1,0,7,7,7},{3,0,0,8,5,0,0,0,0,2,0,9}};

هر سۀ این قالب ها برای کامپایلر یک مفهوم را دارند اما با نگاه کردن به دو قالب اخیر

به سختی می توان فهمید که کدام عنصر از آرایه، کدام مقدار را خواهد داشت.

n تودرتو دقت کنید. به طور کلی برای پیمایش یک آرایۀ for به سه حلقۀ

حلقۀ تودرتو نیاز است. 204 برنامه سازی پیشرفته

پرسش های گزینه ای

1 – کدام گزینه اشتباه است؟

الف – یک آرایه مجموعه ای از متغیرهاست که همگی یک نوع دارند

ب – می توان آرایه را از قسمتی از حافظه به قسمت دیگر منتقل نمود

ج – محل قرارگیری عناصر آرایه در حافظه، پشت سر هم و پیوسته است

د – آرایه را می توان برای دست کاری به تابع ارسال کرد

کدام گزینه اشتباه است؟ int a[ 2 – در مورد دستور ;[ 5

الف – این دستور یک آرایۀ یک بعدی را اعلان می کند

ب – اعضای این آرایه از نوع عددی صحیح هستند

ج – این آرایه پنج عضو دارد

د – هر عضو دارای مقدار پیش فرض صفر است

معادل کدام گزینۀ زیر است؟ int a[] = {0, 0, 3 – کد ;{ 0

int a[ ب – ;[ 0 int a[] = { الف – ;{ 0

int a[3] = { د – ;{ 0 int a[ ج – ;[ 0,0,0

کدام گزینه صحیح است؟ int a[5] = {1, 2, 4 – در مورد دستور ;{ 3

دارای مقدار صفر هستند. a الف – عناصر چهارم و پنجم آرایه

سه عنصر دارد a ب – آرایۀ

دارای مقدار زباله هستند a ج – دو عنصر اول آرایه

د – در این دستور پنج آرایۀ سه عنصری اعلان شده است

کدام گزینه float a[2] = {1.11, 2.22, 5 – در مورد دستور ;{ 3.33

صحیح است؟

دارد float سه عنصر از نوع a الف – آرایۀ

باید دو رقم اعشار داشته باشد a ب – هر عضو آرایۀ

مقدار پیش فرض صفر دارد a ج – عنصر سوم آرایۀ

د – این دستور اشتباه است زیرا فهرست مقداردهی بیش از عناصر آرایه عضو دارد n بعدی به

 

 

فصل ششم / آرایه ها 205

6 – اگر ایندکس آرایه از تعداد اعضای آن بیشتر شود آنگاه:

الف – ممکن است برنامه متوقف شود زیرا اثر همسایگی رخ می دهد

ب – کامپایلر خطا می گیرد و برنامه اصلا اجرا نمی شود

ج – سیستم عامل خطا می گیرد و برنامه متوقف می شود

د – در زمان اجرا به تعداد اعضای آرایه اضافه می شود تا به اندازه ایندکس برسد

و با پنج عنصر تعریف شده باشد، آنگاه کد int از نوع a 7 – اگر آرایۀ

چه اثری دارد؟ float b[] = a;

الف – این کد اشتباه است زیرا آرایه ها را نمی توان به یکدیگر تخصیص داد

قرار می گیرد b ارتقا یافته و سپس درون آرایۀ float به نوع a ب – مقادیر آرایۀ

در آن کپی شود a با پنج عنصر ایجاد می شود بدون این که اعضای آرایۀ b ج – آرایۀ

درون آن کپی می شود a با پنج عنصر ایجاد می شود و اعضای آرایۀ b د – آرایۀ

چه عملی انجام می دهد؟ int a[2][ 8 – دستور ;[ 4

الف – یک آرایۀ دو بعدی تعریف می کند که این آرایه در کل 8 عنصر دارد

ب – یک آرایۀ دو بعدی تعریف می کند که این آرایه در کل 6 عنصر دارد

ج – یک آرایۀ دو بعدی تعریف می کند که مقدار پیش فرض عناصر بعد اول، مقدار 2

و مقدار پیش فرض عناصر بعد دوم ، مقدار 4 است

د – یک آرایۀ یک بعدی با دو عضو تعریف می کند که مقدار عضو اول 2 و مقدار

عضو دوم 4 است

چه رخ می دهد؟ cout << a; یک آرایه باشد، آنگاه با اجرای کد a 9 – اگر

در خروجی چاپ می شود a الف – مقدار اعضای آرایۀ

در خروجی چاپ می شود a ب – تعداد اعضای آرایۀ

در خروجی چاپ می شود a ج – آدرس اولین خانۀ آرایۀ

د – سیستم عامل خطا می گیرد و پیغام خطا در خروجی چاپ می شود

فقط یک پارامتر دارد و آن هم از نوع آرایه است. print() 10 – فرض کنید تابع

را a یک آرایۀ سه عنصری باشد، آنگاه کدام یک از دستورهای زیر آرایۀ a اگر آرایه

می فرستد؟ print() به تابع

print(a[]); – ب print(a[ الف – ;([ 3

 

206 برنامه سازی پیشرفته

a.print(); – د print(a); – ج

تعریف شده است. تابع int c[2][3][ به شکل ;[ 4 c 11 – آرایۀ

به آن ارسال شود. با این c بوده و قرار است که آرایۀ void از نوع print()

باید چگونه اعلان شود؟ print() توضیحات، تابع

void print(int [][][]); ‐ الف

void print(int [2][3][ ب – ;([ 4

void print(int[][3][ ج ‐ ;([ 4

void print(int, int, int); – د

را چاپ می کند؟ a 12 – کدام دستور مقدار اولین عنصر آرایۀ

cout << a[ ب – ;[ 1 cout << a[ الف ‐ ;[ 0

cout << [a د – ;[ 0 cout << a; – ج

باشد آنگاه کدام دستور مقدار 10 را int دارای پنج عنصر از نوع a 13 – اگر آرایۀ

درون آخرین عضو این آرایه قرار می دهد؟

a[4] = ب – ; 10 a[5] = الف ‐ ; 10

a(4) = د – ; 10 a(5) = ج ‐ ; 10

تعریف شده باشد آنگاه کد int a[5][5][ به شکل ;[ 5 a 14 – اگر آرایۀ

چه اثری دارد؟ a[5][5][5] = 0;

را صفر می کند a الف – آخرین عضو آرایۀ

قرار گرفته را صفر می کند a 5) از آرایۀ , 5, ب – عضوی که در محل ( 5

را صفر می کند a ج – همۀ اعضای آرایۀ

ندارد a د – اثری روی اعضای آرایۀ

چه کاری انجام می دهد؟ typedef 15 – دستور

الف – یک نوع جدید تعریف می کند

ب – یک متغیر جدید تعریف می کند

ج – برای یک نوع موجود، نام مستعار تعریف می کند

د – برای یک متغیر موجود، نام مستعار تعریف می کند

 

فصل ششم / آرایه ها 207

عضو دارد به چند حلقه k بعد و در هر بعد n 16 – برای پیمایش آرایه ای که

نیازمندیم؟

حلقه n+k – حلقه د n-k – حلقه ج k – حلقه ب n ‐ الف

17 – در مورد ارسال آرایه ها به تابع، کدام گزینه صحیح نیست؟

الف – آدرس اولین عنصر آرایه به تابع فرستاده می شود

ب – تابع می تواند با توجه به نوع عناصر آرایه و آدرس اولین عنصر آن، به تک تک

عناصر آرایه دسترسی داشته باشد

ج – در حقیقت آرایه ها به طریق ارجاع به تابع ارسال می شوند

د – لازم نیست تابع چیزی راجع به ابعاد آرایه بداند

18 – به مقداری که باید به آدرس عنصر اول آرایه اضافه شود تا به یک عنصر

مفروض برسیم چه می گویند؟

الف – آفست ب – ایندکس ج – بعد د ‐ فاصله

 

208 برنامه سازی پیشرفته

پرسش های تشریحی

1‐ اعضای یک آرایه چند نوع متفاوت می توانند داشته باشند؟

2‐ ایندکس آرایه چه نوع و محدوده ای باید داشته باشد؟

3‐ اگر یک آرایه اعلان شده باشد ولی مقداردهی نشده باشد، عناصر آن آرایه چه

مقادیری خواهند داشت؟

4‐ اگر یک آرایه اعلان شده باشد ولی فهرست مقداردهی آن نسبت به اعضای آرایه

تعداد کم تری داشته باشد آنگاه عناصر آن آرایه چه مقادیری خواهند داشت؟

5‐ اگر در فهرست مقداردهی یک آرایه، عناصر بیشتری نسبت به اندازۀ آرایه وجود

داشته باشد چه اتفاقی می افتد؟

چه تفاوتی وجود دارد؟ typedef و دستور enum 6‐ بین دستور

7‐ اگر بخواهیم یک آرایه را به یک تابع ارسال کنیم، چرا باید اندازۀ همه ابعاد به غیر

از بعد اول در فهرست پارامترهای تابع ذکر شود؟

تمرین های برنامه نویسی

6 را طوری تغییر دهید که برای هر ورودی، یک خط درخواست و ‐ 1‐ برنامۀ مثال 1

برای هر خروجی، یک خط اعلان چاپ شود. مانند تصویر زیر:

Enter 5 numbers

a[0]: 11.11

a[1]: 33.33

a[2]: 55.55

a[3]: 77.77

a[4]: 99.99

In reverse order, they are:

a[4] = 99.99

a[3] = 77.77

a[2] = 55.55

a[1] = 33.33

a[0] = 11.11

 

فصل ششم / آرایه ها 209

6 را طوزی تغییر دهید که آرایه را به طور معکو س پر کند و سپس ‐ 2‐ برنامۀ مثال 1

اعضای آرایه را به همان ترتیبی که ذخیره شده اند چاپ کند. مانند تصویر زیر:

Enter 5 numbers:

a[4]: 55.55

a[3]: 66.66

a[2]: 77.77

a[1]: 88.88

a[0]: 99.99

In reverse order, they are:

a[0] = 99.99

a[1] = 88.88

a[2] = 77.77

a[3] = 66.66

a[4] = 55.55

عنصر n 6 را طوری تغییر دهید که با استفاده از تابع زیر، میانگین ‐ 3‐ برنامۀ مثال 9

اول آرایه را برگرداند:

float ave(int[] a, int n);

// returns the average of the first n elements of a[]

6 را طوری تغییر دهید که خود آرایه، مجموع آن و میانگین آن را ‐ 4‐ برنامۀ مثال 10

6 نگاه کنید) ‐ 6 و مسالۀ 3 ‐ چاپ کند. ( به مثال 9

6 را طوری تغییر دهید که برای هر عنصر آرایه، آدرس حافظۀ آن ‐ 5‐ برنامۀ مثال 11

a+ و 2 a+ و 1 a از عبارت های ،a و محتویات آن را چا پ کند. برای آرایه ای به نام

و... را بدست آورید و از عبارت های a[ و [ 1 a[ و... استفاده کنید تا آدرس های [ 0

و... استفاده کنید تا محتویا ت این مکان ها را بدس ت *(a+ و ( 2 *(a+ و ( 1 *a

اعلان کنید تا مقادیر آرایه وقتی unsigned int a[] آورید. آرایه را به صورت

درج می شوند، به شکل اعداد صحیح چاپ شوند. cout داخل جریان

6 را طور ی تغییر دهید که به جای اولین محل قرار گرفتن یک ‐ 6‐ برنامۀ مثال 12

عنصر مفروض، آخرین محل قرار گرفتن آن را در آرایه برگرداند.

]

210 برنامه سازی پیشرفته

را برگرداند اگر و فقط true 6 را طوری تغییر دهید که مقدار ‐ 7‐ برنامۀ مثال 15

اگر آرایه غیر صعودی باشد.

عنصر اول آرایه، مقدار n 8‐ تابع زیر را نوشته و آزمایش کنید. این تابع در بین

کمینه (مینیمم ) را برمی گرداند.

float min(float a[], int n);

9‐ تابع زیر را نوشته و آزمایش کنید. این تابع، ایندکس اولین مقدار کمینه(مینیمم) را

عنصر اول آرایۀ مفروض برمی گرداند. n از میان

int minIndex(float a[], int n);

n 10 ‐ تابع زیر را نوشته و آزمایش کنید. این تابع مقدار کمینه و بیشینه را در بین

عنصر اول آرایۀ مفروض با استفاده از پارامترهای ارجاعی اش برمی گرداند.

void getEXtremes(float& min, float& max, float a[], int n);

11 ‐ تابع زیر را نوشته و آزمایش کنید. این تابع بزر گترین مقدار و دومین بزرگ ترین

عنصر اول آرایۀ مفروض با استفاده n مقدار (این دو می توانند مساوی باشند) را از بین

از پارامترهای ارجاعی اش برمی گرداند.

void largest(float& max1, float& max2, float a[], int n);

12 ‐تابع زیر که یک مقدار را از آرایه حذف می کند، نوشته و آزمایش کنید:

void remove(float a[], int& n, int i);

را حذف می کند که تمام عناصر بعد از آن را یک a[i] تابع بالا به این روش عنصر

را کاهش می دهد. n پله به عقب می کشد و

13 ‐ تابع زیر را نوشته و آزمایش کنید. این تابع سعی می کند یک عنصر را از آرایه

حذف کند:

bool removeFirst(float a[], int& n, float x);

 

 

فصل ششم / آرایه ها 211

پیدا شود آنگاه x می گردد. اگر x به دنبال a[] عنصر اول آرایۀ n این تابع در بین

در آن واقع شده، حذف می شود و تمام عناصر بعدی یک پله به x اولین محلی که

نیز بازگشت true نیز یک واحد کاهش می یابد و مقدار n عقب کشیده می شوند و

پیدا نشود، آرایه x داده می شود تا مشخص کند که حذف موفقیت آمیز بوده است. اگر

برگردانده می شود. (به مسالۀ 12 نگاه کنید) false بدون تغییر می ماند و مقدار

14 ‐ تابع زیر را نوشته و آزمایش کنید. این تابع عناصری را از آرایه حذف می کند:

void removeAll(float a[], int& n, float x);

را n عنصر اول آرایه حذف می کند و n برابرند را از x تابع مذکور همۀ عناصری که با

به تعداد عناصر حذف شده، کاهش می دهد. (به مسالۀ 13 نگاه کنید)

15 ‐ تابع زیر را نوشت ه و آزمایش کنید:

void rotate(int a[], int n, int k);

موقعیت به k منفی باشد k موقعیت به راست (یا اگر k، را a عنصر اول آرایه n تابع

عنصر آخر به شروع آرایه منتقل می شوند. برای مثال ، فراخوانی k . چپ ) منتقل می کند

آرایۀ { 22,33,44,55,66,77,88,99 } را به آرایۀ rotate(a,8,3)

77,88,99,22,33,44,55,66 } تبدیل می کند. بدیهی است که فراخوانی }

تاثیر مشابهی خواهد داشت. rotate(a,8,-5)

16 ‐ تابع زیر را نوشته و آزمایش کنید:

void append(int a[], int m, int b[], int n);

الحاق می کند. فرض a عنصر او ل آرایۀ m را به انتهای b عنصر اول آرایۀ n تابع بالا

a عنصر جا دارد. برای مثال اگر آرایۀ m+n حداقل به اندازۀ a بر این است که آرایۀ

نیز برابر با b برابر با { 22,33,44,55,66,77,88,99 } و آرایۀ

append(a,5,b, 20,30,40,50,60,70,80 } باشد، آنگاه فراخوانی ( 3 }

به شکل { 22,33,44,55,66,20,30,40 } تغییر a باعث می شود که آرای ۀ

تغییر نمی کند. b کند. توجه داشته باشید که آرایۀ

 

 

212 برنامه سازی پیشرفته

17 ‐ تابع زیر را نوشته و آزمایش کنید:

void insert(float a[], int& n, float x)

را n را درج می کند و x عنصری است مقدار n که a این تابع درون آرایۀ مرتب

افزایش می دهد. عنصر جدید در مکانی درج می شود که ترتیب آرایه حفظ شود. به این

منظور، عناصر باید به جلو منتقل شوند تا برای عضو جدید، جا باز شود. (به همین

عنصر داشته باشد) n+ دلیل آرایه باید حداقل 1

18 ‐ تابع زیر را نوشت ه و آزمایش کنید:

int frequency(float a[], int n, int x);

عنصر اول آرایه ظاهر م یشود را شمرد ه و n در میان x این تابع دفعاتی را که عنصر

برمی گرداند. a در x نتیجه را به عنوان تعداد تکرار

19 ‐ تابع زیر را نوشت ه و آزمایش کنید:

void reverse(int a[] , int n);

عنصر اول آرایه را معکوس می کند. برای مثال فراخوانی n تابع فوق

آرایۀ { 22,33,44,55,66 } را ب ه reverse(a,5)

66,55,44,33,22 } تبدیل می کند. }

20 ‐ تابع زیر را نوشت ه و آزمایش کنید:

void add(float a[], int n, float b[]);

a اضافه می کند. برای مثال اگر a عنصر متناظر در n را ب ه b عنصر او ل n تابع مذکور

نیز برابر با b برابر با { 2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9 } باشد و

add(a,5,b); 6.0,5.0,4.0,3.0,2.0,1.0 } باشد، آنگاه فراخوانی }

{ به { 8.2,8.3,8.4,8.5,8.6,7.7,8.8,9.9 a باعث می شود که آرای ۀ

تبدیل شود.

21 ‐ تابع زیر را نوشت ه و آزمایش کنید:

float outerProduct(float p[][3], float a[], float b[]);

فصل ششم / آرایه ها 213

را برمی گرداند. b با سه عنصر اول a تابع بالا، حاصل ضرب بیرونی سه عنصر اول

{2.0,- برابر با { 1.0,0.0 b برابر با { 2.2,3.3,4.4 } و a برای مثال اگر

به p باعث می شود آرای ۀ دو بعدی outerProduct(p,a,b); باشد، فراخوانی

صورت زیر تبدیل شود:

4.4 -2.2 0.0

6.6 -3.3 0.0

8.8 -4.4 0.0

است . b[j] با a[i] حاصل ضرب p[i][j] عنصر

22 ‐ تابعی را نوشته و آزمایش کنید که عناصر یک آرایۀ دوبعدی مربعی را 90

درجه در جهت عقربه های ساعت بچرخاند. برای مثال این تابع باید آرایۀ :

11 22 33

44 55 66

77 88 99

را به آرایۀ

77 44 11

88 55 22

99 66 33

تبدیل می کند.

 

فصل هفتم

« اشاره گرها 1 و ارجاع ها 2 »

7 مقدمه ‐1

حافظۀ رایانه را می توان به صورت یک آرایۀ بزرگ در

در RAM نظر گرفت. برای مثال رایانه ای با 256 مگابایت

حقیقت حاوی آرایه ای به اندازۀ 268،435،456

228 ) خانه است که اندازۀ هر خانه یک بایت است. این =)

خانه ها دارای ایندکس صفر تا 268،435،455 هستند.

به ایندکس هر بایت، آدرس حافظۀ آن می گویند. آدرس های

حافظه را با اعداد شانزده دهی نشان می دهند. پس رایانۀ مذکور

0 می باشد. هر وقت که x0fffffff 0 تا x دارای محدوده آدرس 00000000

نوع » : متغیری را اعلان می کنیم، سه ویژگی اساسی به آن متغیر نسبت داده می شود

و n و نام int نوع int n; آن. مثلا اعلان « آدرس حافظه » و « نام متغیر » و « متغیر

در آن قرار می گیرد را به یکدیگر مرتبط n آدرس چند خانه از حافظه که مقدار

را n 0 است. بنابراین می توانیم x0050cdc می سازد. فرض کنید آدرس این متغیر 0

0x00000000

0x00000001

0x00000002

0x00000003

0x00000004

0x00000005

0x00000006

0x00000007

0x0064fdc5

0x0064fdc6

0x0064fdc7

0x0064fdc8

0x0ffffffe

 

0x0fffffff

1 – Pointers 2 – References

 

   + MOHSEN GHASEMI - ۱٢:٤٤ ‎ق.ظ ; ۱۳۸٩/٥/٢۱