مقدمات زبان C

مقدمات زبان C

زبان C در سال 1972 توسط دنيس ريچي طراحي شد. اين زبان تكامل يافته زبان BCPL مي‌باشد كه طراح آن مارتين ريچاردز است. زبان BCPL از زبان B كه طراح آن كن‌تامپسون مي‌باشد، نتيجه شده است. علت نامگذاري C اين است كه بعد از B طراحي شد.

كساني كه تا حدودي با زبانهاي برنامه‌سازي آشنايي دارند، مي‌دانند كه زبان ديگري به نام زبان C++ وجود دارد و آن از C ناشي شده است. C++ علاوه بر ويژگيهاي جديدي دارد كه در C موجود نيست. در كتاب حاضر، زبان برنامه‌نويسي C مورد بررسي قرار مي‌گيرد. در اين فصل، بعضي از عناصر زبان C را مورد بحث قرار مي‌دهيم. بعضي از ويژگيهاي زبان C عبارت‌اند از:

  • زبان C يك زبان مياني است. زبانهاي برنامه‌سازي را مي‌توان به سه دسته تقسيم كرد: زبانهاي سطح بالا، زبانهاي مياني، زبانهاي سطح پايين (جدول 1). علت مياني بودن زبان C اين است كه از طرفي، همانند زبان سطح پاييني مثل اسمبلي، قادر است مستقيماً به حافظه دستيابي داشته باشد و با مفاهيم بيت، بايت و آدرس كار كند و از طرف ديگر، برنامه‌هاي اين زبان، همچون زبانهاي سطح بالايي مثل پاسكال، از قابليت خوانايي بالايي برخوردارند. به عبارت ديگر، دستور العملهاي اين زبان، به زبان محاوره‌اي انسان نزديك است، كه اين ويژگي، مربوط به زبانهاي سطح بالاست.
  • زبان C، يك زبان ساخت يافته است. در اين زبان با استفاده از حلقه‌هاي تكراري مثل while، for و do while مي‌توان برنامه‌هايي نوشت كه قابليت خوانايي و درك آنها بالا باشد. بعضي از زبانهاي ساخت يافته در جدول 2 آمده‌اند.

 

جدول 1: سطوح زبانهاي برنامه‌سازي

زبانهاي سطح بالا زبانهاي مياني زبانهاي سطح پايين
پاسكال   (Pascal)اِدا   (Ada)ماجولا-2   (Modula_2)كوبول   (Cobol)بيسيك   (Basic) جاوا   (Java)فورث   (Forth)(C++),C ماكرواسمبلر    (Macro-Assembler)اسمبلر (Assembeler)

جدول 2: زبانها از نظر ساخت‌يافتگي.

زبانهاي ساخت‌يافته زبانهاي غيرساخت‌يافته
پاسكالاِدا(C++),Cماجولا-2جاوا فرترن   (Fortran)بيسيك   (Basic)كوبول   (Cobol)
  • زبان C، قابل انعطاف و بسيار قدرتمند است. در اين زبان، هيچ محدوديتي براي برنامه‌نويس وجود ندارد. هر آنچه را كه فكر مي‌كنيد، مي‌توانيد در اين زبان پياده‌سازي كنيد.
  • C، زبان برنامه‌نويسي سيستم است. برنامه‌هاي سيستم، برنامه‌هايي هستند كه امكان بهره‌برداري از سخت افزار و ساير نرم‌افزارها را فراهم مي‌كنند. بعضي از برنامه‌هاي سيستم عبارت‌اند از: سيستم عامل، مفسر (interpreter)، كامپايلر، ويراستارها، واژه پردازها، مديريت بانكهاي اطلاعاتي و اسمبلر.
  • ارتباط تنگاتنگي بين C و زبان اسمبلي وجود دارد و بدين ترتيب مي‌توان از تمام قابليتهاي اسمبلي در زبان C استفاده كرد.
  • C، زبان قابل حمل است. معناي قابليت حمل اين است كه برنامه‌هايي كه به زبان C، در يك نوع كامپيوتر (مثل آي.بي.ام) نوشته شدند، بدون انجام تغييرات يا انجام تغييرات اندك، در كامپيوترهاي ديگر (مثل VAX و DEC) قابل استفاده‌اند.
  • C، زبان كوچكي است. تعداد كلمات كليدي اين زبان انگشت شمار است (30 كلمه كليدي جدول 3). تصور نشود كه هر چه تعداد كلمات كليدي زبان بيشتر باشد، آن زبان قدرتمند است.

جدول 3: كلمات كليدي زبان C.

struct int double auto
switch long else break
typedef register enum case
union return extern char
unsigned short float const
void signed for continue
volatile sizeof goto default
while static if do

به عنوان مثال، زبان بيسيك در حدود 150 كلمه كليدي دارد ولي قدرت زبان C به مراتب بيشتر از زبان بيسيك است. توجه داشته باشيد كه بعضي از كامپايلرهاي C، علاوه بر اين 32 كلمه كليدي، كلمات ديگري را به زبان اضافه كرده‌اند (جدول 4).

جدول 4: كلمات كليدي C كه بعضي از كامپايلرها اضافه كردند.

