• توجه: در صورتی که از کاربران قدیمی ایران انجمن هستید و امکان ورود به سایت را ندارید، میتوانید با آیدی altin_admin@ در تلگرام تماس حاصل نمایید.

تاپيك آموزش زبان C

تاپيك آموزش زبان C
c.jpg



زبان C در سال ۱۹۷۰ توسط دنیس ریچی طراحی گردید. این زبان تکامل یافته زبان BCPL
میباشد که طراح آن مارتین ریچاردز است ،و زبان BCPL از زبان B که طراح آن
کن تامپسون می باشد ، نتیجه شده است .
زبان C معمولا” یک زبان میانی نامیده می شود . این بدان معنی نیست که آموزش
این زبان مشکل است ، یا قدرت آن از زبان های برنامه سازی مثل پاسکال و بیسیک
کمتر است و یا این که مشکلاتی مشابه زبان اسمبلی برای برنامه نویس ایجاد می کند.
علت میانی بودن زبان C این است که عناصر زبان های سطح بالا را با خصیصه تابعی
زبان اسمبلی درهم آمیخته است .برای پی بردن به جایگاه زبان C درمقایسه با سایر
زبان های برنامه سازی به جدول (۱) مراجعه نمایید .
جدول (۱) . سطوح زبان های برنامه سازی

زبان C همانند سایر زبانهای میانی با مفاهیم بیت ، بایت و آدرس که از عناصر
ابتدایی ماشین هستند سر و کار دارد . یعنی در این زبان می توان محتویات بیت ها
و بایت ها را تیز تغییر داد .
برنامه های نوشته شده به زبان C براحتی از ماشینی به ماشین دیگر قابل انتقال
می باشند . مثلا” برنامه نوشته شده برای کامپیوتر APPL در کامپیوترهای IBM قابل
اجرا است . این خصیصه را قابل حمل بودن (Portability) زبان می گویند .
کلیه زبان های برنامه سازی سطح بالا و میانی دارای نوعهای داده (data types)
هستند . هر نوع داده ، مجموعه ای از مقادیر را مشخص می کند که اعمال خاصی روی
آنها قابل انجام است . نوع داده ای که در اکثر زبانها وجود دارد عبارتند از :
اعداد صحیح ، کاراکتری و اعداد اعشاری . C دارای ۵ نوع داده اصلی است که در آن
تقریبا” تبدیل هر نوع داده به نوع دیگر امکان پذیر است . مثلا” در یک عبارت
می توان نوع کاراکتری را با نوع عددی صحیح و یا اعشاری ترکیب کرد .
زبان C خطای زمان اجرا مثل boundray checking را چک نمی کند . منظور از boundray checking
این است که در آرایه ها تجاوز از حدود مشخص شده ، به راحتی
امکان پذیر بوده و از نظر کامپایلر با خطایی مواجه نمیشود. این مساله برمیگردد
به این که در زبان C آرایه یک اشاره گر (pointer) است . در این راستا ، نوع
پارامترها و آرگومان های توابع نیز در گونه های قدیمی C با یکدیگر مطابقت نشده و
از نظر کامپایلر با خطا مواجه نمی شد ولی در گونه های جدید C با معرفی الگوی
تابع (Function prototype) این مشکل رفع شده است . C
همانند زبان های ALGOL، PASCAL، و… یک زبان ساخت یافته است . یک زبان
برنامه سازی ساخت یافته امکانات زیادی ، از جمله استفاده از چند ساختار حلقه سازی
مثل while، do-while،و forو را فراهم می کند . در این گونه زبان ها از goto به
ندرت استفاده می شود و نوشتن دستورات برنامه در هر ستونی از خط و در هر جای
فایل امکان پذیر بوده ، مثل زبان فرترن مقید به ستون های خاصی نیستند. استفاده
از زیربرنامه ها و بلاک ها نیز از خصیصه های این نوع زبان ها هستند . ذکر اسامی
چند زبان ساخت یافته و غیر ساخت یافته ، در انتخاب زبان برنامه سازی جهت برنامه
نویسی مفید است . ( جدول (۲) ) .
جدول (۲) . بعضی از زبانهای ساخت یافته و غیرساخت یافته

هر برنامه در زبان C دارای خصیصه هایی است که بعضی از آنها عبارتند از : ۱
در زبان C هر دستور برنامه به یک ; ختم می شود . ۲
هر دستور میتواند درچند خط ادامه داشته و یک خط ممکن است شامل چند دستور
باشد . ۳
حداکثر طول یک خط برنامه ۲۵۴ کاراکتر است . ۴
در زبان C برنامه نویس می تواند در هر نقطه از برنامه ، بااستفاده از علائم {
و }و یک بلاک را مشخص کرده و هر متغیری را که می خواهد در آنجا تعریف نماید .
این متغیرها فقط در آن بلاک معنی خواهند داشت . توجه داریم که هر بلاک مجموعه ای
از دستورات وابسته به یکدیگر خواهد بود :
ؤؤ { |

بلاک | ; مجموعه دستورات } |

