زبان برنامه نویسی سی/آرایه
آرایه
[ویرایش]آرایه یا Array در برنامهنویسی به نحوه ای از ایجاد دادهها ( عموماً متغیرها ) میگویند که به تعداد معین از نوع داده تعیین شده ، توسط برنامهنویس ، خانههایی را بر روی حافظه به صورت متوالی ایجاد مینماید ( که به هر یک از آنها عنصر آن آرایه میگوئیم ) . تفاوت آرایه با ساختمان یا اجتماع ، بر روی حافظه اینست که فضای خالی در بین خانهها ایجاد نمیشود و از طرفی ایجاد آرایه بسیار راحتتر از تعریف ساختمان یا اجتماع میباشد . شکل کلی تعریف آرایه به این صورت میباشد :
data-type name[number] = {value, value, ...};
ابتدا نوع داده خود را تعیین مینمائید که میتواند یک متغیر از نوع پایه یا یک نمونه از ساختمان یا اجتماع یا هر نوع داده دیگری باشد ، سپس نام داده خود را می نویسید و بدون فاصله در مقابل نام داده خود ، یک جفت کروشه به صورت باز و بسته مینویسیم که در داخل آن یک عدد ، قرار میگیرد که نشان دهنده تعداد آرایه ساخته شده و قابل استفاده برای برنامهنویس میباشد ؛ به عدد نوشته شده در داخل کروشهها که تعداد عناصر آرایه را تعیین مینماید اندیس ( Index یا Subscript ) گفته می شود
توجه : اندیس تعیین شده توسط شما هرگز نباید 0 باشد
خانه های متوالی و پشت سرهم ذخیره شده برای شما از عنصر اول که همان اندیس 0 آرایه می باشد ، آغاز میگردد و تا عددی که شما تعیین کردهاید ، منهای یکی ادامه مییابد . به عنصر آخر آرایه همواره مقدار تهی یا همان NULL تخصیص مییابد تا مشخص شود که آرایه به پایان رسیده . بنابراین مثلاً شما می نویسید :
int a[5];
با تعریف بالا ۶ متغیر از نوع صحیح ایجاد میشود ( ۶ عنصر ) که شما از [0]a را مقدار می دهید تا [4]a که می شود ۵ عنصر از متغیر صحیح ( ۱۰ بایت برای شما که بر روی ۱۰ آفست از سگمنتهای حافظه ذخیره میشود - در سیستم های ۳۲ بیتی قدیمی - و البته ۲۰ بایت در ۲۰ آفست از سگمنتهای حافظه در سیستمهای جدیدتر ) اما [5]a توسط کامپایلر مقداری تهی میگیرد که شما قادر به استفاده از آن نیستید ، پس به خوبی به یاد داشته باشید که زمانی که شما عدد 5 را به عنوان اندیس آرایه می نویسید ، ۶ داده از داده مشخص شده ایجاد میشود که از شماره 0 تا یکی مانده به اندیسِ نوشته شده در اختیار شما قرار میگیرد تا مقدار دهی گردد و آخرین متغیر یا داده که همان شماره اندیس نوشته شده میباشد ، با استاندارد زبان سی توسط کامپایلر مقدار تهی می گیرد . بنابراین آرایه بالا ۱۲ بایت به صورت استاندارد برای سیستم های ۳۲ بیتی قدیمی و ۲۴ بایت در سیستمهای جدیدتر بر روی حافظه موقت ، فضا اشغال مینماید
به جای نوشتن عدد به عنوان اندیس ، می توان از نام یک متغیر عددی که تعریف شده است ( مقدار آن تعیین شده ) استفاده نمود ، برای این منظور به جای عدد داخل کروشهها ، نام متغیر عددی خود را مینویسید . اما آنچه که بعد از علامت تساوی در بین آکولادها قرار گرفته و value نوشته گردیده ، مقدار و موجودیهای اختصاص داده شده توسط شما برای هر یک از عنصر های آرایه میباشند که توسط علامت کالن ( , ) از یکدیگر جدا میشوند . تعداد مقادیری که مینویسید تا به آرایه اختصاص یابد نباید بیشتر از اندیس نوشته شده توسط شما باشد ، اما اگر کمتر باشد ، کامپایلر طبق استاندارد ، مقدار 0 را برای عنصر یا عنصرهای متناظر در نظر میگیرد . مقادیر به صورت متوالی از چپ به راست به عناصر آرایه ( به ترتیب از 0 تا عنصر آخر ) اختصاص مییابند( بنابراین شما با روش ابتدایی که ذکر نوشته شد نمی توانید یک یا چند عنصر را در بین عنصرهای دیگر از قلم بیاندازید و فقط عنصرهای مورد نظر خود را مقدار دهی کنید )
مثال :
int a[5] = {1, 6, 8, 12};
مثال ۲ :
int i = 7;
;int b[i]
b[i] = {2, 4, 6, 8, 10, 12, 14}
در مثال اول [0]a برابر با مقدار 1 می باشد و [3]a برابر با 12 و [4]a که مقداری ندارد ، توسط کامپایلر مقدار 0 میگیرد و همان طور که گفته شد به [5]a مقدار NULL اختصاص خواهد یافت . در مثال دوم یک متغیر از نوع صحیح با مقدار 7 تعریف نمودیم ، سپس یک آرایه با نام b از نوع صحیح با اندیس i اعلان کردیم که 7 عنصر دارد ( چون مقدار i مقدار ۷ است ) و سپس b را با مقدار دهی تعریف کردیم . همچنین جهت دسترسی به هر یک از عنصرهای آرایه ، شماره آن را مینویسیم و به آن مقدار میدهیم یا اگر مقداری دادهایم مقدارش را عوض میکنیم یا با نوشتن شماره آن و قرار دادن مقدار آن بر روی یک داده دیگر و یا به عنوان آرگومان یک تابع مقدار آن را فرا میخوانیم . فراموش نکنید که تمام عنصرهایی که هنوز مقداری نگرفتهاند به صورت پیش فرض دارای مقدار 0 خواهند بود ( تا زمانی که به آنها مقداری تخصیص بدهیم )
مثال :
int a[6];
a[4] = 18;
اینکه یک آرایه بدون اندیس نوشته شده و مقدار دهی شود ، توسط برخی کامپایلر ها پشتیبانی میشود و برخی دیگر آن را پشتیبانی نمیکنند و از شما خطا خواهند گرفت . اما در مورد کاراکتر ها مسئله متفاوت است ، طبق استاندارد هر متغیر از نوع کاراکتر میتواند بدون اندیس به صورت آرایه تعریف شود . اما طبق استاندارد ، یک آرایه ، تنها زمانی می تواند دارای اندیس نباشد ( به غیر از نبودن از نوع کاراکتر ) که یا :
- پارامتر یک تابع باشد ( که در این صورت ، کامپایلر به صورت خودکار ، آن را به اشارهگری از نوع داده آرایه ، تبدیل مینماید )
- به صورت خارجی ( با کلیدواژه extern ) اعلان گردد که در این صورت باید در جای دیگری از برنامه تعریف شده باشد ( عموماً در یک متن منبع دیگری از پروژه )
- آرایه در جای دیگری در همان متن منبع برنامه مورد نظر ، تعریف گردد
در غیر این صورت ، کامپایلر از ما خطا خواهد گرفت !
گفتیم که آرایههای کاراکتری میتوانند بدون اندیس نوشته شده و مقدار بگیرند . برای مقدار دهی آرایههای کاراکتری می توانیم از روش معمول استفاده نموده و تک تک کاراکترهای مورد نظر را با شیوه استاندارد مقداردهی ، کاراکتر بنویسیم ( یعنی با استفاده از علامت کوت ' ) یا از روش دیگر آن که رایج بوده و قابل استفاده است یعنی قرار دادن یک رشته به عنوان مقدار آرایه کاراکتری استفاده کنیم ، به مثال ذیل توجه نمائید :
char deb[] = "this is a string";
معمولاً بهتر است برای آرایههای کاراکتری از همین شیوه استفاده نمائید ، چرا که در صورت نوشتن اندیس باید حتماً دقت کنید که تعداد کاراکترهای نوشته شده توسط شما از اندیس تعیین شده بزرگتر نباشد . حال به مثالی از تعریف یک نمونه از ساختمان به صورت آرایه بپردازیم :
struct point
{
int x, y;
} point_array[2];
point_array[0].x = 3;
نمونهای که از ساختمان point ایجاد شد ، خود یک آرایه دو عنصری است . بنابراین برای استفاده از آن باید ابتدا نمونه به همراه اندیسی که عنصر آن را میخواهیم مقدار دهی نمائیم بنویسیم و سپس به وسیله عملگر نقطه « . » به عضو ساختمان دسترسی یافته و از آن بهره جوئیم
آرایه های چند بعدی
آرایهها را میتوان به صورت چند بعدی نیز تعریف نمود . استفاده از آن در کار با ماتریسها کاملاً ملموس میباشد . برای این کار به جای تعیین یک اندیس ، چند اندیس ( به هر تعداد ابعادی که مورد نظر ماست ) تعیین مینمائیم . مثال :
float cib[8][7];
در مثال بالا یک متغیر اعشاری با 8 عنصر 7 عنصری اعلان نمودیم ( ۸ دسته ۷ تایی ) . آرایه ها را از آخرین اندیس ( سمت راستترین ) به ترتیب یک به یک پر میکنید و سپس به اندیس قبلتر میرسید ( سمت چپتر ) که با اندیس 0 برای اندیسهای رو به رو ( بعدتر ، راستتر ) شروع میشود تا اندیس قبلتر ( چپتر ) پر شود و پس از رسیدن به آخرین عنصر مجاز اندیس قبلتر ( چپتر ) ، اندیسهای رو به رویی ( مقابل قبلی ) یک به یک اضافه شوند تا به آخرین عنصر مجاز اندیس سمت راستیتر برسید و سپس به سمت ابتداییتر ( چپتر ) بروید و الی آخر ، تا در نهایت آخرین شماره اندیسهای مجاز را بنویسید و عنصرهای خود را مقدار بدهید . اگر مثلاً یک متغیر long را بدین صورت اعلان کنیم :
long kid[5][8][7];
عناصر متغیر kid بدین ترتیب خوانده شده و باید مقدار دهی گردند :
kid[0][0][0]
kid[0][0][1]
kid[0][0][2]
.
.
.
kid[0][0][6]
.
.
.
kid[0][1][0]
kid[0][2][0]
kid[0][7][0]
.
.
.
kide[0][7][1]
.
.
kid[0][7][6]
kid[1][0][0]
kid[2][0][0]
.
.
kid[4][0][0]
.
.
kid[4][1][0]
.
.
kid[4][7][0]
.
.
kid[4][7][1]
.
.
kid[4][7][6]
در مقدار دهی آرایههای چند بعدی نیز می توانیم داخل یک آکولاد مقادیر خود را بنویسیم که توسط کامپایلر از اولین عنصر آرایه چند بعدی ما تا آخرین عنصر به ترتیب مقدار خواهند گرفت ، اما این روش توسط برخی کامپایلرها مورد حمایت قرار نمیگیرد . بنابراین باید از روش استاندارد آن که استفاده از آکولادهای تو در تو می باشد استفاده نمود
مثال :
int two_dimensions[2][5] = {{1, 2, 5, 8, 3}, {7, 6, 5, 12, 10}};
همان طور که میبینید دو دسته پنج تایی از اعداد را به عنوان مقدار به two_dimensions اختصاص دادهایم . حال اگر برای متغیر آرایهای kid ( که در مثال قبل نوشتیم ) میخواستیم مقدار بدهیم باید ۵ تا دسته از ۸ دسته ۷ تایی را در آکولادهای تو در تو مقدار میدادیم
آرایه ها و اشاره گر ها
مبحث بعدی ما در این کتاب ، مبحث اشارهگر میباشد . اشارهگرها دادههایی هستند که به داده دیگری اشاره داده میشوند تا بتوانند به صورت مستقیم آنچه که بر روی حافظه آن داده به عنوان مقدار و موجودی آن قرار گرفته را در دسترس ما قرار دهند و امکانات زیادی برای ما در برنامهنویسی فراهم میآورد که در مبحث بعدی به آن میپردازیم . اما آرایهها ارتباط تنگاتنگی با اشارهگرها دارند . آرایهها در زبان C به صورت اشارهگر تعریف میشوند و از این روی استفاده از آرایهها به وسیله اشارهگرها بسیار راحتتر است و در نوشتن برنامه های پیچیدهتر و تو در توی ما لازمه استفاده بهینه از آرایهها میباشد که اگر کتاب حاضر را همراهی کنید ، به این مبحث مهم میپردازیم تا به نقطه تداخل اشارهگرها با آرایهها و روش دیگر دسترسی به آرایهها برسیم