_es _ds _cs asm
huge far cdecl _ss
d pascal near interrupt
  • C++ كه تكامل يافته زبان C است، داراي ويژگي شيءگرا (Object-Oriented) است. برنامه نويسي شيءگرا، متد جديدي در برنامه‌نويسي است كه بر اشياي موجود در برنامه تاكيد دارد.
  • C نسبت به حروف حساس است (case sensitive). يعني در اين زبان، بين حروف كوچك و بزرگ تفاوت است و تمام كلمات كليدي اين زبان با حروف كوچك نوشته مي‌شوند. به عنوان مثال، while يك كلمه كليدي است ولي WHILE اينطو نيست. توصيه مي‌شود كه تمام برنامه‌هاي C با حروف كوچك نوشته شوند.
  • دستور العملهاي برنامه C داراي ويژگيهاي زير هستند:
  1. هر دستور زبان C به ; ختم مي‌شود.
  2. حداكثر طول يك دستور، 255 كاراكتر است.
  3. هر دستور مي‌تواند در يك يا چند سطر ادامه داشته باشد.
  4. در هر سطر مي‌توان چند دستور را تايپ كرد (اين كار، توصيه نمي‌شود)
  5. توضيحات مي‌توانند در بين /* و */ قرار گيرند و يا بعد از // ظاهر شوند:

/* This is a samble comment */

// This is a samble comment

انواع داده‌ها

هدف از برنامه‌نويسي، ورود داده‌ها به كامپيوتر، پردازش داده‌ها و استخراج نتايج است. لذا، داده‌ها نقش مهمي را در برنامه‌نويسي ايفا مي‌كنند. يكي از جنبه‌هاي زبانهاي برنامه‌سازي كه بايد دقيقاً مورد بررسي قرار گيرد، انواع داده‌هايي است كه آن زبان با آنها سروكار دارد. در زبان C، 5نوع داده وجود دارند كه عبارتند از: char، int، float، double و void. نوع char براي ذخيره داده‌هاي كاراكتري مثل ‘a’ ، ‘b’ ، ‘x’ به كار مي‌رود. نوع int براي ذخيره اعداد صحيح مثل 125، 430، 1650 به كار مي‌رود. نوع float براي ذخيره اعداد اعشاري مثل 15.5، 175.5 و 1250.25 به كار مي‌رود و نوع double براي ذخيره اعداد اعشاري كه بزرگتر از float باشند مورد استفاده واقع مي‌شود. نوع void را در جاي مناسبي تشريح خواهيم كرد. هر يك از انواع داده‌هاي char، int، float، double مقاديري را مي‌پذيرند كه ممكن است از پردازنده‌اي (CPU) به پردازنده ديگر متفاوت باشد. به عنوان مثال، طول نوع int در محيطهاي 16 بيتي مثل DOS يا ويندوز 1/3، شانزده بيت و در محيطهاي 32 بيتي مثل ويندوز NT، سي و دو بيت است. بنابراين، اگر برنامه‌هايي مي‌نويسيد كه بايد در محيطهاي مختلف اجرا شوند، سعي كنيد از كوچكترين مقدار انواع در C استفاده نماييد .

با استفاده از كلماتي مثل signed (با علامت)، unsigned (بدون علامت)، long و short مي‌توان انواع جديدي را ايجاد كرد. كلمات signed، short، long و unsigned را مي‌توان با انواع int به كار برد. نوع char را مي‌توان با signed و unsigned به كار برد. Long به همراه double نيز قابل استفاده است. چون داده‌هاي نوع int با علامت هستند، كاربرد signed با آنها، بي‌مورد است. انواع مختلف داده‌ها و مقاديري را كه هر يك از انواع پشتيباني مي‌كنند در جدول5 آمده است.

جدول 5: انواع داده‌ها و مقادير قابل قبول آنها.

نوع اندازه به بيت بازه قابل قبول
charunsigned charsigned charintunsigned intsigned intshort intunsigned short intsigned short intlong intsigned long intunsigned intfloatdoublelong double 88816 يا 3216 يا 3216 يا 32161616323232326480 127- تا 1270 تا 255127- تا 12732767- تا 327670 تا 6553532767- تا 3276732767- تا 327670 تا 6553532767- تا 327672147483647- تا 21474836472147483647- تا 21474836470 تا 42949672957 رقم دقت (ارقام بعد از اعشار) (تقريباً 38-10 تا 1038)15 رقم دقت (تقريباً 38-10 تا 1038)19 رقم دقت (تقريباً 4932-10 تا 104932)

 

متغيرها

متغيرها نامي براي كلمات حافظه‌اند كه داده‌ها در آنها قرار مي‌گيرند و محتويات آنها ممكن است در طول اجراي برنامه، تغيير كند. برايث مراجعه به متغيرها از نامشان استفاده مي‌شود. لذا متغيرها امكان نامگذاري براي كلمات حافظه را فراهم مي‌كنند. براي نامگذاري متغيرها مي‌توان از تركيبي از حروف a تا z يا A تا Z، ارقام و خط ربط (ـ) استفاده كرد، به طوري كه اولين كاراكتر آنها رقم نباشد. نام متغير مي‌تواند با هر طولي باشد ولي 31 كاراكتر اول آن مورد استفاده قرار مي‌گيرد. بعضي از اسامي مجاز و غير مجاز براي متغيرها در جدول 6 آمده‌اند.

جدول 6: بعضي از اسامي مجاز و غير مجاز براي متغيرها

اسامي مجاز اسامي غيرمجاز
counttest23sumS_1 1testhigh!theregrade.1.pcx

تعريف متغيرها

همانطور كه گفته شد، متغيرها محل ذخيره داده‌ها هستند و چون داده‌ها داراي نوع‌اند، متغيرها نيز بايد داراي نوع باشند. به عبارت ديگر، متغيرهاي فاقد نوع، در C شناخته شده نيستند. قبل از به كارگرفتن متغيرها، بايد نوع آنها را مشخص كرد. نوع متغير، مقاديري را كه متغير مي‌تواند بپذيرد و اعمالي را كه مي‌توانند بر روي آن مقادير انجام شوند، مشخص مي‌كند. تعيين نوع متغير را تعريف متغير گويند. براي تعيين نوع متغير، به صورت زير عمل مي‌شود:

; نام متغير     نوع داده

در اين شكل كلي، نوع داده، يكي از انواع موجود در جدول 5 است. براي تعيين نوع بيش از يك متغير، بايد آنها را با كاما از هم جدا كرد.

مقدار دادن به متغيرها

براي مقدار دادن به متغيرها به سه روش مي‌توان عمل كرد:

  1. هنگام تعريف (تعيين نوع) متغير
  2. پس از تعريف نوع متغير و با دستور انتساب (=)
  3. دستورات ورودي

در مورد تعيين نوع متغيرها اين نكته را به خاطر داشته باشيد: نوع متغيرها را بر حسب نياز تعريف كنيد. به عنوان مثال، اگر تعريف متغيري مثل x از نوع int، جوابگوي نياز شماست، آن را از نوع float ، double يا long int تعريف نكنيد.

تعريف ثوابت

ثوابت مقاديري هستند كه در برنامه وجود دارند ولي قابل تغيير نيستند. براي تعريف ثوابت به دو روش عمل مي‌شود: 1. استفاده از دستور #define و 2. استفاده از دستور const. براي تعريف ثوابت از طريق دستور #define به صورت زير عمل مي‌شود:

>مقدار< >نام ثابت<         #define

نامگذاري براي ثوابت از قانون نامگذاري براي متغيرها تبعيت مي‌كند. مقداري كه براي ثابت تعيين مي‌شود، نوع ثابت را نيز مشخص مي‌كند. دقت داشته باشيد كه در انتهاي دستور #define علامت ; قرار نمي‌گيرد. علتش اين است كه اين دستور، از دستورات پيش پردازنده (preprocessor) است، نه دستور زبان C. پيش پردازنده يك برنامه سيستم است كه قبل از ترجمه برنامه توسط كامپايلر، تغييراتي در آن ايجاد مي‌كند. پيش پردازنده مقدار ثابت را كه در دستور #define آمده است، به جاي نام ثابت در برنامه قرار مي‌دهدو اين دستور در زمان اجرا وجود ندارد. نام ديگر ثوابتي كه بدين صورت تعريف مي‌شوند، ماكرو (macro) است كه در ادامه كتاب مورد بحث قرار مي‌گيرد. براي تفكيك اينگونه ثوابت از متغيرهاي برنامه، بهتر است نام آنها با حروف بزرگ انتخاب شود.

عملگرها

عملگرها نمادهايي هستند كه اعمال خاصي را انجام مي‌دهند. به عنوان مثال، نماد ‘+’ عملگري است كه دو مقدار را با هم جمع مي‌كند (عمل جمع را انجام مي‌دهد). پس از تعريف متغيرها و مقدار دادن به آنها بايد بتوان عملياتي را روي آنها انجام داد. براي انجام اين عمليات بايد عملگرها استفاده كرد. عملگرها در زبان C به چند دسته تقسيم مي‌شوند: 1. عملگرهاي محاسباتي 2. عملگرهاي رابطه‌اي 3. عملگرهاي منطقي 4. عملگرهاي بيتي. عملگرها بر روي يك يا دو مقدار عمل مي‌كنند. مقاديري را كه عملگرها بر روي آنها عمل مي‌كنند، عملوند (operand) گويند. به عنوان مثال، در a+5، متغير a و مقدار 5 را عملوندهاي عملگرِ + گويند.

تعيين طول ميدان در تابع printf()

با استفاده ار امكانات ديگري كه در تابع printf() وجود دارد، مي‌توان مشخص كرد كه هر كدام از اطلاعاتي كه به خروجي مي‌روند، چند بايت از فضاي خروجي را اشغال كنند. فضايي را كه هر قلم اطلاعات اشغال مي‌كند، طول ميدان خروجي گويند. طول ميدان خروجي، معمولاً براي اعداد تعيين مي‌شود و در توليد منظم خروجي و جدول بندي اطلاعات بسيار مفيد است.

طول ميدان مقادير صحيح به صورت %wd بيان مي‌شود كه w طول ميدان را مشخص مي‌كند. اگر طول ميدان از تعداد ارقام عدد صحيح بيشتر باشد، عدد در سمت راست ميدان قرار مي‌گيرد و سمت چپ خالي مي‌ماند. اما اگر طول ميدان كمتر از تعداد ارقام عدد باشد، طول ميدان ناديده گرفته شده، تمام ارقام عدد در خروجي چاپ مي‌شود.

طول ميدان مقادير اعشاري به صورت %w.df بيان مي‌شود كه در آن، w كل طول ميدان و d تعداد ارقام اعشار است. به عنوان مثال، اگر براي چاپ عدد اعشاري، ميدان %5.2f را اعلام كنيم، 2 رقم براي قسمت اعشار (d=2)، دو رقم براي قسمت صحيح و يك محل به نقطه اعشار اختصاص مي‌يابد. اگر طول ميدان قسمت صحيح بيشتر از بخش صحيح عدد باشد، سمت چپ قسمت صحيح خالي باقي مي‌ماند. ولي اگر طول ميدان قسمت صحيح، كمتر از بخش صحيح عدد باشد، كل بخش صحيح در خروجي چاپ مي‌شود و طول ميدان ناديده گرفته مي‌شود. اگر طول ميدان قسمت اعشار، از تعداد ارقام اعشار بيشتر باشد، ارقام اعشاري در سمت چپ ميدان قرار گرفته، سمت راست ميدان خالي مي‌ماند. اما اگر طول ميدان قسمت اعشاري، از تعداد ارقام اعشاري كمتر باشد، قسمت اعشاري عدد، گرد مي‌شود. هنگام گرد كردن، چنانچه رقم حذف شده، بزرگتر يا مساوي 5 باشد، يك واحد به رقم سمت چپ آن اضافه مي‌شود.