ؤؤ ۵
برای داشتن توضیحات در برنامه کافی است آنها را دربین /*و *و/ قرار داد: *

توضیحات /* C
یک زبان ساخت یافته بلاکی نیست . این بدان معنی است که تعریف یک زیربرنامه
( در اینجا تابع ) در زیربرنامه دیگر ( همانند پاسکال ) امکان پذیر نیست و این
امر از مساله coupling می کاهد . C
زبان برنامه نویسی سیستم است . منظور از برنامه های سیستم عبارتند از : ۱
سیستم عامل (Operating system) 2
مفسر (Interpreter) 3
ویراستار (Editor) 4
اسمبلر (Assrmbler) 5
کامپایلر (Compiler) 6
مدیریت بانکهای اطلاعاتی (Database management)
امروزه C در اکثر امور برنامه نویسی مورد استفاده قرار می گیرد . زیرا این
زبان هم دارای خصیصه ” قابل حمل بودن ” است و هم دارای کارآیی خوبی می باشد و
سرعت زیاد C بر محبوبیت آن افزوده است . مساله قابل حمل بودن ، یک مساله بسیار
مهم است زیرا هم موجب صرفه جویی در وقت شده و هم باعث صرفه جویی در هزینه ها
می گردد .
زبان C فقط دارای ۳۲ کلمه کلیدی است ( جدول (۳) ) که ۲۷ کلمه کلیدی آن توسط
ریچی ( طراح زبان ) معرفی شده و ۵ کلمه کلیدی دیگر توسط موسسه استاندارد سازی
زبان به آن اضافه شده است . این تعداد در مقایسه با ۱۵۹ کلمه کلیدی که در زبان
بیسیک وجود دارد قابل توجه است .
| auto | double | int | struct |
| break | else | long | switch |
| case | enum* | register | typedef |
| char | extern | return | union |
| const* | float | short | unsigned |
| continue | for | signed* | void* |
| default | goto | sizeof | volatile* |
| do | if | static | while |

اضافه شدن توسط موسسه استاندارد سازی زبان
جدول (۳) . کلمات کلیدی زبان C

بعضی از کامپایلرها علاوه بر ۳۲ کلمه کلیدی جدول (۳) کلمات کلیدی دیگری به
زبان اضافه نموده اند . ( جدول (۴) ) .
| asm | ess |- ds |- es |
|- ss | cdecl | far | huge |
| intrrupt | near | pascal | |

جدول (۴) . کلمات کلیدی زبان C که بعضی از کامپایلرها اضافه کرده اند

کلیه کلمات کلیدی در زبان C به حروف کوچک نوشته می شوند . چون در این زبان
بین حروف کوچک و بزرگ تفاوت است ، به عنوان مثال کلمه else یک کلمه کلیدی است
 
انواع داده

همان طور که قبلا” گفته شد در هر زبان برنامه سازی تعدادی از نوع های داده
وجود دارند که بازه ای را شامل بوده و اعمال خاصی روی آنها انجام پذیر است و در C
پنج نوع داده اصلی وجود دارد که عبارتند از : char، int،، float،، double، و void
. در این زبان اندازه و محدوده ای که هر نوع داده اختیار می کند بستگی به
نوع پردازشگر (Processor) و نحوه پیاده سازی کامپایلر دارد. شناسه هایی ( متغیر
برچسب ، اسامی توابع و … ) که از نوع char باشند برای ذخیره کردن مقادیری که
توسط کاراکترهای اسکی تعریف شده اند به کار می روند. شناسه هایی از نوع int برای
ذخیره کردن مقادیر صحیح ، و از نوع floatو doubleو برای ذخیره کردن اطلاعات عددی
اعشاری به کار میروند که محدوده آنها توسط تعداد ارقام و دقت آنها مشخص میشود.
نوع void در مورد توباع به کار می رود .
نوعهای داده اصلی ( به جز void ) می توانند با عباراتی مثل signed، long، unsigned
و shortو ترکیب شده و نوع های دیگری را به وجود آورند . ( جدول (۱) ).
نوع | اندازه تقریبی به بیت | بازه قابل قبول |

char
|
| 8 | 127- تا | ۱۲۷ unsigned char
|
| 8 | 0 تا | ۲۵۵ signed char
|
| 8 | 127- تا | ۱۲۷ int
|
| 16 | 32767- تا | ۳۲۷۶۷ unsigned int
|
| 16 | 0 تا | ۶۵۵۲۵ signed int
|
| 16 | 32767- تا | ۳۲۷۶۷ short int
|
| 16 | 32767- تا | ۳۲۷۶۷ unsigned
|
| 16 | 0 تا | ۶۵۵۲۵ | | | short int |
signed
|
| 16 | 32767- تا | ۳۲۷۶۷ | | | short int |
long int
|
| 32 | َ۲۱۴۷۴۸۳۶۴۷- تا | ۲۱۴۷۴۸۳۶۴۷ |
float | 32 | 6 رقم دقت | |
double | 64 | 10 رقم دقت | |
long double | 128 | 10 رقم دقت | |
signed | 32 | َ۲۱۴۷۴۸۳۶۴۷- تا | ۲۱۴۷۴۸۳۶۴۷ | | | long int |
|
| uunsigned long int 32 | 0 تا | ۴۲۹۴۹۶۷۲۹۵
ول (۱) . نوعهای ترکیبی
 
متغیر

متغیر، نامی برای یک محل حافظه است که محتویات آن در طول اجرای برنامه ممکن
است تغییر کند . اسم هر متغیر شامل حروف aتا zا، A،تا Zا ، ارقام ۰تا ۹ا و خط
ربط است . به طوری که با یکی از حروف و یا خط ربط شروع شده باشند . طول نام هر
متغیر بستگی به نوع کامپایلر دارد که معمولا”از ۱ز تا ۳۱ کاراکتر قابل استفاده
است . بعضی از اسامی مجاز و غیر مجاز در زیر آمده اند :
اسامی مجاز برای متغیرها | اسامی غیرمجاز برای متغیرها |

| ۱count | count |
| high! there | test123 |
| grad.1 | high |

تعریف نوع متغیر
برای استفاده از متغیرها درC باید ابتدا آنها را تعریف کنیم . تعریف متغیرها
شامل نامگذاری و تعیین نوع آنها است که به صورت زیر انجام می شود :
<نوع> <اسامی متغیرها>
یکی از انواع است که قبلا<نوع>” شامل متغیرهایی <اسامی متغیرها> ذکر کردیم و
است که می خواهیم دارای آن نوع باشند . برای تعریف چند متغیر در یک دستور باید
اسامی با کاما از یکدیگر جدا گردد : int var1/ var2;

دستور فوق دو متغیر به اسامی var2و var1و را از نوع int تعریف می کند . float flovar1/ flovar2;

دستور فوق ، دو متغیر به نام های flovar2و flovar1و را از نوع float تعریف
می کند . double d1;
char ch;

اولین دستور ، d1 را از نوع double و دستور دوم متغیر ch را از نوع char
تعریف می کند .

مقدار دادن به متغیرها
برای مقدار دادن به متغیرها می توان به دو طریق عمل کرد: ۱ به هنگام تعریف
متغیر . ۲ پس از تعریف متغیر . به عنوان مثال : int a=0;
int b/ c/ d/ e=0;
char ch= ‘a’;
b=0;
c=d=0;

دستور اول ضمن تعریف a از نوع int مقدار آن را برابر با ۰ قرار می دهد .
دستور دوم چهار متغیرb، c،، d،و eو را از نوع int تعریف کرده وفقط مقدار متغیر ch
را از نوع کاراکتری تعریف کرده و مقدار آن را برابر با حرف a قرار می دهد .
دستور چهارم مقدار متغیر b را برابر با ۰ قرار می دهد . دستور پنجم مقدار دو
متغیر cو dو را برابر صفر قرار می دهد و این دستور ، انتساب چندتایی را مشخص
می کند .
همان طور که قبلا”گفته شد مقدار متغیرها ممکن است در طول اجرای برنامه تغییر
کند . با استفاده از کلمه کلیدی const می توانیم متغیرهایی را تعریف کنیم که
مقدار آنها در طول اجرای برنامه ثابت باشد . برای تعریف این نوع متغیرها بصورت
زیر عمل می شود :
<نوع> <اسامی متغیرها>const
نوع ، یکی از نوع هایی است که قبلا” ذکر شده و اسامی متغیرها ، مشخص کننده
متغیرهایی است که باید به صورت ثابت تعریف شوند : const int a = 10 / b = 20;

دستور فوق دو متغیر aو bو را از نوع int تعریف کرده و مقادیر آنها را برابر می دهد . این مقادیر در طول اجرای برنامه قابل تغییر هستند
 
عملگرها

عملگرها نمادهایی هستند که برای انجام اعمال خاصی مورداستفاده قرارمیگیرند.
عملگرها در زبان C از تنوع زیادی برخوردارند . در C چهار دسته عملگر به نامهای
( محاسباتی ، رابطه ای ، منطقی و دستکاری بیت ها ) وجود دارند که آنها را بررسی
می کنیم .

عملگرهای محاسباتی
عملگرهای محاسباتی که در C مورد استفاده قرار می گیرند در جدول (۱) فهرست
شده اند .
ردیف | عملگر | نام | مثال |

۱ | – | تفریق و منهای یکانی | |-xx/x-y

2 | + | جمع | | x+y

3 | * | ضرب | | x*y

4 | / | تقسیم | | x/y

5 | % | باقیمانده تقسیم | | x%y

6 | – - | کاهش یک واحد * | – -xیا xا – |-

۷ | ++ + | افزایش یک واحد * | x+ + یا | + +xا

* decrement ** increment

جدول (۱) . عملگرهای محاسباتی

عملگرهای ردیف ۱تا ۴ا در جدول (۱) تقریبا” در همه زبانهای برنامه سازی وجود
دارند. عملگر % که در بقیه زبانها با علامت دیگری ( مثلا” در بیسیک به صورت MOD)
وجود دارد باقیمانده تقسیم دو عدد را محاسبه می کند : x= 13;
y= 5;
z= x%y;

اگر سه دستور فوق را توسط ماشین اجرا کنیم مقدار۳ که باقیمانده تقسیم ۱۳ بر ۵
است در z قرار می گیرد .
عملگر کاهش ، یک واحد از عملوند مربوط کم می کند . x= 10;
- – x;

دستور x – - از x یک واحد کم می کند و نتیجه را در x قرار می دهد که معادل
دستور ۱ + َx = x-1 است .
عملگر افزایش ، یک واحد به عملوند مربوطه اضافه می کند : x= 40;
++x;

دستور ++x معادل دستور x = + 1 است که موجب افزودن یک واحد به x می شود .
عملگرهای افزایش و کاهش یک واحد را می توان بعداز عملوند مربوطه نیز به کار
برد مثل : x + + و – - x .
اگر در یک عبارت از عملگرهای افزایش و کاهش یک واحد ، استفاده کنیم به کار
بردن این عملگرها در قبل و بعد از عملوند مربوطه ، با یکدیگر متفاوت است . بدین
معنی که اگر این عملگرها قبل از عملوند باشند مقدار فعلی عملوند مورد استفاده
قرار گرفته و سپس عملگرها بر روی آن عمل میکنند، ولی اگر بعد از عملوند مربوطه
باشند پس از انجام عمل افزایش و کاهش یک واحد به آنها مقادیر جدید ، در عبارت
مورد استفاده قرار می گیرند. استفاده ازعملگرهای افزایش و کاهش یک واحد ، سرعت
محاسباتی را بالا می برد .
اگر در یک عبارت از چند عملگر محاسباتی استفاده شود ، مساله تقدم عملگرها
مطرح می شود . ( جدول (۲) ) .
بالاترین تقدم – - | + + |
تفریق یکانی – | | * / % |
|
پایین ترین تقدم – | +

جدول (۲) . تقدم عملگرهای محاسباتی

همان طور که در جدول (۲) مشاهده می شود ، عملگرهای افزایش و کاهش یک واحد
دارای بالاترین تقدم و عملگرهای جمع و تفریق دارای کمترین تقدم هستند و منهای
یکانی ، دارای دومین تقدم است . عملگرهایی که در یک سطر آمده اند ، مثل – و +
بدین معنی است که دارای تقدم مکانی نسبت به یکدیگر هستند. در این صورت هر کدام
از غملگرها که اول ظاهر شود ، زودتر انجام خواهد شد .

عملگرهای رابطه ای
عملگرهای رابطه ای برای تشخیص ارتباط بین عملوندها یا مقایسه آنها مورد
استفاده قرار می گیرند ( جدول (۳) ) .
عملگر | نام | مثال |

> | بزرگتر | y >x | >

= >|> بزرگتر مساوی | =y >x | >

< | کوچکتر | y <

= <|< کوچکتر مساوی | =y <

== | = مساوی بودن | | x=x==y

!= | ! نامساوی | | x=x!=y

جدول (۳) . عملگرهای رابطه ای

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

عملگرهای منطقی
عملگرهای منطقی ( جدول (۴) ) بر روی عملوندهای منطقی عمل میکنند. عملوندهای
منطقی دارای دو ارزش درستی و نادرستی هستند .
عملگر | نام | مثال |

&& | & و(AND) z || x

|| | | یا (OR) z || x

! | نقیض (NOT) | !x |

جدول (۴) . عملگرهای منطقی

ارزش نادرستی درزبان C با مقدار صفر و ارزش درستی با مقادیر غیراز صفر مشخص
میشود. عملگر منطقی ! دارای بالاترین تقدم و عملگر || دارای کمترین تقدم در بین
عملگرهای منطقی هستند . چون عملگرهای منطقی رابطه نزدیکی با عملگرهای رابطه ای
دارند می توان تقدم آنها را نسبت به یکدیگر بیان کرد ( جدول (۵) ) .
بالاترین تقدم | ! | > >= < <= |
| == != |
| && |
|
پایین ترین تقدم | ||

جدول (۵) . تقدم عملگرهای منطقی و رابطه ای

عملگرهای محاسباتی و رابطه ای با یکدیگر ترکیب شده و عملگرهای دیگری را بنام
عملگرهای محاسباتی رابطه ای ایجاد می کنند ( جدول (۶) ) . تقدم این عملگرها از
سایر عملگرها پایین تر است .
عملگر | نام | مثال |

+= | + انتساب جمع | x+=y |

= | انتساب تفریق | x-=y |

*= | * انتساب ضرب | x*=y |

/= | / انتساب تقسیم | x/=y |

%= | % انتساب باقیمانده تقسیم | x%=y |

جدول (۶) . عملگرهای محاسباتی و رابطه ای

در جدول (۶) ، عبارت x + = y معادل با x = x + y است و عبارت x % = y معادل y
x = x % است که موجب انتساب باقیمانده تقسیم xبر yربه x می شود : int a=10;
int b=20;
a+= b;

با اجرای دستورات فوق متغیر a برابر۳۰ خواهد بود. زیرا دستور a + = b معادل
دستور a = a + b است .

عملگر دستکاری بیت ها
ازآنجایی که زبان C طوری طراحی شده است که بتواند دربسیاری ازموارد جایگزین
زبان اسمبلی گردد. باید قادر باشد کلیه اعمال ( یا حداقل بسیاری از اعمال ) که
در زبان اسمبلی قابل انجام هستند را انجام دهد . یکی از اعمالی که در زبان
اسمبلی براحتی انجام پذیر است . انجام اعمالی بر روی بیت های یک بایت یا یک
کلمه از حافظه است که در زبان C برای انجام این منظور از عملگرهایی استفاده
می شود که به عملگرهای بیتی معروفند ( جدول (۷) ) . این عملگرها انجام اعمال
تست ، مقدار دادن و یا انتقال (shift) بیت ها را در یک بایت یا کلمه حافظه
امکان پذیر می نمایند. عملگرهای بیتی فقط بر روی متغیرهایی از نوع charیا intا
عمل می کنند و بر روی متغیرهایی از نوع float، double،، long double،، void، و
یا سایر متغیرها قابل اجرا نیستند . عملگرهای بیتی &، |،و ~و(AND(، OR،و NOTو)
مشابه عملگرهای منطقی AND، OR،و NOTو عمل می کنند با این تفاوت که عمل آنها بر
روی یک بیت است . با فرض این که pو qو دو بیت مختلف باشند ، نحوه عمل عملگر ^
را در ذیل مشاهده می نمایید .
p | q | p^q |

0 | 0 | 0 |

1 | 0 | 1 |

1 | 1 | 0 |

عملگرهای بیتی در جدول (۷) مشاهده می شوند .
عملگر | نوع عمل |
& | AND ( و ) |
| | OR ( یا ) |
^ | XOR ( یا انحصاری ) |
~ | NOT ( نقیض یا متمم یک ) |
>> | انتقال به سمت راست (shift right) |
<< | انتقال به سمت چپ (shift left) |
جدول (۷) . عملگرهای بیتی

همان طور که مشاهده شد ، نتیجه عملگر بیتی ^ وقتی یک (۱) است که یکی از
عملوندهای آن صفر و دیگری یک باشد . به عبارت دیگر ، نتیجه عملگر بیتی ^ وقتی
صفر است که هر دو عملوند آن صفر و یا هر دو یک باشند .
عملگرهای &، |،و ^و و << ، >> بر روی دو عملوند عمل می کنند اما عملگرهای ~
به صورت ذیل به کار می روند: >> و <<بر روی یک عملوند عمل می کنند . عملگرهای
متغیر >>تعداد انتقال
متغیر <<تعداد انتقال
و <<در روش کلی فوق ، متغیر ، یک بایت یا کلمه ای از حافظه است که عملگرهای
باید بر روی آن عمل کنند . تعداد انتقال عددی است که مشخص می کند بیت های >>”
متغیر ” باید چند محل به سمت راست و یا چپ انتقال یابند . همان طور که قبلا”
برای انتقال به چپ مورداستفاده << برای انتقال به راست و عملگر>>گفته شد عملگر
قرار می گیرد . هر انتقال به چپ ، معادل با تقسیم کردن مقدار متغیر به ۲ و هر
انتقال به راست ، معادل ضرب کردن در ۲ است .

مثال ۱ :
تعداد عددی متغیر | x مقدار بیتی متغیر | x دستورات زبان | C
| char x; | | |

| x=7 ; | 00000111 | 7 |

| x<<1 ; | 00001110 | 14 |

| x<<3 ; | 01110000 | 112 |

| x<<2 ; | 11000000 | 192 |

| x>>1 ; | 01100000 | 96 |

| x>>2 ; | 00011000 | 24 |

همان طور که مشاهده می کنید پس از اجرای دستور ۲<< x< اطلاعات واقعی از بین
می روند و مساله ضرب در ۲ شدن ، در اینجا صدق نمی کند .
عملگر ~ در یک بایت یا کلمه حافظه ( یک متغیر ) کلیه بیت ها را نقیض میکند.
یعنی بیت صفر را به بیت یک و بیت یک را به بیت صفر تبدیل می نماید . لذا اگر
این عملگر دو بار بر روی یک متغیر عمل کند وضعیت بیت های متغیر به حالت اول
برمی گردند .

مثال ۲ : x :00101100
~x :11010011
~x :00101100

همان طور که مشاهده می شود بیت های ردیف اول و ردیف آخر دارای یک وضعیت
میباشند ( بیت های ردیف آخر نتیجه دوبار اجرای عملگر نقیض بر روی متغیر است ).
نکته ای که در مورد عملگرهای بیتی باید در نظر داشت این است که این عملگرها
معمولا” در مبدل های دستگاهها (device drivers) مورد استفاده قرار می گیرند .
مثل برنامه هایی که برای کار با modem و با چاپگر نوشته می شوند . زیرا در این
گونه موارد معمولا” تست کردن بیت های یک متغیر مد نظر خواهد بود .

عملگر ?
عملگر ? با تست یک شرط ، مقداری را به یک متغیر نسبت می دهد . این عملگر به
صورت زیر استفاده می شود : exp3
:= exp1 ? exp2 متغیر exp1
، exp2،و exp3و سه عبارت هستند . نحوه عمل ? به این صورت است که : ابتدا
عبارت اول (exp1) ارزیابی می شود چنانچه این عبارت دارای ارزش true ( ارزش
درستی ) باشد مقدار exp2 پس از ارزیابی ، در متغیر ذکر شده قرار می گیرد وگرنه
عبارت سوم (exp3) ارزیابی شده و نتیجه آن به متغیر ذکر شده منتقل می شود . x= 10;
y= x>9 ? 100 :200;

نحوه عمل در دو دستور فوق به این صورت است که عبارت ۹> x> ارزیابی می شود .
چون این عبارت یک ارزش منطقی true دارد ( ۹> x> است ) لذا عدد ۱۰۰ در متغیر y
قرار می گیرد .

عملگرهای &و *و
عملگر & یک عملگر یکانی است که آدرس عملوند خود را مشخص می کند و به صورت
زیر به کار می رود : ;
نام عملوند &
مثل : int num;
p= #

با اجرای دستورات فوق آدرس متغیر num در متغیر p قرار می گیرد. لذا عملگر &
به معنی ” آدرس ” است . عملگر * همانند عملگر & یک عملگر یکانی است که محتویات
یک آدرس حافظه را مشخص می کند و به صورت زیر به کار می رود . ;
نام عملوند *
مثل : p= #
m= *p;

دستور اول ، آدرس متغیر num را در p قرار میدهد و دستور دوم ، محتویات محلی
را که آدرس آن در p قرار دارد ( محتویات num ) ، را در m قرار میدهد. بنابراین
مفهوم ” * محتویات آدرس ” می باشد . دو دستور فوق معادل دستور m = num; است که
موجب انتقال محتویات متغیر num به متغیر m می شود .

عملگر کاما (/)
عملگر کاما برای انجام چند عمل در یک دستور ، به کار رفته و به صورت زیر
استفاده می شود :
( عبارت ۲ و عبارت ۱) =) متغیر
عملگر کاما موجب می شود تا ” عبارت ” ۱ ارزیابی شده و سپس نتیجه ارزیابی ”
عبارت ” ۲ با یکدیگر ارتباط دارند . x =( y = 3 / y + 5);

ابتدا y باربر با ۳ قرار می گیرد و نتیجه عبارت y + 5 که برابر ۸ است در x
قرار خواهد گرفت .

عملگر sizeof
این عملگر که عملگر زمان ترجمه نامیده می شود، برای محاسبه طول یک نوع و یا
یک متغیر به کار رفته و به صورت زیر استفاده می شود . ;
(نوع) sizeof ;
متغیر sizeof
اگر بخواهیم با استفاده از این عملگرها، طول یک نوع مثل int، double و غیره
را محاسبه کنیم باید آن را در داخل پرانتز قرار دهیم : اما اگر بخواهیم طول یک
متغیر را محاسبه کنیم نیازی به استفاده از پرانتز نیست . به عنوان مثال : int a/ b/ c;
a= sizeof( int);
b= sizeof c;

دستور اول سه متغیر a، b،ز cز را به صورت int تعریف می کند . دستور دوم طول
نوع int را محاسبه کرده و در متغیر a قرار می دهد . دستور سوم طول متغیر c را
محاسبه کرده و در متغیر b قرار می دهد. این دستور برای مساله portability زبان C
بسیار مفید است . بعنوان مثال ممکن است طول نوع int از ماشینی به ماشین دیگر
متفاوت باشد . نکته ای که در مورد این عملگر باید توجه داشت این است که معمولا”
روش اول مورد استفاده قرار می گیرد و روش دوم چندان جالب نیست .

تقدم عملگرها در حالت کلی
وقتی که در یک عبارت چندین عملگر مورد استفاده قرار می گیرند تقدم عملگر به
صورت جدول (۸) خواهد بود .
بالاترین تقدم () | | ! ~ + + – - * & sizeof |
| * / % |
| + – |
| << >> |
| << = >> = |
| == =! |
| & |
| ^ |
| | |
| && |
| || |
| ? |
| = +=- = *= /= %= |
| / |

جدول (۸) . تقدم عملگرها در حالت کلی

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

مثال ۳ : int x=5/ y=10/ k=4;
int s;
s= x*((x+y-)3)/k;

درنتیجه اجرای چند دستور فوق مقداری که درs قرار می گیرد برابر با ۱۵ خواهد
بود . سپس عدد ۳ از ۱۵ کم می شود که ۱۲ حاصل می گردد و بعداز آن عمل ضرب انجام برابر با ۶۰ ( ۵ * ۱۲ ) می باشد و عملگر تقسیم (/) آخرین
 
تبدیل انواع

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

مثال ۱: char ch;
int i;
float f;
double d;
result =( ch/i )+( f*d( – )f+i)
| | | | | |
int |double | | float
| | | | | |
| | | | | |

ؤؤؤ ؤؤؤ ؤؤؤ | | |
int double float
| | |
| | |
|
ؤؤؤؤؤؤؤؤؤ | |
| |
double |
| |
| |

ؤؤؤؤؤؤؤؤؤؤؤؤؤ |
double

همان طور که از مثال ۱ پیداست ، نوع نتیجه double خواهد بود .
علاوه بر تبدیل انواع در عبارات ، در احکام انتساب نیز ممکن است تبدیل انواع
صورت گیرد . در تبدیل انواع اطلاعاتی از بین می روند که باید در نتیجه حاصل از
احکام انتساب دقت کافی به خرج داد. در ذیل تبدیل انواع در احکام انتساب مشاهده
می شود : int x;
char ch;
float f;
ch= x;
x= f;
f= ch;
f= x;

کلیه احکام انتساب فوق قابل انجام بوده و از طرف کامپایلر زبان C هیچ گونه
خطایی گزارش نمی شود . اطلاعاتی که ممکن است در تبدیل انواع از بین بروند . در
جدول (۱) آمده است .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
نوع منبع | نوع مقصد | اطلاعاتی که ممکن است از بین برود |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| signed char | char اگر مقدار بزرگتر از۱۲۷ باشد مقصد منفی خواهد شد |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| short 8 | char بیت با ارزش |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| int 8 | char بیت با ارزش |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| long int | char َ۲۴ بیت با ارزش |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| long int | int َ۱۶ بیت با ارزش |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| float | int قسمت کسری یا بیشتر و نتیجه حاصل گرد می شود |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| double | float قسمت کسری و یا بیشتر و نتیجه حاصل گرد می شود |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
جدول (۱) . تبدیل انواع

دو نکته را باید در مورد تبدیل انواع ( جدول (۱) ) به خاطر داشته باشیم : ۱
بعضی از تبدیل انواع در جدول فوق وجود ندارد مثل doubleبه int . در این
موارد می توان double را به float تبدیل کرده و سپس float را به int تبدیل نمود. ۲
وقتی نوع بزرگتری به نوع کوچکتری انتساب داده می شود . قسمتی از اطلاعات
از دست می روند . همان طور که می دانیم ، معمولا” اعداد صحیح (int) در ۲ بایت و
اطلاعات از نوع char در یک بابت ذخیره می شوند :
ؤؤؤؤؤؤؤؤؤؤؤ char
ؤؤؤؤؤؤؤؤؤؤؤ
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ int
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
بایت کم ارزش بایت باارزش
وقتی یک متغیر int به یک متغیر char انتساب داده می شود بایت کم ارزش متغیر
از نوع int به متغیر char منتقل شده ولی با ارزش متغیر int در متغیر char جایی میگوییم در انتساب متغیرintبه char ، ۸، بیت با ارزش از دست میرود.
 
ساختمان زبان C و چند تابع ورودی خروجی

همانطور که قبلا” گفته شد C زبان ساخت یافته است و هر برنامه در این زبان
شامل یک یا چند تابع است . یکی از این توابع که اسم آن ()main است به عنوان
تابع اصلی برنامه و بقیه توابع بعنوان تابع عرضی هستند . اجرای برنامه با تابع
اصلی ، یعنی ()main شروع می شود. در نوشتن برنامه ، باید تابع اصلی و سپس بقیه
توابع را بنویسیم . تعریف یک تابع در داخل تابع دیگر امکان پذیر نیست ولی هر
تابع می تواند یک یا چند تابع دیگر را فراخوانی نماید .
برخلاف زبانهای دیگر که زیر روال و توابع دو چیز جداگانه ای هستند در C همگی
تحت عنوان تابع بررسی می شوند .
کلیه متغیرهایی که در برنامه استفاده می شوند باید تعریف شوند و منظور از
تعریف متغیر ، نامگذاری و تعیین نوع آن است . متغیرها در C مقدار اولیه ندارند
و تا متغیری مقدار نگیرد قابل استفاده نخواهد بود . شکل (۱) ساختمان ساده یک
برنامه به زبان C را نشان می دهد که پس از مطالعه مفاهیم دیگری از زبان C ، آن
را تکمیل تر خواهیم کرد .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | main )(|
| { |
|
تعریف متغیرها | | . |
| . |
| . |
| } |
| f1 )(|
| { |
| . |
| . |
| . |
| } |
| f2 )(|
| { |
| . |
| . |
| . |
| } |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۱) . ساختمان ساده ای از برنامه C

اولین تابع برنامه ، ()main است . ابتدا متغیرهای مورد استفاده این تابع
تعریف ، سپس دستورات تابع اصلی با یک { شروع و به } ختم می شود . بعضی از
دستورات تابع اصلی ممکن است فراخوانی توابع ()f1 ، ()f2 وغیره نیز باشند. ()f1
()f2 دو تابع فرعی هستند که در برنامه وجود دارند همانطوری که مشاهده می گردد
تعریف توابع فرعی پس از تابع اصلی صورت می گیرد. در زبان C فرض میشود که نتایج
حاصل از تابع بصورت int است که اگر غیر از این باشد ، باید ضمن تعریف متغیرها وع توابع استفاده شده در برنامه به کامپایلر اعلان شود .
 
تابع ()printf

این تابع برای انتقال اطلاعات از کامپیوتر به صفحه نمایش مورد استفاده قرار
می گیرد و بصورت زیر استفاده می شود : ;
( عبارت دیگر ” / عبارت ” ۱) printf) ”
عبارت ” ۱ شامل تعدادی کاراکترهای کنترلی ، کاراکترهای قالب جهت تعیین شکل
خروجی و رشته های دیگری است که باید به خروجی منتقل شوند . ” عبارت دیگر ” شامل
اطلاعاتی هستند که با فرمت مشخص شده در ” عبارت ” ۱، باید به خروجی منتقل شوند.
کاراکترهایی که برای تعیین فرمت خروجی مورد استفاده قرار می گیرند با کاراکتر %
شروع می شوند ( جدول ۱ ) .
کاراکتر | نوع اطلاعات که باید به خروجی منتقل شود |

%C | % یک کاراکتر | |
%d | % اعداد صحیح دهدهی مثبت و منفی | |
%i | % اعداد صحیح دهدهی مثبت و منفی | |
%e | % نمایش علمی عدد همراه با حرف e | |
%E | % نمایش علمی عدد همراه با حرف E | |
%f | % عدد اعشاری ممیز شناور | |
%g | % اعداد اعشاری ممیز شناور | |
%G | % اعداد اعشاری ممیز شناور | |
%O | % اعداد مبنای ۸ مثبت | |
%S | % رشته ای از کاراکترها ( عبارت رشته ای ) | |
%U | % اعداد صحیح بدون علامت ( مثبت ) | |
%x | % اعداد مبنای ۱۶ مثبت با حروف کوچک | |
%X | % اعداد مبنای ۱۶ مثبت با حروف بزرگ | |
%p pointer | % ( اشاره گر ) | |
%n | % موجب میشود تا تعداد کاراکترهایی که تا قبل | |
| ازاین کاراکتر به خروجی منتقل شده اند شمارش | |
| شده و در پارامتر متناظر با آن قرار گیرد . | |
%% | % علامت % |

جدول (۱) . کاراکترهای فرمت در تابع ()printf

کاراکترهای کنترلی که در تابع ()printf بکار میروند در جدول (۲) آمده است .
بعضی از کاراکترهای کنترلی برای انتقال خروجی به یک محل معین از صفحه نمایش
مورد استفاده قرار می گیرند .
| کاراکتر عملی که انجام می شود |

\f | \ موجب انتقال کنترل به صفحه جدید می شود | |
\n | \ موجب انتقال کنترل به خط جدید می شود | |
\t | \ انتقال به ۸ محل بعدی صفحه نمایش | |
\” | \ چاپ کوتیشن (“) | |
\’ | \ چاپ کوتیشن (‘) | |
\۰ NULL | \ رشته تهی | | back slash | \\ |
|
\V | \ انتقال کنترل به ۸ سطر بعدی | |
\N | \ ثابت های مبنای ۸( N( عدد مبنای ۸ است ) | |
\xN | \ ثابت های مبنای ۱۶( N( عدد مبنای ۱۶ است ) |

جدول (۲) . کاراکترهای کنترلی

چند دستور متوالی که شامل تابع ()print باشند ، خروجی خود را بر روی یک سطر
منتقل یم کنند . مگر این که با پارامتر کنترلی \n کنترل را به سطر بعدی منتقل
کنیم .
مثال ۱:

main)(

{

printf(" i like %c "/'c' );

printf("%s"/"very much." );

}

خروجی حاصل از اجرای برنامه فوق بصورت ذیل خواهد بود : i like c very much.

با استفاده از \n می توانیم خروجی را در چند سطر داشته باشیم . main)(
{
printf(“this is second program.\n” );
printf(“output is in two line.” );
}

خروجی حاصل از اجرای برنامه فوق بصورت ذیل است : this is second program.
output is in two line.

مثال ۲: main)(
{
int num ;
printf(“the address of num is:” );
printf(” %p”/ &num );
}

در مثال فوق عبارت &num آدرس متغیر num را مشخص می کند که برای نوشتن آن از
کاراکتر فرمت %p استفاده شده است . نمونه ای از خروجی مثال ۲ بصورت زیر است . the address of num is : 6A30:OFE4

اگر در تابع ()printf چند کاراکتر فرمت داشته باشیم ، هر کاراکتر با یک عنصر
داده که باید به خروجی برود تطبیق داده می شود : main)(
{
int a=10 ;
float b=20 ;
printf(” a is:%d/b is :%f”/a/b);
}

خروجی حاصل از اجرای برنامه فوق بصورت ذیل است : a is:10/b is:20:000000

مثال ۳: main)(
{
unsigned int num ;
num=100 ;
printf(“the value of num is:%u”/num);
}

همانطوری که در مثال ۳ مشاهده می شود ، برای چاپ عدد num که بصورت عدد صحیح
بدون علامت تعریف شد ، از %u استفاده شده است .
خروجی حاصل از اجرای برنامه مثال ۳ به صورت ذیل است : the value of num is:100

مثال ۴: main)(
{
double d ;
d=le+007 ;
printf(“the value of d is:%e\n”/d);
printf(“the value of d is:%E\n”/d);
printf(“the value of d is:%g\n”/d);
}

خروجی حاصل از اجرای برنامه مثال ۴ بصورت ذیل خواهد بود : the value of d is:1.00000e+07
the value of d is:1.00000E+07
the value of d is:1e+07

همانطور که مشاهده می شود برای چاپ اعدادی که بصورت نماد علمی باشند میتوان
از کاراکترهای فرمت % e، % E،و % gو استفاده کرد .

مثال ۵: main)(
{
float f=12.50 ;
int t=10 ;
printf(“\n f is:%f”/f );
printf(” tenper is:%%%d”/t );
}

خروجی حاصل از اجرای برنامه فوق بصورت زیر است : f is:12.500000/tenper is:%10

در مثال ۵ برای چاپ علامت % از کاراکتر %% و برای چاپ متغیر f از نوع float
می باشد از %f استفاده شده است .
کاراکتر فرمت %n از سایر کاراکترهای فرمت متفاوت است . این کاراکتر بجای
انتقال مقادیری به خروجی ، موجب می شود تا تعداد کارکترهایی که تا قبل از این
کاراکتر به خروجی منتقل شده اند ، شمارش شده و در پارامتر متناظر با آن قرار
بگیرد .

مثال ۶: main)(
{
printf(“\neach\tword\tis\n” );
printf(“tabbed\tover\tonce” );
}

خروجی از اجرای برنامه فوق بصورت زیر خواهد بود : each word is
tabbed over once

کاراکتر کنترلی \b موجب انتقال مکان نما به اندازه یک کاراکتر به عقب میشود
( بسمت چپ ). کاراکترهای کنترلی \ “و \و برای چاپ کوتیشن درخروجی مورد استفاده
قرار می گیرند .

تعیین طول میدان در تابع ()printf
در حین انتقال اطلاعات توسط تابع ()printf میتوانیم طول میدان خروجی را مشخص
کنیم . در این مورد می توانیم محل نقطه اعشار و تعداد ارقام اعشار را نیز تعیین
کنیم . تعیین طول میدان در جدول بندی ها بسیار مفید است . طول میدان ، بصورت w.d
است که در اعداد اعشاری ممیز شناور ، w طول میدان و d تعداد ارقام اعشار را
مشخص می کند .

مثال ۷: main)(
{
printf(“\n%8.1f %8.1f %8.1f\n”
/3.0/12.5/523.3 );
printf(“\n%8.1f %8.1f %8.1f\n”
/300.0/1200.5/5300.3 );
}

خروجی حاصل از اجرای برنامه فوق بصورت زیر است : ۳٫۰ ۱۲٫۵ ۵۲۳٫۳
۳۰۰٫۰ ۱۲۰۰٫۵ ۵۳۰۰٫۳

همانطورکه مشاهده می گردد طول میدان برابر با ۸ و تعداد ارقام اعشار، برابر
با یک که در منتهاالیه سمت راست میدان قرار گرفته ، منظور شده است . برای توضیح
بیشتر ، عدد ۵۳۰۰/۳ را در حافظه نشان می دهیم :
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | | ۵ | ۳ | ۰ | ۰ | . | ۳ |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
اگر فرمت w.d که طول میدان را مشخص می کند در مورد رشته ها استفاده گردد ، w
حداقل طول میدان و d حداکثر کاراکترهای قابل چاپ را مشخص می کند .
اگر w.d در مورد اعداد صحیح بکار برده شود ، w مشخص کننده حداقل طول میدان
و d تعیین کننده حداکثر طول میدان است .

مثال ۸: main)(
{
printf(“%7.4f\n”/123.1234567 );
printf(“%3.8d\n”/1000 );
printf(“%10.16a\n”/”this is a” );
printf(” simple test” );
}

خروجی حاصل از اجرای برنامه فوق بصورت زیر است : ۱۲۳٫۱۲۳۵
۰۰۰۰۱۰۰۰
this is a simple

در خروجی اول ، تعداد ارقام اعشاری ۴ در نظر گرفته شده که بقیه ارقام حذف
شده اند و ضمنا” عدد حاصل گرد شده است .
در خروجی دوم که : میدان ۳/۸ است عدد صحیح ۱۰۰۰ چاپ شده است .
در خروجی سوم از رشته this is a simple به اندازه ۱۶ کاراکتر چاپ شده است .
در حالت معمولی ، خروجی حاصل در سمت راست میدان قرار می گیرد که می توان با
قرار دادن علامت منها ( – ) بلافاصله پس از علامت % ، اطلاعات را در سمت چپ میدان
 
تابع ()scanf

این تابع برای خواندن اطلاعات از ورودی استاندارد ( صفحه کلید ) بکار رفته و
بصورت زیر استفاده می شود : ;
(آدرس متغیرها ، ” کاراکترهای فرمت “) scanf
کاراکترهای فرمت ، نوع اطلاعاتی که باید خوانده شوند را مشخص می کند. و آدرس
متغیرها، مشخص کننده محل هایی از حافظه هستند که اطلاعات ورودی باید درآن محلها
قرار گیرند. همانطور که قبلا” دیده ایم آدرس متغیرها را با عملگر & مشخص میکنیم .
در تابع scanf همانند تابع printf از تعدادی کاراکترهای فرمت استفاده می شود .
( جدول ۱ ) .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
| کاراکتر اطلاعاتی که خوانده می شوند |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
%c | % یک کاراکتر | |
%d | % یک عدد صحیح دهدهی | |
%i | % یک عدد صحیح دهدهی | |
%e | % عدد اعشاری ممیز شناور | |
%f | % عدد اعشاری ممیز شناور | |
%g | % عدد اعشاری ممیز شناور | |
%o | % عدد مبنای ۸ | |
%x | % عدد مبنای ۱۶ | |
%p | % یک اشاره گر | |
%n | % مشخص کننده تعداد کاراکترهایی است که تا | %%n |
| ورودی خوانده شده اند | |
%u | % عدد صحیح مثبت | |
%s | % رشته ها |
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
جدول (۱) . کاراکترهای فرمت در تابع ()scanf

مثال ۱: main)(
{
char ch ;
printf(“\n enter a character :”);
scanf(“%c”/&ch );
printf(“\n ch=%c”.ch );
}

اجرای فرمان فوق ، ضمن صدور یک پیام ، کاراکتری را از ورودی خوانده در متغیر ch
قرار می دهد . نمونه ای از خروجی را در زیر مشاهده می کنیم : enter a character : s
ch=s

مثال ۲: main)(
{
int year ;
printf(“enter your age in year:”);
scanf(“%d”/&year );
printf(“\n your age is”);
printf(” %d day.”/year*365);
}

نمونه ای از خروجی را در زیر مشاهده می کنیم : enter your age in year:19
your age 6935 day.

این برنامه ، سن شما را از ورودی دریافت کرده و آن را به روز تبدیل میکند و
سپس به خروجی می برد . لازم به ذکر است که در مثال ۲ تابع ()scanf بر روی خطی
عمل می کند که تابع ()printf اولی عمل کرده است . تابع ()printf دومی به علت
وجود \n ، بر روی خط بعدی از صفحه نمایش عمل خواهد کرد . استفاده از سایر
کاراکترهای قالب در تابع ()scanf همانند تابع ()printf است که ذکر مثال درمورد
آنها ضروری به نظر نمی رسد .
قالب دیگری که باید در مورد آن توضیح داده شود %n است که مشابه آن را در
تابع ()printf داشته ایم . %n در تابع ()scanf تعداد کاراکترهای خوانده شده توسط
این تابع تا %n را به متغیری که آدرس آن متناظر با %n ذکر شده است منتقل میکند.
برای خواندن چند متغیر از ورودی توسط تابع ()scanf ، اسامی متغیرها را که
به همراه & ( عملگر آدرس ) ذکر می شوند با کاما از یکدیگر جدا کرده و در حین
ورود اطلاعات می توانیم آنها را با فاصله (blank) ، کلید enter و یا tab جدا
کنیم .

مثال ۳: main)(
{
int a/b/c ;
float ave ;
printf(“\n enter three number :”);
scanf(“%d %d %d”/&a/&b/&c );
ave=(a+b+c)/3 ;
printf(“\n average is:%f”/ave );
}

به نتیجه اجرای برنامه و چگونگی ورود سه عدد ۲۰ ، ۱۹ و ۱۸ بعنوان اطلاعات
ووردی توجه کنید : enter three number :20 19 18
av
 
خواندن یک کاراکتر از ورودی

برای خواندن یک کاراکتر از ورودی ، علاوه بر تابع ()scanf از توابع دیگری نیز
استفاده میشود که قبل از بررسی آنها به مثالی از()scanf جهت خواندن یک کاراکتر
توجه کنید :
مثال ۱: main)(
{
char ch ;
printf(“enter a character : ” );
scanf(“%c”/&ch );
printf(” you typed the character”);
printf(“: %c”/ch );
}

نمونه ای از خروجی حاصل از مثال ۱ بصورت زیر است : enter a character: j
you typed the character:j

تابع ()getch
این تابع برای خواندن یک کاراکتر از ورودی بکار می رود و بصورت زیر استفاده
می شود :
()= getch متغیر
پس از آن که کنترل اجرای برنامه به تابع ()getch رسید ، برنامه منتظر فشار
دادن کلیدی از صفحه کلید می شود . اگر متغیر مورد نظر کاراکتری باشد مقدار
کاراکتری کلید ورود به این متغیر منتقل می شود و در صورتی که این متغیر از نوع
عددی باشد ، کد اسکی کلید وارد شده ، در این متغیر قرار می گیرد .

مثال ۲: main)(
{
char ch ;
int x ;
printf(“\n enter a character : ” );
ch=getch )(;
printf(“\n enter this character” );
printf(” second time :” );
ch=getch )(;
printf(“\n character is:” );
printf(“%c/%c/%d/%d/ch/x/ch/x );
}

فرض کنید در پاسخ به اجرای این برنامه کلید s را دوبار در پاسخ به دو تابع
()getch وارد کنیم . در این صورت خروجی حاصل از اجرای برنامه بصورت زیر خواهد
بود : enter a character:
enter this character second time:
character is:s/s/115/115

اگر در مثال ۲ به تابع ()printf توجه کنید ، متغیر chو xو را یکبار با فرمت %c
و بار دیگر با فرمت %d نوشته ایم که در هر دو حالت عدد ۱۱۵ که کد اسکی s است
چاپ شده است . وقتی متغیر عددی x را با فرمت %d نوشته ایم آنچه که در آن قرار
گرفته ( کد اسکی کلید s ) نوشته شده است و زمانی که این متغیر را با فرمت %c
نوشته ایم کد اسکی به کاراکتر s تبدیل شده و سپس در خروجی چاپ می شود .

تابع ()getche
این تابع همانند تابع ()getch برای خواندن یک کاراکتر از ورودی بکار می رود
و بصورت زیر استفاده می شود :
()= getche متغیر
نوع عمل این تابع مثل ()getch است . با این تفاوت که این تابع پس از اخذ
ورودی ، آن را روی صفحه نمایش چاپ می کند . حرف e در انتهای تابع به معنی echo
( عکس العمل ) است .

تابع ()getchar
این تابع همانند توابع ()getch و ()getche برای خواندن یک کاراکتر از ورودی
بکار رفته و بصورت زیر استفاده می شود :
()= getchar متغیر
نوع عمل این تابع همانند دو تابع فوق الذکر است . با این تفاوت که در این
تابع پس از وارد نمودن کلیه ( کاراکتر ) مورد نظر ، کلید enter نیز باید وارد اله در توربو C رعایت می شود )
 
نوشتن یک کاراکتر در خروجی

برای نوشتن یک کاراکتر در خروجی علاوه بر تابع ()printf ، دو تابع دیگر نیز
معمولا” مورد استفاده قرار میگیرند. قبل از بررسی آنها به مثالی درمورد ()print
که منجر به چاپ یک کاراکتر در خروجی می گردد . می پردازیم . main)(
{
printf(“example for character”);
printf(“: %c”/’a’ );
}

خروجی حاصل از اجرای برنامه فوق ، حرف a است . example for character :a

تابع ()putch
این تابع برای نوشتن یک کاراکتر در صفحه نمایش مورد استفاده قرار گرفته و
بدین صورت استفاده می شود : ;
( متغیر ) putch

مثال ۱: main)(
{
char ch ;
printf(“\n enter a character: “);
ch=getch )(;
printf(“you typed the character:”);
putch(ch );
}

خروجی حاصل بصورت زیر است : enter a character:
you typed the character : s

برای نوشتن یک کاراکتر توسط تابع ()putch این تابع را بصورت زیر هم می توان
بکار برد : putch(‘a’);

دستور فوق موجب چاپ کاراکتر a در خروجی می شود .

تابع ()putchar
این تابع همانند تابع ()putch برای نوشتن یک کاراکتر در صفحه نمایش به کار
می رود و بصورت زیر استفاده می شود : ;
( متغیر )putchar

مثال ۲: #include “stdio.h”
main)(
{
char ch ;
printf(“enter a character :” );
ch=getch )(;
printf(“\n you typed: ” );
putchar(ch );
}

به نمونه ای از خروجی برنامه مثال ۲ که در زیر آمده است توجه کنید : enter a character:
you typed : s
برای نوشتن حرف a در خروجی تابع ()putchar بصورت ;(‘a’)putch بکار می رود .
 
ساختارهای تکرار ، تحت شرایط خاصی امکان اجرای مکرر دستور یا مجموعه ای از
دستورات را فراهم میکنند. این ساختارها در زبان های برنامه سازی مختلف به اشکال
متفاوتی وجود دارند که ذیلا” انواع مختلف این ساختارها در زبان C ، مورد بررسی
قرار می گیرد .

ساختار تکرار for
ساختار for یکی ازامکانات ایجاد حلقه تکرار میباشد که بصورتهای زیر استفاده
می شود :
(َ۱) ;دستور(گام حرکت ;شرط حلقه ;مقدار اولیه اندیس حلقه ) for
(َ۲) (گام حرکت ;شرط حلقه ;مقدار اولیه اندیس حلقه ) for {

مجموعه دستورات }
for(;;( )3)
{

مجموعه دستورات }

نکاتی که باید در مورد نحوه کاربرد ساختار تکرار for در نظر داشت عبارتند
از : ۱
دستوری که بعد از ساختار for آمده است می تواند در خط دیگری تایپ شود . ۲
ساختار forبه ; ختم نمی شود . زیرا در غیر این صوتر مجموعه دستوراتی که
اجرای آنها باید تکرار شود ، فقط یک بار اجرا خواهند شد . ۳
علامت { در نحوه کاربرد دوم و سوم ، می توانند در همان خطی که ساختار for
آمده است قرار گیرند . ۴
بعد از اولین مقدار اندیس حلقه و شرط حلقه ; قرار می گیرد .
ساختار for در مواردی مفید است که تعداد دفعات تکرار مجموعه ای از دستورات
معلوم باشد ، هر حلقه تکرار دارای یک شمارنده است که تعداد دفعات تکرار اجرای
دستورات داخل حلقه را مشخص می کند. این شمارنده ، اندیس حلقه نامگذاری می شود.
اندیس حلقه می تواند مثبت ، منفی ، صحیح و یا اعشاری باشد . مقدار اولیه اندیس
حلقه مشخص می کند که شمارنده ، از چه مقداری شروع می شود. شرط حلقه مشخص میکند
که مجموعه دستورات داخل حلقه تکرار ، تحت چه شرایطی اجرا می شوند . گام حرکت
مشخص می کند که در هر بار اجرای مجموعه دستورات داخل تکرار ، چه مقداری به
شمارنده حلقه اضافه می شود . گام حرکت می تواند مثبت منفی ، صحیح و یا اعشاری
باشد . بعنوان مثال در دستور : for( i=0;i<5;i++)
printf(“\n the value of i is:%d / i);
i
اندیس حلقه تکرار است که مقدار اولیه آن برابر با صفر است . شرط حلقه
تکرار این است که i کوچکتر از ۵ باشد و گام حرکت نیز ۱ است که با i++ مشخص شده
است . خروجی حاصل از اجرای این دستور بصورت زیر است : ۰
۱
۲
۳
۴

مثال ۱: برنامه ای که تعداد ۱۰ عدد را از ورودی خوانده ، میانگین آنها را
محاسبه کرده و به خروجی می برد : main)(
{
int i / sum=0 / num ;
float ave ;
for(i=1 ; i<=10 ; i++)
{
printf(“enter number %d: “/i );
scanf(“%d”/&num );
sum+=num ;
printf(“\n” );
}
ave-sum/10 ;
printf(“\n the average is:%f “/ave);
}

خروجی حاصل از اجرای برنامه مثال ۱ : enter number 1 : 12
enter number 2 : 13
enter number 3 : 17
enter number 4 : 18
enter number 5 : 16
enter number 6 : 20
enter number 7 : 23
enter number 8 : 28
enter number 9 : 31
enter number 10 : 14

the average is:19.000000

مثال ۲: برنامه زیر جدول کدهای اسکی را در خروجی چاپ می کند : main)(
{
int i ;
for(i=41 ; i<=120 ; i++)
{
printf(“%3d=%c\t”/i/i );
if(i%5==0 )printf(“\n” );
}
}

برنامه فوق با چند دستور ساده توانسته است جدول زیر را در خروجی چاپ کند . ۴۱= )۴۲=* ۴۳=+ ۴۴=/ ۴۵=-
۴۶= .۴۷=/ ۴۸=۰ ۴۹=۱ ۵۰=۲
۵۱=۳ ۵۲=۴ ۵۳=۵ ۵۴=۶ ۵۵=۷
۵۶=۸ ۵۷=۹ ۵۸= :۵۹=; ۶۰=<
61== 62=> 63=? 64=@ 65=A
66=B 67=C 68=D 69=E 70=F
71=G 72=H 73=I 74=J 75=K
76=L 77=M 78=N 79=O 80=P
81=Q 82=R 83=S 84=T 85=U
86=V 87=W 88=X 89=Y 90=Z
91=[ 92=\ 93=] 94=^ 95=_
96=` 97=a 98=b 99=c 100=d
101=e 102=f 103=g 104=h 105=i
106=j 107=k 108=l 109=m 110=n
111=o 112=p 113=q 114=r 115=s
116=t 117=u 118=v 119=w 120=x

اگر بخواهیم این برنامه را در زبانهای دیگر بنویسیم ، برنامه طولانی تری به
دست می آید .

مثال ۳: برنامه ای که جدول ضرب اعداد از ۱ تا ۱۰ را درصفحه نمایش چاپ میکند. main)(
{
int i/j ;
for(i=1 ; i<=10 ; i++)
{
for(j=1 ; j<=10 ; j++)
printf(“%3d “/i*j );
printf(“\n” );
}
}

خروجی حاصل از برنامه فوق : ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰
۲ ۴ ۶ ۸ ۱۰ ۱۲ ۱۴ ۱۶ ۱۸ ۲۰
۳ ۶ ۹ ۱۲ ۱۵ ۱۸ ۲۱ ۲۴ ۲۷ ۳۰
۴ ۸ ۱۲ ۱۶ ۲۰ ۲۴ ۲۸ ۳۲ ۳۶ ۴۰
۵ ۱۰ ۱۵ ۲۰ ۲۵ ۳۰ ۳۵ ۴۰ ۴۵ ۵۰
۶ ۱۲ ۱۸ ۲۴ ۳۰ ۳۶ ۴۲ ۴۸ ۵۴ ۶۰
۷ ۱۴ ۲۱ ۲۸ ۳۵ ۴۲ ۴۹ ۵۶ ۶۳ ۷۰
۸ ۱۶ ۲۴ ۳۲ ۴۰ ۴۸ ۵۶ ۶۴ ۷۲ ۸۰
۹ ۱۸ ۲۷ ۳۶ ۴۵ ۵۴ ۶۳ ۷۲ ۸۱ ۹۰
۱۰ ۲۰ ۳۰ ۴۰ ۵۰ ۶۰ ۷۰ ۸۰ ۹۰ ۱۰۰

مثال ۴: برنامه ای که تعداد حروف یک جمله را شمارش می کند ( انتهای جمله با
نقطه مشخص شده است ) . در این برنامه از دستور # include استفاده شده است . #include “stdio.h”
main)(
{
char ch ;
int count ;
for(count=0;(ch=getchar))(!=’.’
; count++ );
printf(“\n length of statement”);
printf(” is:%d”/count );
}

به نمونه ای از خروجی برنامه مثال ۴ توجه نمایید : i like C very much.
length of statement is:18

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

ساختار تکرار while while
( یکی از ساختارهای تکرار در زمان C ) در مواقعی مورد استفاده قرار
می گیرد که تعداد دفعات تکرار مجموعه دستورات مورد نظر مشخص نباشد .
ساختار while بصورت های زیر استفاده می شود : ;
دستور (شرط) while(1(
(شرط) while(2( {

مجموعه ای از دستورات }

وقتی که کنترل اجرای برنامه به ساختار while رسید ، شرطی که در آن ذکر شده
است تست می شود . اگر این شرط دارای ارزش منطقی ” درست ” باشد ، دستور یا
دستورات داخل حلقه تکرار اجرا میشوند واجرای این دستورات تا برقراری شرط مذکور
ادامه می یابد. لذا باید توجه داشت که در داخل بدنه حلقه تکرار ، شرط حلقه نقض
شود ، وگرنه دستورات داخل حلقه ، بینهایت بار اجرا خواهند شد .

مثال ۵: برنامه ای که یک جمله رااز ورودی خوانده و تعداد کاراکترهای آن جمله
را شمارش می کند ( انتهای جمله به کلید enter ختم می شود ) . main)(
{
int count=0 ;
printf(“type a statement and ENTER”);
printf(” to end.”);
while(getche )(!=’\r’)
count ++ ;
printf(“\n length of statement is:”);
printf(“%d/count );
}

حلقه های تکرار بینهایت
با استفاده از ساختارهای تکرار forو whileو می توانیم حلقه های تکراری درست
کنیم که جهت ختم آنها باید از کلید CTL+BREAK استفاده کرد . به این حلقه های
حلقه های بینهایت گفته می شود . برای ساختن حلقه تکرار از while می توانیم بجای
شرط از یک (۱) به معنی ارزش درستی ، استفاده کنیم .

مثال ۶: برنامه ای که تعداد نامحدودی عدد رااز ورودی خوانده و فاکتوریل آنها
را محاسبه می کند :
جهت ختم اجرای برنامه باید از CTL+BREAK استفاده نمود . main)(
{
long int answer ;
int number ;
while(1)
{
printf(“\n type number: ” );
scanf(“%d/&number );
answer=1 ;
while(number>1)
answer*=number –;
printf(“\n factorial is: ” );
printf(“%1d\n”/answer );
}
}

به نمونه ای از خروجی برنامه مثال ۶ توجه نمایید : type number: 5
factorial is: 120

type number: 4
factorial is: 24
type number: 6
factorial is: 720

type number: ^c

همانطور که قبلا” گفته شد برای ساختن حلقه تکرار بینهایت از ساختار for کافی
است که این ساختار را بصورت (;;)for بکار ببریم ( مثال ۷ ) .

مثال ۷: مساله محاسبه فاکتوریل ( مثال ۶ ) با استفاده از حلقه for : main)(
{
long int answer ;
int number ;
for(;;)
{
printf(“\n type number: ” );
scanf(“%d/&number );
answer=1 ;
while(number>1)
answer*=number –;
printf(“\n factorial is: ” );
printf(“%1d\n”/answer );
}
}

ساختار تکرار do
ساختار تکرار do مشابه ساختار تکرار while است . با این تفاوت که در ساختار while
شرط حلقه در ابتدای حلقه تست میشود ولی در ساختار do شرط حلقه در انتهای
حلقه تکرار تست خواهد شد. لذا در ساختار do مجموعه دستورات داخل ساختار، حداقل
یکبار انجام می شوند . این ساختار بصورت زیر استفاده می شود : do
{
;
مجموعه دستورات ;
(شرط) } wwhile
وقتی کنترل اجرای برنامه به ساختار do رسید مجموعه دستورات داخل حلقه تکرار
اجرا می شوند و سپس شرط ذکر شده در این ساختار تست می گردد . چنانچه این شرط
برقرار باشد مجموعه دستورات داخل حلقه تکرار مجددا” اجرا می شود ، وگرنه کنترل
اجرای برنامه از حلقه تکرار خارج می گردد .

مثال ۸: برنامه ای که عددی را از ورودی خوانده و سپس آنرا بصورت معکوس در
خروجی چاپ می کند .
مثلا” عدد ۲۱۵۳ را بصورت ۳۵۱۲ چاپ می نماید . main)(
{
int number / digit ;
printf(“enter a number: ” );
scanf(“%d/&number );
do {
digit=number%10 ;
printf(“%d/digit );
number/=10 ;
}while(number!=0 );
}

نمونه ای از خروجی حاصل از اجرای برنامه مثال ۸ : enter a number:2153
3512

ساخت حلقه های تکرار بینهایت با استفاده از ساختار do نیز امکان پذیر است . استفاده گردد .
 
ساختارهای تکرار،امکانات خوبی برای تکرار اجرای مجموعه ای از دستورات برنامه
می باشند . اما اگر بخواهیم تحت شرایطی که در برنامه اتفاق می افتد تصمیم گیری
لازم را داشته باشیم بطوری که تحت شرایطی ، مجموعه ای از دستورات اجرا شوند و
مجموعه ای دیگر از دستورات اجرا نشده وکنترل اجرای برنامه بجای دیگر منتقل شود
به ابزار دیگری بنام ساختارهای تصمیم نیاز داریم . این ساختارها در زبان های
برنامه سازی مختلف به اشکال متفاوتی وجود دارند که انواع مختلف آن را در زبان C
بررسی می کنیم .
ساختار تصمیم if
ساختار if ( که ساختار انتقال کنترل شرطی نیز نامگذاری میشود ) موجب میگردد
تا تحت شرایطی ، مجموعه ای از دستورات اجرا شده و یااز اجرای این مجموعه دستورات
صرفنظر گردد . این ساختار بصورت های زیر مورد استفاده قرار می گیرد .
(َ۱) ;دستور (شرط) if
(َ۲) (شرط) if {
مجموعه دستورات ۱ }
else
{
مجموعه دستورات ۲ }
در روش (۱) ، شرط ذکر شده بررسی می شود و در صورت برقرار بودن ، دستور بعد
از آن اجرا می شود و در غیر اینصورت کنترل اجرای برنامه به دستور بعد از if
منتقل می گردد .
در روش (۲) ، شرط ذکر شده بررسی می شود و در صورت برقرار بودن ، مجموعه
دستورات (۱) اجرا میشوند و در غیر اینصورت مجموعه دستورات (۲) اجرا خواهند شد.
لازم به ذکر است که وجود else در ساختار if اختیاری است . یعنی ساختار if را
بصورت زیر نیز می توان بکار برد :
(شرط) if {
مجموعه دستورات }
در روش فوق پس از این که کنترل اجرای برنامه به if رسید شرط مورد نظر بررسی
می شود . چنانچه این شرط برقرار باشد ، مجموعه دستورات داخل {و }و ( که یک بلاک
نامیده می شود ) اجرا می گردد وگرنه کنترل اجرای برنامه به اولین دستور بعد از
بلاک if منتقل خواهد شد . استفاده از ساختار if بصورت لانه ای ( تو در تو ) نیز
امکان پذیر است که در اینصورت اولین else به آخرین if بر می گردد .
مثال ۱: برنامه ای که با خواندن یک جمله از ورودی ، تعداد کاراکترها و کلمات
موجود در جمله را محاسبه می کند . کلمات با فاصله (blank) از یکدیگر جدا شده و
انتهای جمله به کلید enter ختم می گردد . main)(
{
int charcount=0 ;
int wordcount=0 ;
char ch ;
printf(“type a statement:\n” );
while((ch=getche))(!=’\r’)
{
charcount ++ ;
if(ch==’ ‘)
wordcount ++ ;
}
printf(“\n character count is:”);
printf(“%d”/charcount );
printf(“\n word count is:”);
printf(“%d”/wordcount );
}
به نمونه ای از خروجی برنامه مثال ۱ توجه نمایید : type a statement:
this book is my fifth book.
character count is:27
word count is:6
مثال ۲: برنامه ای که بااستفاده از ساختار تصمیم if یک شکل گرافیکی را به کمک
کدهای اسکی DBو BOو رسم می کند . main)(
{
int x/y ;
for(y=1 ; y<11 ; y++)
{
for(x=1 ; x<11 ; x++)
{
if(x==y)
printf(“\xDB” );
else
if(x==11-y)
printf(“\xDB” );
else
printf(“\xBO” );
}
printf(“\n” );
}
}
مثال ۳: برنامه ای که تعداد کل کاراکترهای یک جمله و همچنین تعداد ارقام
موجود در آن را شمارش می کند . main)(
{
int charcnt=0 ;
int wordcnt=0 ;
char ch ;
printf(“\n enter a statement: \n” );
while((ch=getche))(!=’\r’)
{
charcnt++ ;
if(ch>=47 && ch<=58)
digthcnt++ ;
}
printf(“\n character count is:” );
printf(“%d”/charcnt );
printf(“\ndigit count is:”);
printf(“%d”/digtcnt);
}
به نمونه ای از خروجی برنامه مثال ۳ توجه نمایید : type a statement:
my telephone number is 817694.
character count is:31
digit count is:6
نکته ای که باید در مورد برنامه مثال ۳ توضیح داد این است که در دستور if
جهت تشخیص این که ، آیا کاراکتر وارد شده ، یکی از ارقام ۰تا ۹ا است یا خیر
از اعداد ۴۷ و ۵۸ استفاده شده است . زیرا کدهای اسکی ارقام ۰تا ۹ا در بین این
دو عدد ( از ۴۸ تا ۵۷ ) می باشند .
ساختار تصمیم else if
تاکنون ساختار if را مطالعه نمودیم و مثال هایی را در این زمینه مشاهده
کردیم . نکته ای باید به آن توجه داشت این است که اگر در ساختارif خواسته باشیم
چندین شرط را مورد بررسی قرار دهیم ، باید ساختار if را به صورت تودرتو بکار
ببریم که نه تنها موجب طولانی شدن برنامه می گردد ، بلکه خوانایی آن را نیز
پایین می آورد . ساختار else if که یک ساختار انتقال کنترل شرطی است می تواند
در این زمینه به ما کمک کرده تا بتوانیم از افزایش بی رویه طول برنامه جلوگیری
کنیم .
جهت روشن شدن مطلب به دو برنامه بعدی ( مثالهای ۴، ۵ ) که یکی با ساختار if
و دیگری با ساختار else if برای حل یک مساله نوشته شده اند توجه کنید . این
برنامه ها دو عدد و یکی از عملگرهای چهار عمل اصلی را از ورودی خوانده و عملگر
را بر روی دو عدد اجرا می کنند .
مثال ۴: main)(
{
int num1 / num2 ;
char op ;
while(1)
{
printf(“type number/operator/”);
printf(“number \n” );
scanf(“%d%c%d”/&num1/&op/&num2);
if(op==’+')
printf(“\n sum=%d”/num1+num2);
else
if(op==’-')
printf(“\nsubtract=%d”/num1-num2);
else
if(op==’*')
printf(“\nmultiple=%d”/num1*num2);
else
if(op==’/')
printf(“\ndivition=%d”/num1+num2);
else
printf(“\n operator is illegal”);
printf(“\n\n” );
}
}
به نمونه ای از خروجی برنامه مثال ۴ توجه نمایید : type number/operator/number
12 + 23
sum=35
type number/operator/number
2*26
multiple=52
type number/operator/number
4%2
operator is illegal
type number/operator/number
^c
مثال ۵: main)(
{
int num1 / num2 ;
char op ;
while(1)
{
printf(“type number/operator/”);
printf(“number \n” );
scanf(“%d%c%d”/&num1/&op/&num2);
if(op==’+')
printf(“\n sum=%d”/num1+num2);
else if(op==’-')
printf(“\n subtract=%d”/num1-num2);
else if(op==’*')
printf(“\n multiple=%d”/num1*num2);
else if(op==’/')
printf(“\n divition=%d”/num1+num2);
else
printf(“\n operator is illegal”);
printf(“\n\n” );
}
}
همانطورکه ملاحظه میشود برنامه ای که با ساختار else if نوشته شده است ( مثال ۵
) کوتاهتر بوده و از خوانایی بهتری برخوردار است . لذا توصیه می شود که در
این گونه موارد از else if بجای ساختار if استفاده گردد .
انتقال کنترل غیرشرطی
ساختارهای ifو else ifو را تحت عنوان انتقال کنترل شرطی مورد بررسی قرار
داده ایم . چند دستور در زبان C وجود دارند که بدون تست کردن شرطی سبب انتقال
کنترل برنامه ، از جایی به جایی دیگر می شوند . نام این دستور انتقال کنترل
غیرشرطی می باشد که در ذیل مورد بررسی قرار می گیرند .
دستور goto
در زبان C علاوه بر ساختارهای تصمیم ، دستوری بنام goto نیز وجود دارد که سبب
انتقال کنترل اجرای برنامه ، از نقطه ای به نقطه دیگر می گردد. این دستور بصورت
زیر بکار می رود : ;
برچسب دستور goto
برچسب دستور ، همانند یک متغیر نامگذاری شده و به دو نقطه :)) ختم می شود .
پیشنهاد می گردد حتی الامکان از دستور goto که معمولا” سبب کاهش میزان خوانایی
برنامه می شود ، استفاده نگردد .
مثال ۶: برنامه ای که با استفاده از دستور goto یک حلقه تکرار می سازد . main)(
{
int x=1 ;
loop1:
x++ ;
if(x<100 )goto loop1 ;
printf(“\n the maximum value”);
printf(” of x is:%d”/x );
}
خروجی حاصل از اجرای برنامه مثال ۶ : the maximum value of x is:100
یکی از خواص gotoدر Cر این است که از تابعی به تابع دیگر نمی توان انشعاب
کرد و فقط انتقال کنترل در یک تابع امکان پذیر است . یعنی برچسب goto باید در
تابعی باشد که این دستور در آن تابع بکار رفته است .
دستور break
این دستور یکی از دستورات انتقال کنترل غیر شرطی است و به صورت زیر مورد
استفاده قرار می گیرد :
دستور break به دو منظور استفاده می شود : الف ) خاتمه داده به case در
ساختار switch ، ب ) خاتمه دادن به حلقه تکرار ( حلقه های تکرار ممکن با for do
یا whileا ساخته شوند ) . پس از اجرای دستور break در داخل ساختارهای تکرار
کنترل اجرای برنامه به اولین دستور پس از حلقه تکرار منتقل می شود .
مثال ۷: main)(
{
int t ;
for(t=0 ; t<100 ; t++)
{
printf(“%3d”/t );
if(t==5)
break ;
}
printf(“\nmaximum value of t is:”);
printf(“%d”/t);
}
خروجی حاصل از اجرای برنامه مثال ۷: ۰ ۱ ۲ ۳ ۴ ۵
maximum value of t is:5
همانطور که از خروجی برنامه پیداست پس از آن که مقدار tبه ۵ رسید کنترل
اجرای برناه از حلقه تکرار for خارج شده و با اجرای دستور printfعدد ۵د را چاپ
می کند . نکته ای که در مورد break باید توجه داشت این است که اگر دو یا چند
حلقه تکرار تودرتو داشته باشیم ، دستور break موجود در داخلی ترین حلقه ، فقط
موجب خروج از همین حلقه تکرار می شود .
مثال ۸: main)(
{
int t ;
for(t=0 ; t<100 ; t++)
{
count=1 ;
printf(“\n” );
for(;;)
{
printf(“%3d”/count );
count ++ ;
if(count==4 )break ;
}
}
}
خروجی حاصل از اجرای برنامه مثال ۸: ۱ ۲ ۳
۱ ۲ ۳
۱ ۲ ۳
۱ ۲ ۳
۱ ۲ ۳
۱ ۲ ۳
در دو مثال ۷و۸و دوحلقه تکرار وجوددارد که حلقه داخلی یک حلقه بینهایت است .
در این حلقه ر گاه مقدار countبه ۴ برسد ، کنترل اجرای برنامه از این حلقه
خارج می شود .
دستور continue
دستور continue در یک حلقه تکرار ، موجب انتقال کنترل به ابتدای حلقه تکرار
شده ، بصورت زیر استفاده می شود : continue;
پس از اجرای این دستور کنترل به ابتدای حلقه برگشته و شرط حلقه تست می گردد
که در صورت برقرار بودن شرط ، مجموعه دستورات داخل حلقه تکرار مجددا” اجرا
می شوند وگرنه کنترل از حلقه تکرار خارج خواهد شد .
مثال ۹: برنامه ای که کاراکتری را از ورودی دریافت کرده و این کاراکتر و
کاراکتر بعد از آن را به خروجی می برد . main)(
{
char done=0 / ch ;
while(!done)
{
printf(“\n type a character / “);
printf(“& for exit :”);
ch=getch)(;
printf(“\n you typed the”);
printf(“character: %c”/ch);
if(ch==’&’)
{
done=1 ;
continue ;
}
printf(“\nthe next character is:”);
printf(“%c”/ch+1 );
}
}
به نمونه ای از خروجی برنامه مثال ۹ توجه نمایید : type a character /& for exit:
you typed the character: a
the next character is:b
type a character /& for exit:
you typed the character: b
the next character is:c
type a character /& for exit:
you typed the character: &
ساختار switch
ساختار switch که یکی از ساختارهای جالب جهت بالا بردن توانایی برنامه است
بصورت زیر استفاده می شود :
( عبارت ) switch {
:مقدار case 1
مجموعه دستورات ۱ break;
:مقدار case 2
مجموعه دستورات ۲ break;
.
.
.
default:
مجموعه دستورات }
نحوه عمل ساختار switch بدین صورت است که : عبارت ذکر شده در switch ارزیابی
می شود ، سپس نتیجه ارزیابی از بالا به پایین با مقادیر ذکر شده ( مقدار ۱
مقدار ۲ و … ) مقایسه می شود ( ابتدا با ” مقدار ” ۱ مقایسه می گردد ) اگر
نتیجه ارزیابی بااین مقدار برابر باشد مجموعه دستورات داخل آن case اجرا میشود
و با دستور break کنترل اجرای برنامه از این ساختار خارج می شود . اگر نتیجه
ارزیابی با ” مقدار ” ۱ برابر نباشد ، مقایسه با ” مقدار ” ۲ انجام می شود و
این روند تا انتهای این ساختار ادامه پیدا می کند . اگر هیچکدام از مقادیری که
در case ذکر شده اند با نتیجه ارزیابی ” عبارت ” برابر نباشند ، مجموعه دستورات
پس از defaule اجرا می شود . defaule اختیاری است و ممکن است در ساختار switch
استفاده نگردد. در این صورت اگر هیچکدام از مقادیر ۱، ۲ و… با نتیجه ارزیابی ”
عبارت ” برابر نباشند ، کنترل به بعد از ساختار switch برخواهد گشت .
حداکثر تعداد case که در یک ساختار switch می تواند قرار گیرد برابر با ۲۵۷
است .
نکاتی که در مورد ساختار switch باید در نظر داشت عبارتند از : ۱
این ساختار با ساختار if از این جهت متفاوت است که در ساختار switch فقط
مساله ” مساوی بودن “(equality() مطرح است اما در ساختار if می توان یک عبارت
منطقی و یا رابطه ای را مورد بررسی قرار داد . ۲
دو یا چند case در ساختار switch نمی توانند یک مقدار مساوی را مورد تست
قرار دهند . بعضی در نحوه کاربرد ساختار switch ، مقدار ۱ ، مقدار ۲ و …
نمی توانند با یکدیگر برابر باشند . ۳
اگر ثابت های کاراکتری در ساختارswitch بکار گرفته شوند، آنها به مقادیر ”
صحیح ” تبدیل می شوند . ۴
اگر در یک case از دستور break استفاده نشود پس از اجرای مجموعه دستورات
مربوط بخ این case مجموعه دستورات موجود در case بعدی نیز اجرا می شوند . ۵
دو یا چند شرط را می توان در ساختار switch با یکدیگر OR نمود که برای
این منظور کافی است چند case را با مقادیری که می خواهیم با هم OR شوند پشت سر
هم ذکر کنیم ( مثال ۱۱ ) .
مثال ۱۰: برنامه ای که دو عدد و یکی از عملگرهای چهار عمل اصلی را از ورودی
خوانده و عملگر را بر روی دو عدد عمل می کند . main)(
{
int num1 / num2 ;
char op ;
while(1)
{
printf(“type number/operator/”);
printf(“number \n” );
scanf(“%d%c%d”/&num1/&op/&num2);
switch(op)
{
case ‘+’:
printf(“\nsum=%d”/num1+num2);
break ;
case ‘-’:
printf(“\nsubtract=%d”/num1-num2);
break ;
case ‘*’:
printf(“\nmultiple=%d”/num1*num2);
break ;
case ‘/’:
printf(“\ndivition=%d”/num1+num2);
break ;
default:
printf(“\n operator is illegal”);
printf(“\n\n” );
}
}
به نمونه ای از خروجی حاصل از اجرای برنامه مثال ۱۰ توجه نمایید : type number/operator/number
12 + 23
sum=35
type number/operator/number
2*26
multiple=52
type number/operator/number
4%2
operator is illegal
type number/operator/number
^c
اگر بجای علامت *از ‘x’ز و یا بجای ‘/’از ‘\’ز استفاده گردد، این برنامه عمل
نخواهد کرد . اما برنامه ذیل ( مثال ۱۱ ) طوری طراحی شده است که با استفاده از
امکان ترکیب شرطهای مختلف در ساختار switch ، به این دو مورد نیز پاسخ دهد .
مثال ۱۱: برنامه ای که دو عدد و یکی از عملگرهای چهار عمل اصلی را از ورودی
خوانده و آن عملگر را بر روی آن دو عدد عمل می کند . main)(
{
int num1 / num2 ;
char op ;
while(1)
{
printf(“type number/operator/”);
printf(“number \n” );
scanf(“%d%c%d”/&num1/&op/&num2);
switch(op)
{
case ‘+’:
printf(“\nsum=%d”/num1+num2);
break ;
case ‘-’:
printf(“\nsubtract=%d”/num1-num2);
break ;
case ‘*’:
case ‘x’:
printf(“\nmultiple=%d”/num1*num2);
break ;
case ‘/’:
case ‘\\’:
printf(“\ndivition=%d”/num1+num2);
break ;
default:
printf(“\noperator is illegal”);
}
printf(“\n\n” );
}
}
نمونه ای از خروجی حاصل از اجرای برنامه مثال ۱۱ : type number/operator/number
20 x 4
multiple=80
type number/operator/number
60 \ 3
division=2o
type number/operator/number
4%2
operator is illegal
type number/operator/number
12 + 23
sum=35
type number/operator/number
2*26
multiple=52
type number/operator/number
^c
مثال ۱۲: برنامه ای که اطلاعات تعدادی از ورودی خوانده و سپس معدل هر دانشجو
را محاسبه می نماید. پس از محاسبه معدل ، دانشجویان ممتاز ( معدل بیشتر از ۱۷ )
و دانشجویان مشروط ( معدل کمتر از ۱۲ ) را مشخص و در خروجی چاپ می کند . main)(
{
int sumgrad/sumunit/number ;
int cours/unit/grad/aver/j/n=0 ;
char name[20] ;
printf(“enter number of student:\t”);
scanf(“%d”/&number);
while(n!=number)
{
n++ ;
sumunit=sumgrad=j=0 ;
printf(“\n enter name of student “);
printf(“%d:”/n );
scanf(“%s”/&name );
printf(“\n enter number of cours “);
printf(“of this st:.”);
scanf(“%d”/&cours );
while(j!=cours)
{
printf(“\n enter unit of cours”);
printf(” %d:”/j+1 );
scanf(“%d”/&unit );
printf(“\n enter grade of cours”);
printf(” %d:”/j+1 );
scanf(“%d”/&grad );
sumunit=sumunit+unit ;
sumgrad=sumgrad+grad*unit ;
j++ ;
}
aver=sumgrad/sumunit ;
printf(“\n average is:\t” );
printf(“%d”/aver );
if(aver<12)
{
printf(“\n student is probation”);
printf(“… “);
}
else if(aver>17)
{
printf(“\n student is exelent”);
printf(“… “);
}
}
}
به نمونه ای ازخروجی مثال ۱۲ که برای دو نفر ازدانشجویان عمل نموده است توجه
نمایید . enter number of students :2
enter name of student 1: ali
enter number of cours of this st:.2
enter unit of cours 1:2
enter grade of cours 1:19
enter unit of cours 2:3
enter grade of cours 2:20
aver is : 19
studnt is exelent…
enter name of student 2: reza
enter number of cours of this st:.3
enter unit of cours 1:2
enter grade of cours 1:12
enter unit of
 
توابع و کلاسهای حافظه

در مورد برنامه های طولانی و پیچیده که شامل چندین قسمت منطقی تقریبا” مستقلی
هستند بهتر است برای هر قسمت منطقی ، برنامه ای نوشته و سپس آنها را به یکدیگر
متصل (Link) کرد . هر یک از این قسمتها یک زیر برنامه نام دارند . استفاده از
زیر برنامه جهت طراحی برنامه ها ، دارای مزایای زیادی است که بر اهل کامپیوتر
پوشیده نیست . در زبانهای برنامه سازی مختلف معمولا”دو نوع زیربرنامه وجود دارند
و عبارتند از : ( الف ) زیر برنامه های تابع ( ب ) زیر برنامه های زیر روال ، در
زبان C فقط زیربرنامه تابع مورد استفاده قرار میگیرد. کاری را که زیربرنامه های
زیر روال در سایر زبان های برنامه سازی انجام می دهند ، در زبان C توسط زیر
برنامه های تابع صورت می گیرد . در اینجا منظور از زیر برنامه ، توابع هستند .
توابع در زبان C دارای ساختمان خاصی هستند که شکل (۱) آن را نشان می دهد .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ |
<نوع تابع > <نام تابع > ( اسامی پارامترها ) | |
تعریف پارامترها | | { |
|
بدنه تابع | | } |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۱) . ساختمان توابع

در شکل (۱) منظور از نوع تابع ، یکی از انواع معتبر در زبان C است که نوع
مقدار برگردانده شده توسط تابع را مشخص می کند . تعیین نوع توابع ، اختیاری
است . اگر تابعی تعیین نوع نگردد کامپایلر زبان C فرض می کند مقداری که توسط
تابع برگردانده می شود از نوع ” صحیح ” است . نام تابع از قانون نامگذاری برای
متغیرهای تبعیت می کند . اسامی پارامترها شامل متغیرهایی است که باید به تابع
منتقل کردند . اگر تعداد پارامترها بیش از یکی باشد یا کاما از یکدیگر جدا
می شوند . تعریف پارامترها مجموعه دستوراتی است که نوع پارامترها را تعیین
می نماید . تعیین نوع پارامترها در حین تعریف تابع نیز امکان پذیر است . بدنه
تابع شامل دستورالعمل هایی است که عمل تابع را مشخص می کند .
نکاتی را که باید در مورد توابع در نظر داشت عبارتند از : ۱
کلیه توابع فرعی بعد از تابع اصلی (()main) تعریف می شوند . ۲
اگر نوع تابعی غیراز نوع ” صحیح ” باشد، نوع آن باید در تابع فراخواننده
به کامپایلر اعلان شود . ۳
برای اجرای تابع باید آنها را فراخوانی نمود ( فراخوانی توابع توسط نام
آنها انجام می شود ) . ۴
همانطور که متغیرهای قابل استفاده در تابع اصلی باید در ابتدای این تابع
تعریف شوند ، متغیرهای مورد نیاز هر تابع فرعی نیز باید در ابتدای آنها تعریف
کردند . ۵
تعریف یک تابع در داخل تابع دیگر امکان پذیر نیست . ولی فراخوانی سطوح
مختلف توابع ، ممکن است . ۶
توابع از نظر تعداد مقادیری که به تابع فراخواننده برمی گردانند ، به سه
دسته تقسیم می شوند .
الف ) توابعی که هیچ مقداری را برنمی گردانند .
ب ) توابعی که فقط یک مقدار را برمی گردانند .
ج ) توابعی که چند مقدار را به عنوان نتیجه عمل برمی گردانند . ۷
درموقع فراخوانی توابع باید دقت داشت که تعداد و نوع آرگومانها با تعداد
ونوع پارامترها یکسان باشند. برای پی بردن به تفاوت بین آرگومانها و پارامترها
می توانند به شکل (۲) مراجعه نمایید .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | main )(|
| { |
|
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | |
آرگومان ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | |
< فراخوانی تابع ؤؤؤؤؤؤ;(a/b)out | | |
| } |
| |
|
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | |
پارامتر تابع ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | | |
(< تعریف تابع ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤk/i)out | | int k/i; |
| { |
| |
| printf(“k=%d/i=%d”/k/i); |
| |
| } |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۲) . تفاوت آرگومان و پارامتر

در شکل (۲) aو bو را که در فراخوانی تابع out آمده اند ، آرگومان تابع و I و K
را که در تعریف تابع out آمده اند پارامتر تابع می گوییم . همانطور که ملاحظه وانند هم نام نباشند .
 
توابعی که هیچ مقداری را برنمی گردانند

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

مثال ۱: برنامه ای که با استفاده از یک تابع ، زمانی که شامل ساعت ، دقیقه
و ثانیه است را از ورودی خوانده و این زمان را به ثانیه محاسبه می نماید : main)(
{
convert )(;
}

convert)(
{
int hours/minutes/second/time ;
printf(“enter time to be convertd”);
printf(“\n hour/minutes/second : “);
scanf(“%d%d”/&hours/&minutes);
printf(“%d/&second);
time=(60*hours+minutes)*60+second ;
printf(“\ntime is: %d second.”/time);
}

به نمونه ای از خروجی برنامه مثال ۱ توجه نمایید : enter time to be convertd
hour/minutes/secound : 4 8 30

time is: 14910 second.

در مثال ۱ از تابعی به نام convert استفاده شده است که هیچگونه پارامتری
ندارد . متغیرهای مورد نیاز این تابع ، تعریف شده ، اطلاعات از ورودی خوانده
می شوند و پس از انجام محاسبات به خروجی منتقل می گردند . این تابع هیچ مقداری
را به تابع فراخوانده ( تابع اصلی ) برنمی گرداند . به چنین توابعی توابع از
نوع void گفته می شود . اگر بخواهیم برنامه مثال ۱ را با استفاده از این تعریف
( تابع از نوع void ) بنویسیم ، مثال (۲) حاصل خواهد شد .

مثال ۲: برنامه مثال ۱ با استفاده از تعریف نوع void : main)(
{
void convert )(;
convert )(;
}

void convert)(
{
int hours/minutes/second/time ;
printf(“enter time to be convertd”);
printf(“\n hour/minutes/second : “);
scanf(“%d%d”/&hours/&minutes);
printf(“%d/&second);
time=(60*hours+minutes)*60+second ;
printf(“\ntime is: %d second.”/time);
}

همانطوریکه در مثال ۲ مشاهده میشود باید درتابع فراخواننده ( در اینجا تابع
اصلی ) نوع تابع convert را که از نوع void است به کامپایلر اعلان نمود وسپس در
حین تعریف تابع نوع آن مشخص گردد (()void convert) .
در توابعی مانند convert که هیچگونه پارامتری ندارند ، برای جلوگیری از
هر گونه اشتباه احتمالی در فراخوانی اینگونه توابع ( که ممکن است اشتباها” با
پارامتر فراخوانی گردند ) می توان بجای پارامتر و آرگومان از کلمه کلیدی void
استفاده نمود. با توجه به این نکته که اگر اشتباها” توابع فاقد هرگونه پارامتر
( و آرگومان ) با پارامتر فراخوانی گردند . کامپایلر C خطایی را اعلام نمی کند.
در این حالت ذکر کلمه کلیدی void بجای پارامتر و آرگومان تابع مفید بنظر میرسد
( مثال ۳ ) .

مثال ۳: main)(
{
void convert(void );
convert )(;
}

void convert(void)
{
int hours/minutes/second/time ;
printf(“enter time to be convertd”);
printf(“\n hour/minutes/second : “);
scanf(“%d%d”/&hours/&minutes);
printf(“%d/&second);
time=(60*hours+minutes)*60+second ;
printf(“\ntime is: %d second.”/ti
 
انواع فراخوانی و مقادیری که توابع برمی گردانند

همانطوریکه قبلا” گفتیم ، توابع از نظر تعداد مقادیری که به تابع فراخواننده
برمی گردانند به سه دسته تقسیم می شوند که یک دسته از آنها ( توابعی که هیچ
مقداری را برنمی گردانند ) را مورد بررسی قرار داده ایم .
توابع در زبان C به دو روش فراخوانی می شوند که عبارتند از : ۱
فراخوانی توسط ارزش (Call by value). دراین روش مقدار آرگومان تابع ، در
پارامتر متناظر با آن کپی می شود . لذا هرگونه تغییری در پارامترها هیچگونه
تاثیری در مقدار آرگومان ها نخواهد داشت . بنابراین در روش فراخوانی توسط ارزش
هیچ مقداری توسط پارامترها وآرگومانها به تابع فراخواننده ، برگردانده نمیشوند.
ولی می توان فقط یک مقدار را با استفاده از دستور return به تابع فراخواننده
برگرداند . مقداری که توسط این دستور به تابع فراخواننده برگردانده می شود، در
نام تابع فراخوانده شده قرار میگیرد. دستور return به دو صورت زیر بکار میرود: return( 1)

(َ۲) (مقدار) return
دستور return در حالت (۱) صرفا” خاتمه اجرای تابع را مشخص می کند و هیچگونه
مقداری را به تابع فراخواننده برنمی گرداند. در حالت (۲) ضمن اعلام خاتمه اجرای
تابع ، مقداری را نیز به تابع فراخواننده برمی گرداند ( مثال ۱ ) .

مثال ۱: main)(
{
int t=10 ;
printf(“\n t=%d/square is:”/t);
printf(“%d”/aqr(t ));
}
eqr(int x)
{
int y ;
y=x*x;
return(y );
}

خروجی حاصل از اجرای برنامه مثال ۱ به صورت زیر است : t=10/aqurare is:100

در مثال ۱ تابع sqr برای انجام عمل توان نوشته شده است که پارامتر آن x بوده
و از نوع “صحیح ” است ( به چگونگی تعریف نوع پارامتر دقت شود ). پس از فراخوانی
تابع sqr مقدار آرگومان t (10) در پارامتر x کپی می شود و از این لحظه به بعد
هیچ کاری با t نیست . در این تابع ، نتیجه عمل در متغیر y قرار می گیرد و سپس
توسط دستور return مقدار متغیر y به تابع فراخواننده برگردانده می شود . این
مقدار در نام تابع ((t)sqr) قرار می گیرد .
۲
فراخوانی توسط ارجاع (Call by reference) . در این روش ، آدرس آرگومان
در پارامتر کپی می شود . لذا در داخل تابع فراخوانده شده ، آدرس آرگومان برای
دسترسی به آرگومان مورداستفاده قرار میگیرد و این بدان معنی است که درفراخوانی
توسط ارجاع ، پارامترها حاوی آدرس های آرگومان ها هستند. لذا در فراخوانی توسط
ارجاع باید آدرس آرگومان بجای مقدار آرگومان به تابع فراخواننده منتقل گردد .
بحث بیشتر در این مورد را به مطالعه اشاره گرها (pointer) موکول می کنیم .

مثال ۲: برنامه ای که کاراکترهایی را از ورودی خوانده و تشخیص می دهد آیا
کاراکتر وارد شده a، b، و یا غیر از این دو حرف بوده است . ضمنا” این برنامه
قبل از انجام عمل مقایسه ، با استفاده از یک تابع کاراکترهای خوانده شده را به
حروف کوچک تبدیل می کند ( کد اسکی حروف بزرگ درباره ۶۵ و ۹۱ است که اگر به این
بازه ۳۲ واحد اضافه شود کد اسکی حروف کوچک حاصل خواهد شد ) . main)(
{
char ch ;
printf(“\n type a character: ” );
ch=getcha )(;
switch(ch)
{
case ‘a’:
printf(“\n you typed the”);
printf(” character ‘a’” );
break ;
case ‘b’:
printf(“\n you typed the”);
printf(” character ‘b’” );
break ;
default:
printf(“\n you typed no ‘a’”);
printf(” and no ‘b’” );
}
}

getcha)(
{
char cl ;
cl=getch )(;
if(cl>64 && cl<91)
cl+=32 ;
return(cl );
}

نمونه ای از خروجی حاصل از اجرای برنامه مثال ۲ : type a character: s
you typed no ‘a’ and no ‘b’

تعریف توابع در داخل یکدیگر امکان پذیرنیست ، اما فراخوانی سطوح مختلف تابع
ممکن است . این مطلب در مثال ۳ مشاهده می شود .

مثال ۳: برنامه ای که با استفاده از چند تابع ، دو عدد را از ورودی خوانده و
با محاسبه مجموع مربعات آن دو ، آنها را به خروجی منتقل می کند . main)(
{
int num1/num2 ;
printf(“\n type two number:” );
scanf(%d%d”/&num1/&num2 );
printf(“\nsum of square is:”);
printf(“%d/sumsqr(num1/num2));
}

sumsqr(j/k)
int j /k ;
{
return(sum(sqr(j)/sqr(k )));
}
sqr(z)
int z ;
{
return(z*z);
}

sum(x/y)
int x/y ;
{
return(x+y);
}

نمونه ای از خروجی حاصل از اجرای برنامه مثال ۳ : type two number : 12 9
sum of square is:225

در مثال ۳از ۳ز تابع به نامهای sumsqr، sqr،و sumو استفاده شده است . وظیفه
تابع sumsqr محاسبه مجموع مربعات دو عدد num1و num2و است که برای این کار ، دو
تابع sumو sqrو را فراخوانی می کند . تابع sqr در دو بار فراخوانی ، مربع دو
عدد num1و num2و را محاسبه کرده و تحویل تابع sum می دهد . این تابع مجموع دو
پارامتر خود را که همان مربعات دو عدد num1و num2و هستند ، محاسبه می کند و به گرداند .
 
تعیین نوع تابع

همانطور که قبلا” گفته شد اگر در حین تعریف تابع از ذکر نوع آن خودداری شود
کامپایلر فرض می کند مقداری که توسط این تابع برگردانده می شود ( توسط دستور return
) یک مقدار ” صحیح ” است . به اینگونه توابع ، توابع نوع صحیح گفته
می شود . اگر بخواهیم توابعی غیر از نوع ” صحیح ” داشته باشیم باید: الف ) نوع
تابع ار در تابع فراخواننده به کامپایلر اعلان کنیم . ب ) نوع تابع را در حین
تعریف تابع مشخص کنیم ( مثال ) .

مثال : برنامه ای که شعاع دایره ای را از ورودی خوانده و با محاسبه مساحت آن
را به خروجی می برد . main)(
{
float area(float );
float radius ;
printf(“\n entera radius : ” );
scanf(“%f”/&radius );
printf(“area of circle is:”);
printf(“%.2f”/area(radius ));
}
float area(float rad)
{
return(3.13*rad*rad );
}

به نمونه ای از خروجی برنامه مثال توجه نمایید : enter radius: 4
area of circle is: 50.08

همانطوری که در مثال بالا مشاهده می گردد ، مقداری که توسط تابع ()area
برگردانده میشود از نوع اعشاری است ، لذا در اولین دستور تابع ()main نوع تابع
()area را به کامپایلر اعلان کرده و در حین تعریف این تابع ، نوع آن را نیز مشخص
نموده ایم . در بسیاری از گونه های زبان C ذکر نوع نتیجه تابع ، در آرگومان آن
الزامی نیست و درمثال بالا اولین دستور تابع ()main را نیز می توان به صورت زیر
نوشت . f
 
کلاسهای حافظه

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

مثال ۱: برنامه ای که چگونگی استفاده از متغیرهای همنام را در توابع مختلف
نشان می دهد . main)(
{
int i ;
printf(“enter the value of i:” );
scanf(“%d”/&i );
input )(;
printf(“\nvalue of i in main is:”);
print(“%d”/i );
}

input)(
{
int i ;
printf(“enter value of i”);
printf(“(in function:)”);
scanf(“%d”/&i );
printf(“\nvalue of i in function is:”);
printf(“%d”/i);
}

به نمونه ای از خروجی حاصل از اجرای برنامه مثال ۱ که درپاسخ به اولین دستور scanf
عدد ۱۰ و در پاسخ به دومین دستورscanf عدد ۴۰ وارد شده است توجه نمایید: enter the value of i:10
enter vale of i(in function:)40
vale of i in function is: 40
value of i in main is : 10

با مطالبی که تاکنون گفته شد روشن گردید که متغیرهایی که در یک تابع تعریف
میشوند فقط درهمان تابع قابل استفاده هستند و به محض برگشت کنترل اجرای برنامه
از آن تابع ، این متغیرها عملا” وجود ندارند. به چنین متغیرهایی که محدوده حضور
آنها فقط در تابعی است که در آن تابع تعریف شده اند متغیرهای محلی گفته می شود.
همه متغیرها در زبان C دارای چنین خصیصه ای نیستند. بلکه انواع دیگری ازمتغیرها
نیز وجود دارند که برای معرفی آنها لازم است به تشریح کلاس حافظه بپردازیم .
کلاس حافظه هر متغیر دو چیز را برای آن متغیر مشخص می کند : ۱
مدت حضور آن در برنامه یا طول عمر (life time) متغیر . ۲
محدوده حضور آن در برنامه (scope vvisibility) .
یکی از علل مطالعه کلاس های حافظه این است که با داشتن اطلاعاتی در مورد مدت
حضور متغیرها در برنامه و همچنین محدوده حضور آنها ، می توانیم برنامه هایی
بنویسیم که : ۱
از حافظه کامپیوتر به نحو خوبی استفاده گردد . ۲
سرعت اجرای آنها بالا باشد . ۳
برنامه ها کمتر با خطا مواجه شوند و عیب یابی سهل تر گردد .

کلاس های حافظه ای که در زبان C از آنها استفاده می شود عبارتند از :
۱
کلاس حافظه اتوماتیک (automatic) . 2
کلاس حافظه استاتیک (static) . 3
کلاس حافظه ثبات (register) . 4
کلاس حافظه خارجی (extern) .
کلمات کلیدی auto، static،، register،و externو بترتیب مشخص کننده کلاس های
حافظه اتوماتیک ، استاتیک ، ثبات و خارجی هستند. این کلمات قبل از کلمات کلیدی
تعیین نوع متغیر بکار می روند .
شکل کلی تعیین کلاس های حافظه بصورت زیر است : ;
<کلاس حافظه > <نوع متغیر> <اسامی متغیرها>
بعنوان مثال دستور auto int i/y ; متغیرهای iو yو را از نوع ” صحیح ” و با
کلاس حافظه اتوماتیک تعریف می نماید .

کلاس حافظه اتوماتیک
متغیرهایی با کلاس حافظه اتوماتیک ، بیشتر ازسایر انواع متغیرها مورداستفاده
قرار می گیرند . متغیرهایی که تاکنون در برنامه ها استفاده شده اند ، دارای کلاس
حافظه اتوماتیک بوده اند. یعنی در زبان C متغیرها در حالت عادی دارای کلاس حافظه
اتوماتیک هستند . متغیرهای با کلاس حافظه اتوماتیک دارای خصوصیات زیر می باشند: ۱
وقتی در یک تابع و یا یک بلاک تعریف می شوند فقط درآن تابع و یا بلاک قابل
دسترسی اند ( ” محلی ” آن تابع و یا بلاک محسوب می شوند ) . ۲
در موقع ورود به تابع و یا بلاک به آنها حافظه اختصاص می یابد . ۳
در هنگام خروج از تابع و یا بلاک ، حافظه اختصاص یافته به آنها، پس گرفته
می شود .

مثال ۲: برنامه ای که تعریف متغیرهای اتوماتیک در بلاک را نشان می دهد . main)(
{
int sum=10 ;
{
float sum=3.1416;
printf(“\n sum in block is:”);
printf(%6.4f\n”/sum );
}
printf(“\n sum out of block is:”);
printf(“%2d\n/sum );
}

نمونه ای از خروجی حاصل از اجرای برنامه مثال ۲ در ذیل آمده است : sum in block is:3.1416
sum out of block is:10

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

مثال ۳: استفاده از متغیرهای با کلاس حافظه اتوماتیک که دارای ارزش اولیه
می باشند . main)(
{
auto int k ;
void aquare )(;
for(k=1;k<5;k++)
aquare(k);
}

void square(d)
int d;
{
int squared=d^d ;
printf(“\n%2d squared is” );
printf(” %3d\n”/d/squared);
}

خروجی حاصل از اجرای برنامه مثال ۳ : ۱ squared is 1
2 squared is 4
3 squared is 9
4 squared is 16

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

مثال ۴: برنامه ای که نحوه استفاده از متغیرهای عمومی را نشان می دهد . این
برنامه تعداد ۵ عدد رااز ورودی خوانده و مجموع مربعات آنهارا محاسبه می نماید. int k/sq ;
int sum=0 ;
main)(
{
auto j/i=5 ;
printf(“\n enter five number:” );
for(j=0 ;j
input )(;
printf(“\n sum of square is:%d”/sum);
}

input)(
{
scanf(“%d”/&k );
square )(;
sum+=sq ;
}

square)(
{
sq=k*k ;
}

نمونه ای از خروجی حاصل از اجرای برنامه مثال ۴ : enter five number: 10 12 4 7 20
sum of square is:709

در مثال ۴ متغیرهای sq، k،و sumو در خارج از تابع ()main تعریف شده اند و در
توابع ()square و ()input بدون تعریف این متغیرها از آنها استفاده شده است .
اگر توابع تعریف شده در یک برنامه علاوه بر متغیرهای عمومی از متغیرهای محلی
نیز استفاده نمایند و یک یا چند متغیر محلی توابع ، با یک یا چند متغیر عمومی
مراجعه داشته باشد ( مقدار آنرا تغییر دهد و یا مقدار آن متغیر را مورداستفاده
قرار دهد ) تاثیری در متغیر عمومی همنام با این متغیر محلی نخواهد داشت .

مثال ۵: برنامه ای که توابع موجود در آن علاوه بر استفاده از متغیرهای عمومی
از متغیرهای محلی همنام با متغیرهای عمومی نیز استفاده می کنند . int count ;
main)(
{
count=100 ;
func1 )(;
}

func1)(
{
int temp ;
temp=count ;
func2 )(;
printf(“\n count is:%d”/count );
}

func2)(
{
int count ;
for(count=1/count<6;count++)
printf(” %c “/’*’
}

خروجی حاصل از اجرای برنامه مثال ۵ : * * * * *
count is :100

در مثال ۵ متغیر count که قبل از تابع ()main تعریف شد، یک متغیر عمومی است
و متغیر count که در تابع ()func1 بکار رفته است ، همین متغیر میباشد. در تابع
()func2 متغیری به نام count تعریف شد که محلی این تابع می باشد . لذا در این
تابع هر مراجعه به متغیر count مراجعه به متغیری است که در این تابع تعریف شده
است .
درشروع اجرای برنامه برای متغیرهای عمومی ، حافظه اختصاص می یابد و درپایان
اجرای برنامه ، این حافظه از متغیرها اخذ می گردد. بنابراین اگر تعداد متغیرهای
عمومی زیاد باشد تاثیر بسزایی در میزان حافظه مصرفی دارد . بهر حال در مواقعی
که توابع موجود در برنامه به متغیرهای مشترکی نیاز داشته باشند ، خوب است از
متغیرهای عمومی استفاده گردد. ولی باید توجه داشت متغیرهایی که بندرت در سراسر
برنامه مورد استفاده قرار می گیرند ، بصورت متغیرهای عمومی تعریف نگردند .
اگر برنامه هایی که به زبان C نوشته می شود طولانی باشد ، می توان آن برنامه
را به قسمت های منطقی کوچکتری تقسیم کرده ، سپس هر قسمت را در یک فایل قرار
داده و پس از کامپایل کردن آنها به طور مجزا ، همه قسمت ها را با یکدیگر اجرا
نمود . به هر یک از این قسمت های مجزا ، یک واحد (unit) گفته می شود . اگر
متغیرهایی در واحد اصلی تعریف شوند و بخواهیم از آنها در واحدهای فرعی دیگر
استفاده کنیم ( بدون این که در واحدهای فرعی به آنها حافظه ای اختصاص یابد )
باید در واحدهای فرعی توسط کلمه کلیدی extern به کامپایلر گفته شود که این
متغیرها در جای دیگری ( در واحد اصلی ) تعریف شده اند. در غیر این صورت استفاده
از متغیرهای مورد نظر در واحدهای دیگر ممکن نیست ( جدول ۱ ) .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | file1 file2 |
| int s/y; extern int x/ y; |
| char ch; extern char ch; |
| main )(func 22 )(|
| { { |
| x=y/10; |
| } } |
| func 1 )(func 23 )(|
| { { |
| x=123; y=10; |
| } } |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
جدول (۱) . کاربرد extern در واحدهای مختلف یک برنامه

در جدول ۱ کلمه کلیدی extern به کامپایلر می گوید که متغیرهای x، y،و chو
قبلا” در جای دیگری تعریف شده اند ، لذا در برنامه file2 حافظه جدیدی به آنها
اختصاص نمی یابد .
استفاده از کلمه کلیدی extern درتوابع موجود در یک فایل نیز امکان پذیر است
که البته نیازی به آن نیست ( کاربرد extern در این گونه موارد اختیاری است ) .

مثال ۶: برنامه ای که کاربرد کلمه کلیدی extern را در یک فایل نشان می دهد . int first/second ;
main)(
{
extern int first/second ;
printf(“\n enter two number: ” );
scanf(“%d%d”/&first/&second );
printf(“\nsum is :%d”/first+second);
}

به نمونه ای از خروجی برنامه مثال ۶ توجه نمایید : enter two number: 15 30
sum is:45

در برنامه مثال ۶ دو متغیر firstو secondو در خارج از تابع ()main تعریف
شده اند . دستور extern در تابع ()main به کامپایلر می گوید که این متغیرها در
جای دیگری ( در خارج از تابع اصلی ) تعریف شده اند . البته همانطور که گفته شد
توابعی که در یک فایل وجود دارند می توانند از متغیرهای عمومی استفاده کنند و
نیاز به معرفی آنها توسط extern نیست .
متغیرهای عمومی ، دارای کلاس حافظه خارجی (extern) هستند و دارای دو خصیصه
زیر می باشند : ۱
طول عمر این متغیرها ، از بدو اجرای برنامه تا خاتمه اجرای آن است . ۲
محدوده حضور آنها در سراسر یک برنامه است .

کلاس حافظه استاتیک
متغیرهایی که دارای کلاس حافظه استاتیک هستند می توانند به دو دسته تقسیم
شوند :
الف ) متغیرهای استاتیک محلی
ب ) متغیرهای استاتیک عمومی

متغیرهای استاتیک محلی دارای خواص زیر هستند : ۱
فقط در همان تابعی که تعریف شده اند قابل دسترسی اند ( حضور دارند ) . ۲
در هنگام خروج از تابع ، مقادیر متغیرها آخرین مقداری خواهد بود که در
تابع به آنها اختصاص یافته است . ۳
می توانند مقدار اولیه بگیرند . ۴
اگر متغیر استاتیک محلی مقدار اولیه بگیرد ، این ارزش دهی اولیه ، فقط
یکبار صورت می گیرد ( این مطلب را از مورد ۲ نیز می توان نتیجه گرفت ) .

مثال ۷: main)(
{
int i ;
void subroutine )(;
for(i=0 ; i<5 ; i++)
subroutine )(;
}

void subroutine)(
{
static int static_var=0 ;
int auto_var=0 ;
printf(“\nautomatic=%d/”/auto_var);
printf(“static=%d”‘static_var );
auto_var ++;
static_var ++ ;
}

خروجی حاصل از اجرای برنامه مثال ۷ : automatic=0/static=0
automatic=0/static=1
automatic=0/static=2
automatic=0/static=3
automatic=0/static=4

متغیرهای استاتیک عمومی فقط در یک فایل ( در یک واحد ) از برنامه ، از جایی
که تعریف می شوند به بعد قابل دسترسی اند ( برخلاف متغیرهای عمومی غیر استاتیک
که در همه واحدهای یک برنامه قابل دسترسی اند ) . مثال های ۸و ۹و .

مثال ۸: static int i/j ;
main)(
{
.
.
.
}

f1)(
{
.
.
.
}

f2)(
{
.
.
.
}

در مثال ۸ متغیرهای xو yو در تابع ()main و کلیه توابعی که بعد از آن تعریف
می شوند قابل استفاده اند .

مثال ۹: main)(
{
.
.
.
}

f1)(
{
.
.
.
}

static x/y ;
f2)(
{
.
.
.
}

f3)(
{
.
.
.
}

در مثال ۹ ، متغیرهای xو yو در توابع ()main و ()f1 قابل دسترسی نیستند ولی
در دو تابع ()f2 و ()f3 و کلیه توابعی که بعداز آن تعریف میشوند، قابل استفاده
هستند .
استفاده کلاس حافظه استاتیک درپنهان سازی اطلاعات (information hide) میباشد.

کلاس حافظه ثبات
ذخیره هایی که دارای کلاس حافظه هستند در صورت امکان در یکی از ثبات های CPU
قرار می گیرند . لذا سرعت انجام عملیات با آنها بسیار بالا است و موجب افزایش
سرعت اجرای برنامه می شود . کلیه متغیرهای اتوماتیک و آرگومان های توابع
می توانند دارای کلاس حافظه ثبات باشند .
در مورد کلاس حافظه ثبات محدودیتهای زیر را داریم : ۱
از آنجایی که تعداد ثباتهای CPU محدود است ، تعداد کمی از متغیرها را
می توان با کلاس حافظه ثبات تعریف کرد . اگر تعداد متغیرهای با کلاس حافظه ثبات
زیاد باشد کامپایلر کلاس حافظه ثبات را از متغیرها حذف می کند . ۲
انواع متغیرهایی که میتوانند دارای کلاس حافظه ثبات باشند، درکامپیوترهای
مختلف متفاوت است و معمولا” نوع های int، char،و pointerو می توانند دارای کلاس
حافظه ثبات باشند . ۳
آدرس متغیری که دارای کلاس حافظه ثبات باشد، عملا” مفهوم نخواهد داشت و یا
به عبارت دیگر، عملگر & را نمیتوان برای متغیرهای با کلاس حافظه ثبات بکار گرفت
( چون این متغیرها در ثبات CPU قرار دارند ) .

مثال ۱۰: int n/fact=1 ;
main)(
{
printf(“\n enter a number(1-9: )”);
scanf(“%d/&n );
factolial )(;
printf(“\nfactolial of number:%d”/n);
printf(” is :%d”/fact );
}

factorial)(
{
register int i ;
for(i=2 ; i<=n ; i++)
fact *=i ;
}
 
آرایه ها

آرایه ، اسمی برای چند متغیر همنوع است و یا بعبارت دیگر مجموعه ای است از
چند کمیت که دارای یک اسم باشند . به هر یک از این کمیت ها یک عنصر آرایه گفته
می شود . دسترسی به هر یک از عناصر آرایه توسط نام آرایه و محل قرار گرفتن این
عنصر در آرایه مشخص می شود . نامگذاری برای آرایه ها از قانون نامگذاری برای
متغیرها تبعیت می کند. بعنوان مثال ک مجموعه ای از دانشجویان یک کلاس می توانند
تشکیل یک آرایه بدهند . اگر نام این آرایه را Y انتخاب کنیم ، آنگاه (۱)Y اولین
عنصر آرایه ، (۲)Y دومین عنصر آرایه و بالاخره (n)Y، n امین عنصر آرایه را مشخص
می کند . به هر یک از اعداد ۱، ۲، و … و n که محل قرار گرفتن یک عنصر را در
آرایه مشخص می کنند ، اندیس آرایه گفته می شود . اندیس آرایه ارتباط بین عناصر
آرایه را مشخص می کند مثلا”(َ۲)Y در آرایه قبل از (۳)Y و بعد از (۱)Y قرار دارد.
چون دسترسی به عناصر آرایه از طریق اندیس امکان پذیر است ، آرایه را متغیر
اندیس دار نیز می گویند .
آرایه های دارای یک اندیس را آرایه های یک بعدی ، آرایه های دارای دو اندیس را
آرایه های دو بعدی و به طور کلی آرایه های دارای n اندیس را آرایه های n بعدی
می گویند .
آرایه ها و رشته ها دو قسمت مجزا نیستند زیرا : ” رشته آرایه ای از کاراکترها
است ” .

آرایه های یک بعدی
آرایه یک بعدی که نام دیگر آن لیست است ، بصورت زیر تعریف می شود : ]
طول آرایه [ <نوع آرایه > <اسم آرایه >
نوع ، یکی از نوع های معتبر در زبان C مثل intو floatو است که مشخص می کند
هر یک از عناصر آرایه از چه نوعی هستند . طول آرایه ، عددی صحیح است که تعداد
عناصر آرایه را مشخص می کند . با استفاده از طول آرایه و نوع آن می توان مشخص
کرد که آرایه چند بایت از حافظه را اشغال می کند :
طول آرایه * ( نوع آرایه ) = sizeof مقدار حافظه مورد نیاز آرایه
اندیس آرایه ها در زبان C از صفر شروع می شود . بعنوان مثال اگر آرایه ای به
طول ۵ داشته باشیم ، اولین متغیر آن دارای اندیس صفر و آخرین عنصر دارای اندیس ۴
خواهد بود .

مثال ۱: int temp [5];

دستور فوق آرایه ای بنام temp و به طول ۵ را تعریف میکند که همه عناصر آن از
نوع int هستند . شکل ۱ نشان می دهد که چگونه می توان به هر یک از عناصر آرایه temp
دسترسی پیدا کرد .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ temp | | | | | |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ temp [0] temp [1] temp [2] temp [3] temp [4]

شکل (۱) . نحوه دسترسی به عناصر آرایه

نکته ای که در مورد آرایه ها در زبان C باید توجه داشت این است که در آن bounds checking
وجود ندارد. بعنوان مثال ، اگر آرایه ای بنام x و به طول ۱۰ را
تعریف کرده باشیم ( با توجه به این که بزرگترین اندیس آن ۹ است ) ، می توانیم
این آرایه را با اندیس های بزرگتر از ۹ ( بدون اینکه از طرف کامپایلر C جلوی
آن گرفته شود ) مورد استفاده قرار دهیم . در این مورد دستوراتی مثل y = x[10]
و k = x[n] ازنظر کامپایلر با اشکالی مواجه نخواهد شد. ولی بدیهی است که نتیجه
مطلوبی حاصل نخواهد شد. لذا برنامه نویس باید مطلب فوق را در نظر داشته باشد تا
در نتیجه اجرای برنامه اشکالی پیش نیاید .

مثال ۲: برنامه ای که با تعریف یک آرایه به طول ۱۰ ، مقدار هر عنصر آن را
برابر با اندیس آن قرار داده و سپس با محاسبه مجموع مربعات عناصر آرایه ، آنها
را در خروجی چاپ می کند . main)(
{
float list[20]/max ;
int i / j ;
for(i=0 ; i<20/i++)
{
printf(“\n enter moadel %d :”/i+1);
scanf(“%f”/&list );
}
max=list[0] ;
j=1 ;
for(i=1 ;i<20 ; i++)
{
if(list>max)
{
max=list ;
j=i+1 ;
}
}
printf(“\nmax=%f/position=%d”/max/j);
}

خروجی حاصل از برنامه مثال ۲ : enter moadel 1 :12
enter moadel 2 :12.5
enter moadel 3 :10.75
enter moadel 4 :14
enter moadel 5 :13
enter moadel 6 :16
enter moadel 7 :17.25
enter moadel 8 :18.5
enter moadel 9 :17.5
enter moadel 10 :18.25
enter moadel 11 :19.5
enter moadel 12 :15.75
enter moadel 13 :16.25
enter moadel 14 :17.5
enter moadel 15 :18.5
enter moadel 16 :19.25
enter moadel 17 :20
enter moadel 18 :11.5
enter moadel 19 :10.5
enter moadel 20 :10.75

max=20.000000/position=17

مثال ۳: برنامه ای که با خواندن تعدادی عدد از ورودی ، آنها را در آرایه ای
قرار می دهد . سپس این آرایه را به طریق حبابی (bubble sort) مرتب می کند . main)(
{
counst int k=7 ;
int temp[7]/i/j/item ;
for(i=0 ; i
{
printf(“\n enter number %d:”/i+1);
scanf(“%d”/&temp );
}
printf(“\n\t\t the intitial”);
printf(” data are: ” );
printf(“\n\n\t\t” );
for(i=0 ;i
printf(” %3d”/temp );
for(i=k-1 ;i>0;i)–
for(j=0;j
if(temp[j]>temp[j+1])
{
item=temp[j] ;
temp[j]=temp[j+1];
temp[j+1]=item ;
}

printf(“\n\t\t the sorted data”);
printf(” are: ” );
printf(“\n\n\t\t” );
for(i=0 ;i
printf(” %3d”/temp );
}

نمونه ای از خروجی برنامه مثال ۳ : enter number 1:10
enter number 2:1
enter number 3:20
enter number 4:6
enter number 5:45
enter number 6:34
enter number 7:47
the initial data are:
10 1 20 6 45 34 47
the sorted data are:
1 6 10 20 34 45 47

مثال ۴: برنامه ای که با خواندن تعدادی عدد از ورودی آنها را در یک آرایه
قرار داده ، سپس کلیه عناصر آرایه را بر عنصر وسط تقسیم می کند . اگر عنصر وسط
صفر باشد ، بر عنصر بعد از عنصر وسط و اگر این عنصر نیز صفر باشد بر عنصر قبل
از عنصر وسط تقسیم می کند . اگر این عناصر صفر باشند برای پیدا کردن عنصری غیر
صفر و انجام عمل تقسیم به ترتیبی که در بالا گفته شد عمل می کند و اگر چنانچه
کلیه عناصر آرایه برابر با صفر باشند پیام مناسبی صادر می شود ( تعداد عناصر
آرایه فرد است ) . main)(
{
int i/j/m/k/sign/y ;
const int n=9 ;
int list[9] ;
printf(“\nenter 9 number and press”);
printf(” enter\n”);
for(i=0;i
scanf(“%d”/&list );
m=(n+1)/2-1 ;
k=list[m] ;
if(k==0)
{
j=1 ;
sign=1 ;
while(j
{
y=0 ;
while(y<2)
{
k=list[m+j*sign] ;
sign=-sign ;
if(k==0)
y++ ;
else
{
action(list/k/n );
break ;
}
}
j++ ;
}
printf(“\nall elemens are zero.”);
}
else
action(list/k/n );
}

action(int arr[]/int gol/int length)
{
int i ;
printf(“\n\t\t the intitial list:”);
printf(“\n\n\t\t” );
for(i=0 ; i
printf(” %3d”/arr );
for(i=0 ; i
arr=arr/gol ;
printf(“\n\t\t the final list: “);
printf(“\n\n\t\t” );
for(i=0 ; i
printf(” %3d”/arr );
}

دو نمونه از خروجی برنامه مثال ۴ :
( الف ) enter 9 number and press enter.
10 12 14 16 2 18 20 22 24
the initial list:
10 12 14 16 2 18 20 22 24
the final list:
5 6 7 8 1 9 10 11 12

( ب ) enter 9 number and press enter.

0 0 0 0 0 0 0 0 0
all elements are zero.

آرایه های چند بعدی
تاکنون نحوه تعریف و استفاده از آرایه های یک بعدی را مورد بررسی قرار
داده ایم . اکنون می خواهیم ببینیم که ” چگونه می توان آرایه بیش از یک بعدی را
تعریف کرده و به عناصر آن دسترسی پیدا کرد ” . در تعریف آرایه دو بعدی باید ۲
اندیس و در تعریف آرایه سه بعدی باید ۳ اندیس و در تعریف آرایه n بعدی باید n
اندیس را ذکر کرد . بعنوان مثال ، دستور : int table [10] [10];

یک آرایه دو بعدی بنام table را تعریف میکند که دارای ۱۰ سطر و ۱۰ ستون است
و نوع عناصر آن int است . دستور : int k[5] [10] [15];

آرایه ای سه بعدی بنام k را تعریف می کند که دارای ۵ سطر ، ۱۰ ستون و ۱۵
ارتفاع است و نوع عناصر آن int می باشد .
به دو نکته در مورد آرایه توجه کنید : ۱
عناصر آرایه در محل های متوالی حافظه ذخیره می شوند . ۲
عناصر آرایه به صورت سطر ذخیره می شوند . بعنوان مثال اگر آرایه ای بصورت [۴]
table [3] داشته باشیم مشابه شکل (۲) در حافظه ذخیره می شوند .
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | table [0] [0] |
| table [0] [0] |
| table [0] [1] |
| table [0] [2] |
| table [0] [3] |
| table [1] [0] |
| table [1] [1] |
| table [1] [2] |
| table [1] [3] |
| table [2] [0] |
| table [2] [1] |
| table [2] [2] |
| table [2] [3] |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ
شکل (۲) . نحوه ذخیره شدن آرایه در حافظه

مثال ۵: برنامه ای که با محاسبه جدول ضرب اعداد ۱ تا ۱۰، ضمن قرار دادن آنها
در یک آرایه به خروجی نیز منتقل می کند . main)(
{
int table[10] [10] ;
int i / j ;
for(i=0;i<10 ; i++)
for(i=0;i<10;i++)
table[j]=(i+1)*(j+1 );
for(i=0;i<10;i++)
{
for(i=0;i<10;i++)
printf(“%4d”/table [j] );
printf(“\n” );
}
}

خروجی حاصل از مثال ۵ : ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰
۲ ۴ ۶ ۸ ۱۰ ۱۲ ۱۴ ۱۶ ۱۸ ۲۰
۳ ۶ ۹ ۱۲ ۱۵ ۱۸ ۲۱ ۲۴ ۲۷ ۳۰
۴ ۸ ۱۲ ۱۶ ۲۰ ۲۴ ۲۸ ۳۲ ۳۶ ۴۰
۵ ۱۰ ۱۵ ۲۰ ۲۵ ۳۰ ۳۵ ۴۰ ۴۵ ۵۰
۶ ۱۲ ۱۸ ۲۴ ۳۰ ۳۶ ۴۲ ۴۸ ۵۴ ۶۰
۷ ۱۴ ۲۱ ۲۸ ۳۵ ۴۲ ۴۹ ۵۶ ۶۳ ۷۰
۸ ۱۶ ۲۴ ۳۲ ۴۰ ۴۸ ۵۶ ۶۴ ۷۲ ۸۰
۹ ۱۸ ۲۷ ۳۶ ۴۵ ۵۴ ۶۳ ۷۲ ۸۱ ۹۰
۱۰ ۲۰ ۳۰ ۴۰ ۵۰ ۶۰ ۷۰ ۸۰ ۹۰ ۱۰۰

مثال ۶: برنامه ای که دو ماتریس را از ورودی خوانده و با حاصل ضرب آنها ، به
خروجی منتقل می کند . main)(
{
int mat1[2][3]/mat2[3][4] ;
static int mat3[2][4]={0} ;
int i/j/k/l ;
for(i=0 ; i<2 ; i++)
{
for(i=0 ; i<3 ; i++)
{
printf(“\n\tenter”);
printf(” mat1[%d][%d] :”/i/j);
scanf(“%d”/&mat1[j] );
}
for(i=0 ; i<3 ; i++)
{
for(i=0 ; i<4 ; i++)
{
printf(“\n\tenter”);
printf(” mat2[%d][%d] :”/i/j);
scanf(“%d”/&mat2[j] );
}
}
for(i=0 ; i<2 ; i++)
{
for(i=0 ; i<4 ; i++)
{
mat3[j]=0 ;
for(k=0 ;k<3 ; k++)
mat3[j]=mat3[j]+mat1[k]*
mat2[k][j];
}
}
printf(“\nthe product of mat1 & “);
printf(“mat2 is: \n\n” );
for(i=0 ;i<2 ;i++)
{
for(i=0 ; i<4 ; i++)
printf(“%5d”/mat3[j] );
printf(“\n\n” );
}
}

نمونه ای از خروجی برنامه مثال ۶ : enter mat1[0][0]:1
enter mat1[0][1]:2
enter mat1[0][2]:3
enter mat1[1][0]:5
enter mat1[1][1]:4
enter mat1[1][2]:7
enter mat2[0][0]:8
enter mat2[0][1]:9
enter mat2[0][2]:5
enter mat2[0][3]:8
enter mat2[1][0]:10
enter mat2[1][1]:0
enter mat2[1][2]:12
enter mat2[1][3]:21
enter mat2[2][0]:0
enter mat2[2][1]:5
enter mat2[2][2]:9
enter mat2[2][3]:12

the product of mat1
 
ارزش دهی اولیه به آرایه ها

گاهی ممکن است در هنگام تعریف آرایه ها خواسته باشیم مقادیری را نیز به آنها
نسبت بدهیم . به این مقادیر ارزش های اولیه آرایه می گوییم . باید توجه داشت
که فقط آرایه های دارای کلاس های حافظه staticو externو می توانند مقادیر اولیه
را بپذیرند . برای ارزش دهی اولیه به آرایه ها از روش کلی زیر می توان استفاده
کرد : }
مقادیر]={طول بعدnام [..].طول بعد دوم ][طول بعداول [ <کلاس حافظه ><نوع><اسم آرایه >

در روش کلی فوق ، کلاس حافظه ، یکی از کلاس های static و یا extern است و
مقادیر که در داخل {} قرار می گیرند بترتیب به عناصر آرایه نسبت داده می شوند.
یعنی اولین مقدار به اولین عنصر ، دومین مقدار به دومین عنصر و n امین مقدار
به n امین عنصر آرایه نسبت داده می شوند .
در مورد ارزش دهی اولیه به آرایه ها ، باید دو نکته زیر را در نظر گرفت : ۱
اگر طول آرایه مشخص شود و تعداد مقادیری که به آرایه نسبت داده می شوند
کمتر از تعداد عناصر آرایه باشند ، بقیه عناصر صفر فرض خواهند شد . ۲
اگر طول آرایه مشخص نشود ، به تعداد مقادیری که به آرایه نسبت داده
می شوند ، منظور خواهد شد .

مثال ۱: نمونه ای از ارزش دهی اولیه به آرایه های یک بعدی . main)(
{
int i ;
static int array[5]={10/5/15/20/25};
static int table[]={5/6/8/9/11} ;
static int mix[5]={0} ;
printf(“\n\t tehe result of ” );
printf(“operation is:\n\n\t” );
for(i=0 ; i<4 ; i++)
{
mix=array+table ;
printf(“%d\t”/mix );
}
printf(“%d\t”/mix[4] );
}

خروجی برنامه مثال ۱ : the result of operation is:
15 11 23 29 0

در مثال ۱ اولین دستور ، آرایه ای از نوع صحیح با کلاس حافظه static را تعریف
می کند که طول آن ۵ بوده و مقادیر ۲۵ ، ۲۰ ، ۱۵، ۵، و ۱۰ را به عناصر آن نسبت
می دهد . دومین دستور ، آرایه ای بنام table را با طول نامشخص تعریف می کند و
و پنج مقدار ۵، ۶،، ۸،، ۹، و ۱۱ را به آن نسبت می دهد ، لذا کامپایلر طول این
را ۵ فرض خواهد کرد . سومین دستور آرایه ای بنام mix را با طول ۵ تعریف می کند
و به کلیه عناصر آن مقدار صفر را نسبت می دهد .
برای ارزش دهی اولیه آرایه دو بعدی و یا چند بعدی به دو روش می توان عمل
کرد . این دو روش با ذکر مثالی تشریح می شود .

مثال ۲: دستوراتی که به دو روش ، آرایه دو بعدی را ارزش اولیه می دهد : static int array[2][3]={1/2/3/4/5/6} ;
static int table[2][3]={3/4} ;
static int mix[2][3]={{1/2/3}/{4/5/6}};

اولین دستور، آرایه دو بعدی به ابعاد ۲ x 3 را تعریف کرده و مقادیر ۱، ۲، و ۳
به سطر اول و مقادیر ۴، ۵،و ۶و به سطر دوم نسبت داده می شوند . دومین دستور
مثال ۲ آرایه ای دو بعدی با ابعاد ۲ x 3 را تعریف می کند و دو مقدار۳و ۴و را به
آن نسبت می دهد که ۳ در محل table[1][1]و ۴و در محل table[1][2] قرار می گیرد
و بقیه عناصر آن صفر خواهند بود .
دستور سوم روش دیگری برای دستور اول است .

مثال ۳: نمونه ای از ارزش دهی اولیه به آرایه سه بعدی . static intthreed[3][2][4]=
{{{1.2.3.4}/
{5/6/7/8}/}/
{{7/9/3/2}/
{4/6/8/3}/}/
{{7/2/6/3}/
 
رشته ها

رشته ها معمولا” نوعی داده هستند که در زبانهای برنامه سازی به اشکال متفاوتی
مورد استفاده قرار گرفته و برای ذخیره کردن و دستکاری متن ها ، ( مثل کلمات
اسامی افراد ، جملات و غیره ) به کار می روند . اما در زبان C رشته ها نوعی داده
نیستند بلکه به صورت آرایه ای از کاراکترها ( از نوع char ) هستند که به NULL
( رشته تهی ) که دارای ارزش عددی صفر است ختم میشوند. برای نمایش NULL از ‘\۰′
استفاده می شود . بنابراین طول رشته ها را که بصورت آرایه تعریف می شوند ، باید
به اندازه یک واحد بیش از مقدار لازم در نظر بگیریم . مثلا” اگر بخواهیم رشته ای
را که طولانی ترین اسم آن دارای ۳۰ حرف باشد ، برای ذخیره کردن اسامی افراد
تعریف کنیم باید آرایه ای به طول ۳۱ را در نظر بگیریم . کامپایلر زبان C کاراکتر NULL
را به انتهای رشته ها اضافه می کند و نیازی نیست که برنامه نویس آن را در
انتهای رشته ها قرار دهد .

مثال ۱: main)(
{
char fname[21] ;
printf(“enter your name: ” );
scanf(“%d”/fname );
printf(“\nyour name is : %s”/fname);
}

نمونه ای از خروجی برنامه مثال ۱ : enter your name : ali
your name is : ali

رشته Ali در متغیر fname بصورت زیر قرار می گیرد :
ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ | a | l | i |\0 | | | | | | | | | | | | | | |

ؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤؤ ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ ۱۱ ۱۲ ۱۳ ۱۴ ۱۵ ۱۶ ۱۷

نکته ای که در مورد مثال ۱ باید روشن شود این است که تاکنون برای خواندن
مقادیر متغیرها از ورودی توسط تابع ()scanf ، اسم متغیر را با & ذکر می کردیم .
اما دلیلی که در این مثال برای خواندن محتویات رشته fnameاز &ز استفاده نشده
این است که fname نام یک آرایه است و نام آرایه بعنوان یک آدرس به اولین عنصر
 
بالا