ورود اطلاعات توسط تابع scanf()

اين تابع براي ورود اطلاعات از صفحه كليد مورد استفاده قرار مي‌گيرد و يك تابع همه منظوره در ورود داده‌هاست. الگوي اين تابع در فايل stdio.h قرار دارد. اين تابع، تمام انواع داده‌ها را مي‌تواند از ورودي بخواند و آنها را در حافظه ذخيره نمايد. اين تابع، چنانچه با موفقيت اجرا شود، تعداد متغيرهايي را كه از ورودي خوانده است برمي‌گرداند و در صورت بروز خطا، EOF توسط تابع برگردانده مي‌شود. EOF مقداري است كه بيانگر عدم اجراي صحيح تابع scanf() است (EOF با حروف بزرگ در نظر است). تابع scanf() به صورت زير به كار مي‌رود:

(>عبارت2< , >”عبارت1”<) scanf

>عبارت2< آدرس متغيرهايي است كه بايد ورودي خوانده شوند و>عبارت1< مشخص مي‌كند كه مقادير ورودي چگونه بايد خوانده شوند و ردمتغيرهايي كه آدرس آنها در>عبارت2< مشخص شده است قرار گيرند. >عبارت1< شامل سه نوع كاراكتر است:

  1. كاراكترهاي فرمت. اين كاراكترها تعيين مي‌كنند كه چه نوع اطلاعاتي بايد از ورودي خوانده شوند و با % شروع مي‌شوند. مثل %d كه براي خواندن اعداد صحيح از ورودي به كار مي‌رود. كاراكترهاي فرمت كه در تابع scanf() مورد استفاده قرار مي‌گيرند در جدول 7 آمده‌اند.
  2. كاراكترهاي فضاي خالي (space). وجود فضاي خالي در عبارت >عبارت1< موجب مي‌شود تا تابع scanf() از فضاي خالي موجود در ابتداي اطلاعات ورودي صرفنظر كند. كاراكترهاي جدول‌بندي (tab)، خط جديد (new line) و رد كننده صفحه (form feed) نيز به عنوان فضاي خالي محسوب مي‌شوند. حتي يك فضاي خالي در >عبارت1< موجب مي‌شود تا scanf() هر تعداد از فضاي خالي (و حتي صفرها) را كه در ابتداي اولين كاراكتر غير فضاي خالي (يا صفر) وجود دارد بخواند و از آنها رد شود (آنها را ذخيره نمي‌كند).
  3. كاراكترهاي غير از فضاي خالي و فرمت. وجود چنين كاراكتري موجب مي‌شود تا چنانچه همان كاراكتر در رشته ورودي وجود داشته باشد، آن را خوانده، از آن صرفنظر كند. به عنوان مثال، “%d,%d” موجب مي‌شود تا يك عدد صحيح خوانده شود، سپس يك كاما (,) خوانده و از آن صرفنظر شود و سپس عدد صحيح ديگري خوانده شود. اگر كاراكتر مشخص شده در >عبارت1< در رشته ورودي وجود نداشته باشد، تابع scanf() خاتمه مي‌يابد. براي خواندن و سپس صرفنظر از علامت % بايد %% را در عبارت >عبارت1< به كار ببريد.

وقتي دستور scanf() اجرا مي‌شود، منتظر مي‌ماند تا داده‌ها را از صفحه كليد دريافت نمايد. هنگام وارد كردن داده‌ها، هر يك از اقلام داده را با يك فاصله يا كاما (,) از هم جدا كنيد و پس از ورود داده‌ها، كليد Enter را فشار دهيد.

جدول 7: كاراكترهاي فرمت در تابع scanf()

كاراكتر

اطلاعاتي كه خوانده مي‌شوند
%c يك كاراكتر
%d يك عدد صحيح دهدهي
%I يك عدد صحيح دهدهي
%e عدد اعشاري مميز شناور
%f عدد اعشاري مميز شناور
%g عدد اعشاري مميز شناور
%o عدد مبناي 8
%x عدد مبناي 16
%p يك اشاره‌گر
%n مشخص كننده تعداد كاراكترهايي است كه تا %n از ورودي خوانده شده‌اند
%u عدد صحيح مثبت
%s رشته‌ها

ورودي و خروجي كاراكترها

همانطور كه ديديد، با استفاده از توابع scanf() و printf() مي‌توان ورودي و خروجي كاراكترها را انجام داد. ولي در C، توابع خاصي براي ورودي و خروجي كاراكترها منظور شد كه كاركردن با آنها راحت‌تر از توابع scanf() و printf() است. در اين بخش، تعدادي از آنها را مورد بررسي قرار مي‌دهيم.

خواندن كاراكتر با توابع getch() و getche()

اين توابع، كاراكتري را از ورودي خوانده در متغيري قرار مي‌دهند. اين توابع در فايل conio.h قرار دارند و نحوه كاربرد آنها به صورت زير است:

getch() ; = متغير

getche() ; = متغير

وقتي برنامه به اين دستورات مي‌رسد، منتظر مي‌ماند تا كليدي از صفحه كليد فشار داده شود. در اين صورت، كاراكتر معادل آن كليد، در متغير قرار مي‌گيرد. اين توابع به صورت زير نيز قالب استفاده‌اند.

getch () ;

getche()

در اين صورت، برنامه منتظر مي‌ماند تا كليدي از صفحه كليد فشار داده شود. پس از فشردن كليد، اجراي بقيه دستورات برنامه ادامه مي‌يابد.

تابع getch() عكس العملي در صفحه نمايش ندارد. يعني وقتي كليدي فشار داده شد، كاراكتر معادل آن در صفحه نمايش ظاهر نمي‌شود. در حالي كه تابع getche() پس از خواندن كاراكتر آن را در صفحه نمايش نيز ظاهر مي‌كند. ضمناً در اين توابع نياز به فشردن كليد Enter نيست. در حالي كه هنگام خواندن كاراكتر از طريق تابع scanf()، پس از وارد كردن كاراكتر، كليد Enter نيز بايد فشار داده شود.

خواندن كاراكتر با تابع getchar()

اين تابع نيز همانند توابع getch() و getche() براي خواندن كاراكتر از صفحه كليد به كار مي‌رود. اين تابع در فايل stdio.h قرار دارد و نحوه كاربرد آن به صورت زير است:

getchar() ; = متغير

توجه داشته باشيد كه در اين تابع، پس از ورود كاراكتر، بايد كليد Enter نيز فشار داده شود. اين تابع كاراكتر خوانده شده را در صفحه نمايش نيز ظاهر مي‌كند.

 

نوشتن كاراكتر با تابع putch()

اين تابع مي‌تواند يك كاراكتر يا يك متغير كاراكتري را در صفحه نمايش چاپ كند. اين تابع در فايل conio.h قرار دارد و به صورت زير به كار مي‌رود:

; (متغير)   putch

; (كاراكتر) putch

به عنوان مثال، دستور زير، كاراكتر ‘a’ را در خروجي چاپ مي‌كند:

putch (‘a’) ;

نوشتن كاراكتر با تابع putchar()

اين تابع براي نوشتن يك كاراكتر در صفحه نمايش به كار مي‌رود و در فايل stdio.h قرار دارد. نحوه كاربرد اين تابع به صورت زير است:

; (متغير)   putchar

; (‘كاراكتر’)   putchar

ساختارهاي تكرار

ساختارهاي تكرار، تحت شرايط خاصي، يك يا چند دستور را چندين بار اجرا مي‌كنند. به عنوان مثال، اگر بخواهيم تعداد 100 عدد را از ورودي بخوانيم و آنها را با هم جمع كنيم. بايد عمل خواندن عدد را 100 بار تكرار كنيم. ساختارهاي تكرار در زبانهاي برنامه‌سازي مختلف به شكلهاي گوناگوني مورد استفاده قرار مي‌گيرند. اين ساختارها را در زبان C مورد بررسي قرار مي‌دهيم.

 

ساختار تكرار for

ساختار تكرار for، يكي از امكانات ايجاد حلقه است و معمولاً در حالتي كه تعداد دفعات تكرار حلقه از قبل مشخص باشد، به كار مي‌رود. در اين ساختار، متغيري وجود دارد كه تعداد دفعات تكرار حلقه را كنترل مي‌كند. اين متغير را شمارنده يا انديس حلقه تكرار مي‌ناميم. انديس حلقه داراي يك مقدار اوليه است و در هر بار اجراي دستورات حلقه، مقداري به آن اضافه مي‌شود. اين مقدار را كه پس از هر بار اجراي حلقه به شمارنده اضافه مي‌شود، گام حركت گويند. گام حركت مي‌تواند عددي صحيح و اعشاري، مثبت يا منفي و يا كاراكتري باشد. يكي ديگر از اجزاي حلقه for، شرط حلقه است. شرط حلقه مشخص مي‌كند كه دستورات داخل حلقه تا كي بايد اجرا شوند. اگر اين شرط داراي ارزش درستي باشد، دستورات داخل حلقه اجرا مي‌شوند وگرنه كنترل برنامه از حلقه تكرار خارج مي‌شود. انديس حلقه تكرار مي‌تواند عددي منفي، مثبت، صحيح و يا اعشاري و كاراكتري باشد. دستور for را به دو شكل مي‌توان به كار برد:

{. (گام حركت ; شرط حلقه ; مقدار اوليه انديس حلقه)  for       .1

دستور 1

دستور 2

دستور n

}

{ (;;)   for       .2

دستور 1

دستور 2

دستور n

}

در هر يك از دو شيوه كاربرد، { مي‌تواند در سطر بعدي (زير for) قرار داشته باشد. ولي براي صرفه‌جويي در طول برنامه، در اين كتاب به همين شكل كه بيان شد استفاده مي‌شود. در هر يك از روشهاي كاربرد دستور for، چنانچه فقط يك دستور در حلقه وجود داشته باشد، نيازي به { و } نيست. در اين حالت، اين دستورات به صورت زير قابل استفاده‌اند:

(گام حركت ; شرط حلقه ; مقدار اوليه انديس حلقه)      for       .1

; دستور

(;;)       for       .2

; دستور

همانطور كه ملاحظه مي‌شود، در روش كاربرد دوم، for فاقد مقدار اوليه انديس حلقه، شرط حلقه و گام حركت است. اين دستور براي ايجاد حلقه تكرار بي‌نهايت (حلقه تكراري كه شرط پايان ندارد) مورد استفاده قرار مي‌گيرد. براي خاتمه دادن به اجراي حلقه تكرار بي‌نهايت، بايد كليد CTRL+BREAK را از صفحه كليد فشار داد.

براي آشنايي با مفاهيم توصيف شده، دستور ساده زير را در نظر بگيريد:

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

; (“%3d\n”,i)printf

در اين دستور ساده for، انديس حلقه تكرار (شمارنده) i و مقدار اوليه انديس حلقه برابر با صفر است. شرط حلقه i<5 است. يعني تا زماني i<5 باشد، اجراي دستور موجود در اين حلقه ادامه مي‌يابد وگرنه كنترل از حلقه تكرار خارج مي‌شود. گام حركت نيز يك است. يعني به ازاي هر بار اجراي دستور printf()، كه در داخل حلقه قرار دارد، يك واحد به i اضافه مي‌شود. شيوه اجراي اين دستور for را مي‌توان به صورت شكل 1 رسم كرد.

شكل 1: شيوه اجراي حلقه for.

ساختار تكرار while

ساختار تكرار while يكي ديگر از امكاناتي است كه براي تكرار اجراي دستورات به كار مي‌رود. اين ساختار به صورتهاي زير قابل استفاده است:

(شرط)   while  .1

; دستور

{ (شرط)           while  .2

دستور 1

دستور 2

.

.

.

دستور n

}

همانطور كه ملاحظه مي‌كنيد، وقتي دستورات تكرار شونده، بيش از يكي باشند، بايد آنها را در بين { و } قرار داد. پس از اينكه اجراي برنامه به اين دستور رسيد، شرط حلقه تست مي‌شود. اگر اين شرط داراي ارزش درستي باشد، دستورات حلقه اجرا مي‌شوند وگرنه كنترل برنامه از حلقه تكرار خارج مي‌شود. براي اينكه حلقه خاتمه پيدا كند، شرط حلقه بايد در داخل حلقه تكرار نقض شود. يعني بايد شرايطي در داخل حلقه فراهم شود تا شرط حلقه ارزش نادرستي پيدا كند و حلقه خاتمه يابد. اگر شرط حلقه هميشه درست باشد (هيچگاه نقض نشود)، حلقه تكرار بي‌نهايت ايجاد مي‌شود. در ادامه، مثالي را در اين مورد مشاهده خواهيد كرد.

ساختار تصميم if

ساختار if كه نام ديگرش، دستور انتقال كنترل شرطي است، شرطي را تست مي‌كند و در صورتي كه آن شري داراي ارزش درستي باشد، مجموعه‌اي از دستورات را اجرا مي‌كند. اين دستور به صورت زير به كار مي‌رود:

(شرط)               if         .1

; دستور

else

; دستور

{ (شرط)           if         .2

دستور 1

دستور 2

دستور n

}

{   eles

دستور n1

دستور n2

دستور n

}

در هر يك از روشهاي كاربرد، چنانچه شرط مورد بررسي درست باشد، دستور يا دستورات بعد از if وگرنه دستور يا دستورات بعد از eles اجرا مي‌شوند. اگر بيش از يك دستور بعد از if يا eles بيايند، آن دستورات بايد در بين { و } قرار گيرند. دستور if مي‌تواند فاقد قسمت eles باشد. در اين صورت، چنانچه شرط مورد بررسي، درست باشد، دستورات بعد از if اجرا مي‌شوند وگرنه بدون اجراي اين دستورات، كنترل اجراي برنامه از if خارج مي‌شود.

ساختار تصميم eles if

اگر بخواهيم از دستور if براي تست شرطهاي متعددي استفاده كنيم بايد آنها را به طور تو در تو به كار ببريم. كاربرد if به صورت تو در تو، نه تنها موجب طولاني شدن برنامه مي‌شود، بلكه از خوانايي برنامه نيز مي‌كاهد. ساختار eles if مي‌تواند به جاي ifهاي تو در تو به كار گرفته شود و ميزان خوانايي برنامه را بالا ببرد.

انتقال كنترل غيرشرطي

دستور if شرطي را بررسي كرده، براساس نتيجه شرط، دستور العملهايي را انجام مي‌دهد. در C دستور العملهايي وجود دارند كه بدون تست شرطي مي‌توانند كنترل اجراي برنامه را از نقطه‌اي به نقطه ديگر منتقل كنند. اين دستورات را انتقال كنترل غيرشرطي گويند.

دستور break

اين دستور موجب خروج از حلقه‌هاي تكرار مي‌شود. نحوه كاربرد اين دستور به صورت زير است:

break ;

اگر چند حلقه تو در تو وجود داشته باشد، اين دستور موجب خروج از داخلي‌ترين حلقه تكرار مي‌شود. كاربرد ديگر اين دستور، خاتمه دادن به ساختار switch است.

توابع و برنامه‌سازي ساخت‌يافته

با استفاده از توابع مي‌توان برنامه‌هاي ساخت يافته‌اي نوشت. در اين نوع برنامه‌ها، اعمال برنامه، توسط بخشهاي مستقلي كه تشكيل دهنده برنامه‌اند انجام مي‌شود. اين بخشهاي مستقل همان توابع هستند. امتيازات برنامه نويسي ساخت يافته عبارت‌اند از:

  1. نوشتن برنامه‌هاي ساخت يافته آسان است، زيرا برنامه‌هاي پيچيده به بخشهاي كوچكتري تقسيم مي‌شوند و هر بخش توسط تابعي نوشته مي‌شود. دستور العملها و داده‌هاي موجود در تابع، مستقل از ساير بخشهاي برنامه است.
  2. همكاري بين افراد را فراهم مي‌كند. به طوري كه افراد مختلف مي‌توانند بخشهاي مختلفي از برنامه را بنويسند.
  3. اشكالزاديي برنامه‌هاي ساخت يافته ساده‌تر است. اگر برنامه اشكالي داشته باشد، بررسي تابعي كه اين اشكال در آن به وجود آمده است، ساده است.
  4. برنامه‌نويسي ساخت‌يافته موجب صرفه‌جويي در وقت مي‌شود. بدين ترتيب كه، اگر تابعي بنويسيد كه عملي را در برنامه‌اي انجام دهد، مي‌توانيد آن تابع را در برنامه ديگري كه به اين عمل نياز دارد، به كار بريد. حتي اگر، با تغيير اندكي در توابع نوشته شده، بتوانيد آنها را در برنامه‌هاي ديگر به كار ببريد، باز هم مقرون به صرفه است.

براي طراحي برنامه‌هاي ساخت‌يافته، ابتدا بايد اعمالي را كه در برنامه انجام مي‌شوند، مشخص كنيد. سپس بخشهايي از برنامه را كه مي‌توانند به طور مستقل انجام شوند، به صورت توابع طراحي و پياده‌سازي كنيد. براي اين منظور، ساختار تابع، وروديها و خروجيهاي تابع را تعيين نمايد. در اغلب برنامه‌هاي C، تابع main() بسيار كوچكاست و وظايف اصلي برنامه‌ها به عهده توابع است.

نوشتن توابع

براي نوشتن تابع بايد اهداف تابع مشخص باشد. تابع چه وظيفه‌اي به عهده دارد، وروديهاي تابع چيست، و خروجيهاي تابع كدامند. با دانستن اين موارد، نوشتن تابع چندان دشوار نيست.

هر تابع داراي دو جنبه است، جنبه تعريف تابع و جنبه فراخواني آن. جنبه تعريف تابع، مجموعه‌اي از دستورات است كه عملكرد تابع را مشخص مي‌كند و جنبه فراخواني تابع، دستوري است كه تابع را فراخواني مي‌كند. فراخواني تابع با نام آن انجام مي‌شود. نامگذاري براي تابع، از قانون نامگذاري براي متغيرها تبعيت مي‌كند. توابع را بايد پس از تابع main() نوشت. ساختار و اجزاي توابع C در شكل 2 آمده‌اند.

شكل 2: ساختار تابع.
>نوع تابع< يكي از انواع موجود در C يا انواع ديگري است كه توسط كاربر تعريف مي‌شود. اگر تابعي بخواهد مقداري را به تابع فراخوان برگرداند، آن مقدار در نام تابع قرار مي‌گيرد. چون هر مقداري داراي نوع است، سپس نام تابع نيز بايد داراي نوع باشد. اگر تابع هيچ مقداري را به برنامه فراخوان برنگرداند، نوع آن void منظور خواهد شد. پارامترها اطلاعاتي هستند كه هنگام فراخواني تابع، از برنامه فراخوان به آن ارسال مي‌شوند. به عبارت ديگر، پارامترها وسيله‌اي براي تبادل اطلاعات بين تابع فراخوان و فراخواني شونده هستند. اگر تعداد پارامترها بيش از يكي باشد، پارامترها بايد با كاما از هم جدا شوند. در ليست پارامترها، نوع هر يك از پارامترها نيز مشخص مي‌شود. اطلاعاتي كه هنگام فراخواني تابع، در جلوي نام تابع (در داخل پرانتز) ظاهر مي‌شوند، آرگومان تابع نام دارند. دقت داشته باشيد كه پارامترها متغيرهايي هستند كه هنگام تعريف تابع، در جلوي نام تابع و در داخل پرانتز قرار مي‌گيرند. براي به كارگيري تابع در برنامه، بايد الگوي آن را در خارج از تابع main() به كامپايلر اعلان كرد. الگوي تابع، مشخص مي‌كند كه تابع چگونه فراخواني مي‌شود. الگوي تابع نيز به صورت زير مشخص مي‌شود:

; (ليست پارامترها)           نام تابع      >نوع تابع<

به نمونه‌اي از برنامه با تابعي به نام sample() كه رد شكل 3 آمده است توجه كنيد.

در استفاده از توابع در C، موارد زير را به خاطر داشته باشيد:

  1. الگوي تمام توابع را قبل از تابع main() اعلان كنيد (هر چند كه مي‌توانيد در تابع main() نيز اعلان كنيد).
  2. نوع توابع را تعيين نماييد.
  3. براي اجراي توابع، آنها را با نامشان فراخواني كنيد.
  4. الگوي تابع بايد همانند عنوان تابع باشد (شكل 3). عنوان تابع، اولين سطر در تعريف تابع است.
  5. متغيرهاي مورد نياز توابع را در داخل توابع تعريف كنيد. هيچ تابعي نمي‌تواند از متغيرهاي توابع ديگر استفاده كند. مگر اينكه از طريق پارامترها منتقل شوند.
  6. تعريف تابع در داخل تابع ديگر امكان‌پذير نيست.
  7. هنگام فراخواني توابع، دقت داشته باشيد كه تعداد و نوع پارامترها و آرگومانها يكسان باشد.
  8. توابع از نظر تعداد مقاديري كه مي‌توانند به توابع فراخوان برگردانند به سه دسته تقسيم مي‌شوند. (1) توابعي كه هيچ مقداري را برنمي‌گردانند (نوع void)، (2) توابعي كه يك مقدار را برمي‌گردانند، و (3) توابعي كه چندين مقدار را برمي‌گردانند. هر كدام از اين توابع در ادامه مورد بحث قرار مي‌گيرند.
  9. هنگام اعلان الگوي توابع، نياز به ذكر اسامي پارامترها نيست. بلكه ذكر نوع آنها كفايت مي‌كند. به عنوان مثال، الگوي تابع sample() را كه در شكل 3 آمده است، مي‌توان به صورت زير نوشت:

void     sample   (int, int) ;

  1. اگر تابعي فاقد آرگومان است، به جاي ليست آرگومانها، كلمه void را قرار دهيد.

 

 

 

 

 

 

 

 

شكل 3: شيوه به كارگيري تابع در برنامه.

نكاتي در مورد نوشتن توابع

  1. ابتدا بدون پرداختن به جزئيات پياده‌سازي توابع، آرگومانها و نتيجه‌اي را كه از توابع انتظار داريد، مشخص كرده، برنامه اصلي را بنويسيد. به عبارت ديگر، در قدم اول لازم نيست به جزئيات پياده‌سازي تابع بپردازيد. پس از نوشتن برنامه اصلي، توابع ديگر را بنويسيد.
  2. توابع را طوري طراحي و پياده سازي كنيد كه هر تابع فقط به آنچه كه نياز دارد دسترسي داشته باشد و بقيه قسمتهاي برنامه و ساير اطلاعات، توسط توابع غير مرتبط، قابل دستيابي نباشد. اين موضوع را پنهان سازي اطلاعات (infformation hiding) گويند. براي اين منظوره، هر تابع بايد يك نقطه ورود و يك نقطه خروج داشته باشد.
  3. براي ارتباط بين توابع، از آرگومانها و پارامترها استفاده كنيد.

تابع چگونه كار مي‌كند

وقتي تابعي، توسط تابع ديگري فراخواني مي‌شود، دستورات آن تابع اجرا مي‌شوند. پس از اجراي دستورات تابع، كنترل اجراي برنامه به برنامه فراخوان برمي‌گردد. پس از برگشت از تابع فراخواني شده، اولين دستور بعد از فراخواني تابع (در تابع فراخوان) اجرا مي‌شود.

شكل 4 سه تابع را كه هر كدام از آنها يك بار فراخواني شده‌اند نمايش مي‌دهد. با فراخواني تابع، دستورات آن تابع اجرا مي‌شوند و پس از اجراي تابع، كنترل به برنامه اصلي برمي‌گردد. هر تابع مي‌تواند چندين بار فراخواني شود.

شكل 4: چگونگي عملكرد توابع.

روشهاي ارسال پارامترها به توابع

پارامترها را به دو طريق مي‌توان از تابع فراخوان به تابع فراخواني شونده ارسال كرد. اين دو روش عبارتند از:

  1. روش فراخواني با مقدار (call by value)
  2. روش فراخواني با ارجاع (call by reference)

روش فراخواني، تعداد مقاديري را كه توابع فراخواني شونده مي‌توانند برگردانند، مشخص مي‌كند. در روش فراخواني با مقدار، دو دسته توابع مي‌توانند وجود داشته باشند (1) توابعي كه هيچ مقداري را برنمي‌گردانند (2) توابعي كه فقط يك مقدار را برمي‌گردانند. اما در روش فراخواني با ارجاع، توابع مي‌توانند چندين مقدار را به تابع فراخوان برگردانند.

در روش فراخواني با مقدار، هنگام فراخواني، مقادير آرگومانها در پارامترها كپي مي‌شوند و هر گونه تغييري در پارامترها، تاثيري در آرگومانها ندارد. اما در روش فراخواني با ارجاع، آدرس آرگومانها به پارامترها منتقل مي‌شود. بنابراين پارامترها بايد قابليت نگهداري آدرس را داشته باشند. نگهداري آدرسها به بحث اشاره‌گرها مربوط مي‌شود.

توابعي كه هيچ مقداري را برنمي‌گردانند

ممكن است در برنامه، از توابعي استفاده كنيم كه آن توابع، پس از فراخواني، عمليات مورد نظر را انجام مي‌دهند و خروجيهاي مورد انتظار را توليد و چاپ نمايند و هيچ مقداري را به تابع فراخوان تحويل ندهند. در بسياري از مسئله‌هايي كه با كامپيوتر حل مي‌شوند، اينگونه توابع به چشم مي‌خورند.

توابعي كه يك مقدار را برمي‌گردانند

در بسياري از مسئله‌هايي كه توسط كامپيوتر حل مي‌شوند، نياز به نوشتن توابعي است كه يك مقدار را برگردانند. مثل تابع sin() كه سينوس يك زاويه را برمي‌گرداند. اينگونه توابع، كاربردهاي فراواني دارند. براي نوشتن اينگونه توابع، نوع آنها را بايد در الگوي تابع و عنوان تابع مشخص كرد. براي برگرداندن مقداري توسط تابع، از دستور return به صورتهاي زير استفاده مي‌شود:

(>عبارت<)         return

>عبارت<           return

تفاوتي بين دو روش كاربرد return وجود ندارد. هم بدون پرانتز و هم با پرانتز قابل استفاده است. مقداري كه توسط دستور return برگشت داده مي‌شود، در نام تابع قرار مي‌گيرد. در برنامه فراخوان، مي‌توان نام تابع را به متغيري نسبت داد و از محتويات آن استفاده كرد. به عنوان مثال، اگر f1() يك تابع از نوع int و x متغيري از نوع int باشد، دستور زير، تابع f1() را فراخواني كرده، مقداري را كه توسط دستور return در نام تابع قرار مي‌گيرد، در x قرار مي‌دهد. در اينجا تابع f1() فاقد آرگومان است:

x = f1() ;

 

۱۳۹۵-۲-۸ ۲۱:۲۴:۰۵ +۰۴:۳۰اردیبهشت ۸ام, ۱۳۹۵|Categories: مهندسی نرم افزار|بدون ديدگاه

ثبت ديدگاه

پرداخت

1-پرداخت آنلاین
برای پرداخت آنلاین از لینک زیر استفاده کنید
پرداخت آنلاین
2- پرداخت آفلاین
برای پرداخت آفلاین مبلغ مورد نظر را به یکی از شماره کارت
6037997245888723بانک ملی