بـــــــــــــــــــــســـــــــــــــــــم الـــــــــلــــــــــه الـــــــــــــــرحـــــــمــــــــــــــن الــــــرحیـــــــــــم

¸.¤°´¯`°¤ .¸آموزش هک¸.¤°´¯`°¤ .¸ - پست های آموزش زبان c


¸.¤°´¯`°¤ .¸آموزش هک¸.¤°´¯`°¤ .¸


مفاهیم اولیه در زبان c
پنجشنبه 9 اسفند 1386

مفاهیم اولیه زبان C

در این فصل به مقدمات اولیه برنامه نویسی به زبان  C می پردازیم و اصول اولیه آن را بررسی می نماییم

شناسه ها در C

شناسه (identifier) نامی است که به یک قسمت از برنامه مانند متغیر، تابع، ثابت و یا ... داده می شود. در زبان C برای انتخاب شناسه ها فقط می توان از علائم زیر استفاده کرد: - حروف انگلیسی کوچک و بزرگ (A…Z a…z)
- ارقام (0…9)
- علامت خط پایین یا _


البته یک شناسه تمی تواند با یک رقم شروع شود. مثلا شناسه های sum ، average ، name2 و یا student_average مجاز هستند، اما شناسه های 2name و یا student average مجاز نیستند. البته در برنامه نویسی امروزی پیشنهاد می شود بجای شناسه هایی همانند student_average از studentAverage استفاده گردد. یعنی بجای اینکه در شناسه ها از _ برای جداکننده استفاده کنیم، اولین حرف هر قسمت را بصورت بزرگ بنویسیم.

نکته مهم دیگری که باید به آن اشاره کرد آنستکه زبان C برخلاف بسیاری از زبانهای دیگر به کوچک و بزرگی حروف حساس است (case sensitive). در نتیجه شناسه های زیر با یکدیگر متفاوتند :

Sum ≠ sum ≠ SUM

این مسئله معمولا درهنگام برنامه نویسی باعث ایجاد بعضی خطاها می شود.
آخرین نکته اینستکه در هنگام انتخاب شناسه نمی توانید از کلمات کلیدی که برای منظورهای خاص در زبان C رزرو شده اند استفاده کنید. زبان C دارای 32 کلمه کلیدی است که عبارتند از :

 

auto

break

case

char

Const

continue

default

do

double

Else

enum

extern

float

for

Goto

if

int

long

register

Return

short

signed

sizeof

static

Struct

switch

typedef

union

unsigned

Void

volatile

while

 

 

 

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

انواع داده ها در C

همانطور که قبلا نیز گفتیم هر متغیر پیش از آنکه استفاده گردد ابتدا باید اعلان گردد. اعلان یک متغیر تعیین نوع آن را نیز دربر می گیرد. سوال اصلی آنستکه چه نوع داده هایی در زبان C و جود دارد. انواع داده های متداول عبارتند از :

 

نوع داده

توضیح

اندازه (بیت)

محدوده

char

کاراکتر

8

-128 to +127

int

عدد صحیح

16

-32768 to + 32767

float

عدد اعشاری

32

3.4e-38 to 3.4e+38

double

عدد اعشاری با دقت مضاعف

64

1.7e-308 to 1.7e+308

البته چند نکته مهم درمورد جدول فوق قابل ذکر است :

- اندازه int در محیطهای 16 بیتی مانند DOS برابر 16 بیت است. اما در محیطهای 32 بیتی همانند Windows اندازه آن 32 بیت می باشد که در اینصورت محدوده ای برابر -2,147,483,647 تا +2,147,483,647 را پوشش می دهد.

- در بعضی از کامپایلرهای C، نوع داده bool نیز وجود دارد که می تواند یکی از مقادیر true(درست) یا false (غلط) را نشان دهد . اما در نسخه های اولیه C از همان نوع داده صحیح یا int برای اینکار استفاده می شد. بدین صورت که 0 نشاندهنده false و هر عدد غیر صفر (معمولا 1) نشاندهنده true است.

- از آنجا که برای ذخیره سازی کاراکترها کد اسکی آنها ذخیره می گردد، از یک متغیر کاراکتری یا char می توان بعنوان یک عدد صحیح کوچک نیز استفاده کرد و اعمال ریاضی برروی آنها نیز مجاز است.

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

 این اصلاح کننده ها عبارتند از : short, long, signed, unsigned

تمام اصلاح کننده های فوق می توانند به نوع داده int اعمال شوند و اثر آنها بستگی به محیط دارد. مثلا در یک محیط 16 بیتی، short int بازهم برابر 16 بیت است ولی long int برابر 32 بیت خواهد بود. علاوه براین unsigned int باعث می شود که یک عدد 16 بیتی بدون علامت داشته باشیم که بازه بین 0 تا 65535 را پوشش می دهد. signed int نیز همانند int معمولی بوده و تفاوتی ندارد. البته ترکیب این اصلاح کننده ها نیز ممکن است. مثلا unsigned long int یک عدد 32 بیتی بدون علامت است که بازه 0 تا 4,294,967,295 را پوشش می دهد.

اما برروی نوع داده char فقط اصلاح کننده های signed و unsigned را می توان اعمال کرد. معمولا از اصلاح کننده unsigned وقتی استفاده می شود که قصد داشته باشیم از char بعنوان یک عدد صحیح مثبت بین 0 تا 255 استفاده کنیم.

برروی نوع داده double تنها اصلاح کننده long قابل اعمال است و دراینصورت عدد اعشاری با 80 بیت را خواهیم داشت که قادر است هر عددی در بازه 3.4e-4932 تا 1.1e+4932 را در خود نگاه دارد.

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

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

<type> <variable-list>;

که type یکی از نوع داده های گفته شده و variable-list لیستی از متغیرها است که با کاما از یکدیگر جدا شده اند. بعنوان مثال :

int sum;
float average;
long int a, b, c ;
unsigned long int i, j, k ;

علاوه براین می توان در هنگام تعریف متغیر به آن مقدار اولیه نیز داد. مثال :

int d = 0 ;

نكته مهم آنكه زبان C به متغیرها مقدار اولیه نمی دهد (حتی 0) و برنامه نویس خود باید اینكار را صریحا انجام دهد، درغیر اینصورت مقدار اولیه متغیر، نامعین خواهد بود.
تعریف متغیرها طبق اصول زبان C میتواند درهرجایی از برنامه صورت پذیرد، و متغیرهای تعریف شده از همان خط به بعد قابل استفاده خواهد بود. اما معمولا توصیه می گردد كه تعریف متغیرها در همان خط ابتدایی تابع و بلافاصله پس از { صورت پذیرد.

 ثوابت

ثابتها مقادیر ثابتی هستند كه مقدار آنها در حین اجرای برنامه تغییر نمی یابد. ثابتها می توانند از هریك از نوع داده های اصلی باشند. برای نمایش هر ثابت بسته به نوع آن عمل می كنیم كه شرح هریك در زیر آمده است :
4 ثوابت عددی صحیح : برای نمایش این دسته از ثوابت، از دنباله ای از ارقام بعلاوه علامت + یا - استفاده می كنیم. بعنوان مثال 45- و یا 3489 ثوابت صحیح هستند. در حالت عادی C هر عدد را در كوچكترین نوع داده ای كه می تواند قرار می دهد. مثلا عدد 85 در یك int قرار می گیرد، اما عدد 145398 در یك long int قرار خواهد گرفت. اما اگر قصد دارید یك عدد كوچك بعنوان long محسوب گردد، می توانید از پسوند L در انتهای آن استفاده می كنیم. مثلا 245L یك عدد long محسوب می شود.

 

long int a = 20L;

ضمن اینكه پسوند U در انتهای عدد نیز نشانه بدون علامت بودن آن است.
نكته دیگر آنكه C به شما اجازه می دهد درصورت لزوم ثوابت صحیح خود را در مبنای 8 یا 16 نیز كه از مبناهای متداول در برنامه نویسی هستند، بنویسید. برای نوشتن عدد در مبنای 8 باید آن را با 0 آغاز كنید، مثلا 0342 یك عدد در منای 8 محسوب می گردد. اما برای نوشتن یك عدد در مبنای 16 باید آن را با 0x آغاز نمایید، مانند 0x27A4.
8 ثوابت عددی اعشاری : برای نمایش اعداد اعشاری، باید از نقطه اعشار استفاده كنیم، مانند 237.45 ، اما نكته جالب آنستكه می توانید از نماد علمی نیز برای نمایش اعداد اعشاری استفاده كنید. برای اینكار كافی است از حرف e برای نمایش قسمت توان استفاده نمایید. بعنوان مثال :

-23.47 × 10 5 = -23.47e5
42.389 × 10 -3 = 42.389e-3

دقت كنید كه قسمت توان، حتما یك عدد صحیح است. نكته جالب اینجاست كه برخلاف مورد قبل، كامپایلر بطور پیش فرض داده های اعشاری را از نوع double فرض می كند.چنانچه دوست دارید ثابت شما ازنوع float درنظر گرفته شود، در انتهای آن F قرار دهید. ضمنا پسوند L نیز داده اعشاری را از نوع long double درنظر می گیرد. 10 ثوابت كاراكتری : برای نشان دادن ثوابت كاراكتری، آنها را در داخل ' قرار می دهیم. بعنوان مثال 'A' یك ثابت كاراكتری است.

char ch = 'S' ;

دقت كنید كه همانطور كه قبلا گفته شد، كد اسكی كاراكترها در متغیر ذخیره می گردد، بنابراین می توان از آن بعنوان یك عدد صحیح نیز استفاده كرد. نكته مهم دیگر آنستكه به تفاوت عدد 5 و كاراكتر '5' دقت داشته باشید. در حقیقت '5' برابر است با عدد 53 كه همان كد اسكی آن است.
از آنجا كه بعضی كاراكترها، مانند enter قابل نمایش نیستند، بهمین دلیل آنها را با استفاده از \ نمایش می دهیم. علاوه براین بعضی كاراكترها مانند خود " نیز چون دارای معنای خاص هستند، باید با استفاده از \ نمایش داده شوند. موارد مهم عبارتند از :

\n خط جدید
\t tab كاراكتر
\a بوق كامپیوتر \" "
\' ' \\ \


14 ثوابت رشته ای : C علاوه بر ثوابت فوق، از یك ثابت دیگر بنام رشته نیز حمایت می كند. رشته، دنباله ای از كاراكترها است كه در داخل " قرار می گیرند. بعنوان مثال "this is a test" یك رشته است. دقت كنید كه 'a' یك كاراكتر است، اما "a" یك رشته است كه فقط شامل یك كاراكتر می باشد.

عملگرها

عملگر، نمادی است كه به كامپایلر می گوید تا عملیات محاسباتی یا منطقی خاصی را برروی یك یا چند عملوند، انجام دهد. به عملگرهایی كه فقط یك عملوند دارند، عملگر یكانی می گوییم و همواره عملگر در سمت چپ عملوند قرار می گیرد(مانند عدد -125). اما عملگرهایی كه برروی دو عملوند اثر می كنند را عملگر دودویی نامیده و عملگر را بین دو عملوند قرار می دهیم (مانند 23+86). هر ترکیب درستی از عملگرها و عملوندها را یک عبارت می نامیم.


C از نقطه نظر عملگرها یك زبان بسیار قوی است. این عملگرها به چند دسته اصلی تقسیم می گردند كه آنها را به ترتیب بررسی می كنیم..

عملگرهای محاسباتی

این عملگرها، همان اعمال متداول ریاضی هستند كه در زبان C مورد استفاده قرار می گیرند. این اعمال عبارتند از :

عمل

نوع

عملگر

منفی كردن عملوند سمت راست

یكانی

-

جمع دو عملوند

دودویی

+

تفریق دو عملوند

دودویی

-

ضرب دو عملوند

دودویی

*

تقسیم دو عملوند

دودویی

/

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

دودویی

%

 

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

int a,b ;
float c,d ;
a = 10 ; b = 4 ;
c = 8.2; d = 4.0;

اكنون به نتایج عملیات زیر دقت كنید :

a / b = < 2
c / d = < 2.05
a / d = < 2.5
a / 4 = < 2

چنانچه به آخرین مورد توجه كنید، متوجه می شوید كه از آنجا كه a یك متغیر صحیح است و 4 نیز یك ثابت صحیح در نظر گرفته شده، درنتیجه تقسیم بصورت صحیح بر صحیح انجام گرفته است. چنانچه بخواهیم تقسیم بصورت اعشاری صورت پذیرد، به دو شكل می توانیم عمل كنیم. اول اینكه آن را بصورت a / 4.0 بنویسیم و دوم اینكه از عملگر قالب ریزی استفاده كنیم.
عملگر قالب ریزی می تواند یك نوع را به نوع دیگری تبدیل نماید. شكل كلی آن به شكل زیر است :

(< type > < expression >


كه type نوع مورد نظر است كه قصد تبدیل عبارت expression به آن نوع را داریم. بعنوان مثال در مورد بالا می توان به شكل زیر عمل كرد :

(float) a / 4

در این حالت ابتدا از كامپایلر خواسته ایم كه ابتدا عدد a را به اعشاری تبدیل كند (البته بصورت موقت) و سپس آن را بر 4 تقسیم نماید، كه مسلما حاصل اعشاری خواهد بود.
بطوركلی هرگاه ثابتها و متغیرهایی از انواع مختلف در یك عبارت محاسباتی داشته باشیم، كامپایلر C همه آنها را به یك نوع یكسان كه همان بزرگترین عملوند موجود است تبدیل خواهد كرد. بعنوان مثال به مورد زیر دقت كنید :

 

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

1        عملگر یکانی

2        عملگرهای * و / و %

3        عملگرهای + و

 

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

 

عبارت زبان c

ترتیب اجرای عملگرها

b + c * d

ابتدا عمل * و سپس عمل +

(b + c) * d

ابتدا عمل + و سپس عمل *

b + c / d * e

ابتدا عمل / سپس عمل * و در انتها عمل +

b + c / (d * e)

ابتدا عمل * سپس عمل / و در انتها عمل +

 

مثال زیر، یک مثال کامل در این زمینه می باشد :

عملگرهای انتساب

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

a = 5;
b = c + 2 * d;

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

int a;
a = 2.5 * 5.0;

که دراینصورت عدد 12 در a ذخیره خواهد شد.
شرکت پذیری این عملگر از راست به چپ می باشد، بدین معنا که چنانچه چندین عملگر نسبت دهی داشته باشیم، این عملگرها از راست به چپ محاسبه می شوند. مثلا پس از اجرای دستور زیر :

a = b = c = 10;

مقدار هر 3 متغیر برابر 10 خواهد شد.
نکته جالب درمورد زبان C آنستکه دارای یک سری عملگرهای انتساب خلاصه شده است که باعث می شوند در بعضی موارد بتوانیم عبارات کوتاهتری را بنویسیم. این عملگرها عبارتند از :

عملگر

مثال

عبارت انتساب معادل

++

a ++;

a = a + 1;

--

a --;

a = a – 1;

+=

a += 5;

a = a + 5;

-=

a -= 8;

a= a – 8;

*=

a *= 10;

a= a * 10;

/=

a /= 2;

a = a / 2;

%=

a %= 10;

a = a % 10;

عملگر اول و دوم، عملگرهای یکانی هستند که بترتیب عملگر افزایش و عملگر کاهش نامیده می شوند. نکته جالب آنستکه این دو عملگر به دوصورت مورد استفاده قرار می گیرند. در حالتی که از دستور a ++; استفاده شود به آن پس افزایش می گویند و بدین معناست که ابتدا از مقدار فعلی a در عبارت موردنظر استفاده کن و سپس آن را افزایش بده. اما دستور ++ a که به آن پیش افزایش گفته می شود، ابتدا a را افزایش داده و سپس از آن در عبارت استفاده می کند. به برنامه زیر دقت کنید:

#include < stdio.h >
void main() {
int a ,b ;
a = 5 ;
b = a ++;
printf(“a=%d and b=%d \n”,a,b);
a = 5 ;
b = ++ a;
printf(“a=%d and b=%d \n”,a,b);
}

 

a=6 b=5
a=6 b=6

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

عبارت عملگر متغیر = متغیر

که عملگر یکی از عملگرهای محاسباتی ( + ، - ، * یا / ) باشد، دراینصورت می توانیم آن را بصورت زیر بنویسیم:

عبارت =عملگر متغیر

عملگرهای مقایسه ای (رابطه ای)

این عملگرها دو عبارت را بایکدیگر مقایسه کرده و نتیجه را باز می گردانند. نتیجه می تواند درست (true) یا غلط (false) باشد. همانطور که قبلا نیز گفته شد در کامپایلرهای جدید C++ نوع داده bool اضافه شده است و بنابراین نتیجه این عملگرها یک مقدار bool است. اما در کامپایلرهای قدیمیتر، نتیجه این عملگرها یک عدد صحیح است که درصورت درست بودن 1 و درصورت غلط بودن 0 باز می گردانند. این عملگرها عبارتند از:

 

عملگر

مفهوم عملگر

مثال

<

بزرگتر (<

a > b

>

کوچکتر (>

a < b

=<

بزرگتر یا مساوی (≤)

a >= b

=>

کوچکتر یا مساوی (≥)

a <= b

==

مساوی (=)

a == b

=!

نامساوی (≠)

a != b

نکته مهمی که باید به آن دقت کرد عملگر مساوی (==) است، چرا که یک اشتباه بسیار متداول برنامه نویسان C استفاده اشتباه از عملگر انتساب (=) بجای عملگر تساوی (==) است که باعث ایجاد خطا در برنامه می شود.
اولویت این عملگرها از بالا به پایین بشرح زیر است:
3 عملگرهای <، > ، =< و = >
4 عملگرهای == و =!
لازم بذکر است که در هنگام مساوی بودن اولویت چند عملگر، این عملگرها از چپ به راست محاسبه می گردند.
عملگرهای منطقی
این عملگرها به شما اجازه می دهند که شرطهای ساده ای را که با استفاده از عملگرهای مقایسه ای ایجاد شده اند را با یکدیگر ترکیب نموده و شرطهای پیچیده تری را بسازید. این عملگرها عبارتند از :

 

عملگر

مفهوم عملگر

نحوه کار

مثال

&&

AND منطقی

اگر هر دو عملوند درست باشند, درست و در غیر اینصورت نادرست باز می گرداند.

a>0 && sw==1

||

OR منطقی

اگر هر دو عملوند نادرست باشند, نادرست و در غیر اینصورت درست باز می گرداند.

a<=100 |


نوشته شده توسط دیونه در پنجشنبه 9 اسفند 1386 و ساعت 12:02 ب.ظ


مقدمه ای بر زبان C
پنجشنبه 9 اسفند 1386


مقدمه ای بر زبان C


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

2- زبان اسمبلی : این زبان شکل ساده تر زبان ماشین است، بدین صورت که برای هر دستورالعمل زبان ماشین، یک اسم نمادین انتخاب شده است (مانند دستور ADD بجای کد دودویی دستورالعمل جمع) که بخاطر سپردن و برنامه نویسی با آنها برای انسانها ساده تر است. اما این برنامه ها برای ماشین قابل فهم نیست و باید قبل از اجرا شدن توسط برنامه مترجمی بنام اسمبلر به زبان ماشین تبدیل شود. توجه کنید که از آنجا که هر دستور زبان اسمبلی معادل یک دستور زبان ماشین است، این زبان نیز وابسته به ماشین می باشد و برنامه های نوشته شده به این زبان فقط برروی همان کامپیوتری که برای آن نوشته شده اند قابل اجرا است. علاوه براین کار با این زبانها هنوز هم نسبتا مشکل بود و فقط متخصصین کامپیوتر قادر به استفاده از آنها بودند.

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

- بیسیک (Basic): برای کاربردهای آموزشی
- فرترن (Fortran) : برای کاربردهای علمی و مهندسی
- پاسکال (Pascal) : برای کاربردهای آموزشی و علمی

و بالاخره زبان برنامه نویسی C که درمورد آن بیشتر صحبت خواهیم کرد. البته برنامه های نوشته شده به این زبانها ابتدا باید به زبان ماشین ترجمه شوند تا برروی کامپیوتر قابل اجرا باشند. برای ترجمه این زبانها از کامپایلرها و یا مفسرها (به فصل 1 مراجعه کنید) استفاده می شود.

تاریخچه C
 
برای بررسی تاریخچه زبان C باید به سال 1967 بازگردیم که مارتین ریچاردز زبان BCPL را برای نوشتن نرم افزارهای سیستم عامل و کامپایلر در دانشگاه کمبریج ابداع کرد. سپس در سال 1970 کن تامپسون زبان B را بر مبنای ویژگیهای زبان BCPL نوشت و از آن برای ایجاد اولین نسخه های سیستم عامل Unix در آزمایشگاههای بل استفاده کرد. زبان C در سال 1972 توسط دنیس ریچی از روی زبان B و BCPL در آزمایشگاه بل ساخته شد و ویژگیهای جدیدی همچون نظارت بر نوع داده ها نیز به آن اضافه شد. ریچی از این زبان برای ایجاد سیستم عامل Unix استفاده کرد اما بعدها اکثر سیستم عاملهای دیگر نیز با همین زبان نوشته شدند. این زبان با سرعت بسیاری گسترش یافت و چاپ کتاب "The C Programming Language" در سال 1978 توسط کرنیگان و ریچی باعث رشد روزافزون این زبان در جهان شد.

متاسفانه استفاده گسترده این زبان در انواع کامپیوترها و سخت افزارهای مختلف باعث شد که نسخه های مختلفی از این زبان بوجود آید که با یکدیگر ناسازگار بودند. در سال 1983 انستیتوی ملی استاندارد آمریکا (ANSI) کمیته ای موسوم به X3J11 را را مامور کرد تا یک تعریف فاقد ابهام و مستقل از ماشین را از این زبان تدوین نماید.در سال 1989 این استاندارد تحت عنوان ANSI C به تصویب رسید و سپس در سال 1990، سازمان استانداردهای بین المللی (ISO) نیز این استاندارد را پذیرفت و مستندات مشترک آنها تحت عنوان ANSI/ISO C منتشر گردید.

در سالهای بعد و با ظهور روشهای برنامه نویسی شی گرا نسخه جدیدی از زبان C بنام C++ توسط بیارنه استراوستروپ در اوایل 1980 در آزمایشگاه بل توسعه یافت. در C++ علاوه بر امکانات جدیدی که به زبان C اضافه شده است، خاصیت شی گرایی را نیز به آن اضافه کرده است.

با گسترش شبکه و اینترنت، نیاز به زبانی احساس شد که برنامه های آن بتوانند برروی هر ماشین و هر سیستم عامل دلخواهی اجرا گردد. شرکت سان مایکروسیستمز در سال 1995 میلادی زبان Java را برمبنای C و C++ ایجاد کرد که هم اکنون از آن در سطح وسیعی استفاده می شود و برنامه های نوشته شده به آن برروی هر کامپیوتری که از Java پشتیبانی کند(تقریبا تمام سیستمهای شناخته شده) قابل اجرا می باشد. شرکت مایکروسافت در رقابت با شرکت سان، در سال 2002 زبان جدیدی بنام C# (سی شارپ) را ارائه داد که رقیبی برای Java بشمار می رود.

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

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

اصلی ترین نکته در این روش عدم استفاده از دستور پرش (goto) است. تحقیقات بوهم و ژاکوپینی نشان داد که می توان هر برنامه ای را بدون دستور پرش و فقط با استفاده از 3 ساختار کنترلی ترتیب، انتخاب و تکرار نوشت.

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

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

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

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

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

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

کمی بعد زبان C ارائه گردید که علاوه بر دارا بودن ویژگیهای برنامه نویسی ساختیافته بدلیل سرعت و کارایی بالا مقبولیتی همه گیر یافت و هم اکنون سالهاست که بعنوان بزرگترین زبان برنامه نویسی دنیا شناخته شده است.

 مراحل اجرای یک برنامه C

برای اجرای یک برنامه C ابتدا باید آن را نوشت. برای اینکار می توان از هر ویرایشگر متنی موجود استفاده کرد و سپس فایل حاصل را با پسوند .C ذخیره نمود (فایلهای C++ با پسوند .CPP ذخیره می گردند). به این فایل، کد مبدا (source code) گفته می شود. مرحله بعدی تبدیل کد مبدا به زبان ماشین است که به آن کد مقصد (object code) گفته می شود. همانطورکه قبلا نیز گفته شد برای اینکار از یک برنامه مترجم بنام کامپایلر استفاده می شود. کامپایلرهای متعددی برای زبان C توسط شرکتهای مختلف و برای سیستم عاملهای مختلف نوشته شده است که می توانید برحسب نیاز از هریک از آنها استفاده نمایید. اما هنوز برنامه برای اجرا آماده نیست. معمولا برنامه نویسان از در برنامه های خود از یک سری از کدهای از پیش آماده شده برای انجام عملیات متداول (مانند محاسبه جذر و یا سینوس) استفاده می کنند که برنامه آنها قبلا نوشته و ترجمه شده است. این برنامه ها یا در قالب کتابخانه های استاندارد توسط شرکتهای ارائه کننده نرم افزار عرضه شده است و یا توسط دیگر همکاران برنامه نویس اصلی نوشته و در اختیار وی قرار داده شده است. در این مرحله باید کد مقصد برنامه اصلی با کدهای مربوط به این برنامه های کمکی پیوند زده شود. برای اینکار نیاز به یک پیوند زننده (Linker) داریم و نتیجه این عمل یک فایل قابل اجرا خواهد بود (در ویندوز این فایل پسوند .EXE خواهد داشت). مرحله بعدی اجرای برنامه و دادن ورودیهای لازم به آن و اخذ خروجیها می باشد. در شکل زیر این مراحل نشان داده شده اند.

مسلما طی مراحل بالا برای اجرای هر برنامه زمانبر می باشد، بهمین دلیل اکثر تولید کنندگان کامپایلرها، محیطهایی را برای برنامه نویسی ارائه کرده اند که کلیه مراحل بالا را بطور اتوماتیک انجام می دهند.

به این محیطها IDE (Integrated Development Environment) یا محیط مجتمع توسعه نرم افزار گفته می شود. این محیطها دارای یک ویرایشگر متن می باشند که معمولا دارای خواص جالبی همچون استفاده از رنگهای مختلف برای نشان دادن اجزای مختلف برنامه مانند کلمات کلیدی، و یا قابلیت تکمیل اتوماتیک قسمتهای مختلف برنامه می باشد. پس از نوشتن برنامه و با انتخاب گزینه ای مانند Run کلیه عملیات فوق بطور اتوماتیک انجام شده و برنامه اجرا می گردد. علاوه براین، این محیطها معمولا دارای امكانات اشكالزدایی برنامه (Debug) نیز می باشند كه شامل مواردی همچون اجرای خط به خط برنامه و یا دیدن محتویات متغیرها در زمان اجرا است. چند محیط معروف برنامه نویسی عبارتند از :

Borland C++ 3.1 برای محیط DOS
Borland C++ از نسخه 4 به بالا برای Windows
Microsoft Visual C++ برای محیط Windows
Borland C++ Builder برای محیط Windows

برای شروع ما از محیط Borland C++ 3.1 تحت Dos كه نحوه كار ساده تری نسبت به سایرین دارد استفاده می كنیم.
پس از نصب این نرم افزار، برنامه BC.exe را اجرا كنید تا وارد محیط borland c شوید

همانطور كه می بینید، این محیط از 3 قسمت اصلی تشكیل شده است :
- بخش ویرایش برنامه : بخش آبی رنگ وسط می باشد كه در حقیقت یك ویرایشگر است كه برنامه در آن تایپ می شود. همانطور كه می بینید در این ویرایشگر از رنگهای مختلف برای نشان دادن قسمتهای مختلف برنامه استفاده می شود. مثلا برای كلمات كلیدی از رنگ سفید استفاده شده است.

- بخش منوهای كاری : این بخش كه در قسمت بالا واقع شده است،- حاوی تعدادی منو (گزینه) برای انجام وظایف مختلف است. خلاصه این عملیات عبارتند از :
o منوی File : عملیاتی مانند باز كردن و یا ذخیره یك برنامه
o منوی Edit : عملیات ویرایش مانند حذف،o كپی و یا چسباندن یك قسمت از برنامه
o منوی Search : جستجوی و یا تعویض یك متن در برنامه
o منوی Run : اجرای برنامه بصورت كامل یا دستور به دستور
o منوی Compile : عملیات مربوط به كامپایل و پیوند برنامه
o منوی Debug : عملیات مربوط به اشكالزدایی مانند دیدن مقادیر متغیرها در زمان اجرا
o منوی Project : عملیات مربوط به مدیریت برنامه هایی كه شامل چندین فایل مستقل هستند (پروژه)
o منوی Options : عملیات مربوط به تنظیمات سیستم مانند نحوه كامپایل و یا رنگ پیش فرض محیط
o منوی Windows : عملیات مربوط به پنجره های باز فعلی (مربوط به چندین برنامه یا نمایش متغیرها و ... ) 
 خطاهای برنامه نویسی

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

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

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

a. خطاهای مهلک: در این دسته خطاها کامپیوتر بلافاصله اجرای برنامه را متوقف کرده و خطا را به کاربر گزارش می کند. مثال معروف این خطاها،b. خطای تقسیم بر صفر می باشد.

c. خطاهای غیرمهلک: در این دسته خطا،d. اجرای برنامه ادامه می یابد ولی برنامه نتایج اشتباه تولید می نماید. بعنوان مثال ممکن است دراثر وجود یک خطای منطقی در یک برنامه حقوق و دستمزد،e. حقوق کارمندان اشتباه محاسبه شود و تا مدتها نیز کسی متوجه این خطا نشود!

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

آخرین نکته اینکه در اصطلاح برنامه نویسی به هر گونه خطا، bug و به رفع خطا debug گفته می شود.

یك برنامه نمونه

در این قسمت برای آشنایی اولیه با زبان C یك برنامه نمونه آورده شده است كه بدون هیچ تغییری در محیط BorlandCPP  قابل اجرا است.
 

// This Program Computes the Area of a Circle
#include <stdio.h>
void main() {
int radius ;
float area;
printf("please enter radius : ");
scanf("%d",&radius);
area = 2 * 3.14 * radius;
printf("Area is %f",area);
{
please enter radius : 10
Area is 62.8

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

- خط اول یک توضیح درمورد برنامه است. در زبان C برای توضیحات یک خطی از علامت // استفاده می گردد. اما چنانچه توضیحات بیش از یک خط بود،- آن را با علامت /* شروع کرده و با */ پایان دهید. کامپایلر از این توضیحات صرفنظر خواهد کرد. این توضیحات باعث می شوند که برنامه شما خواناتر شده و دیگران بهتر آن را درک کنند.

- هر دستوری که با علامت # شروع شود،- یک دستور C نیست،- بلکه جزو دستورات پیش پردازنده محسوب می گردد. دستورات پیش پردازنده،- دستوراتی هستند که توسط کامپایلر قبل از شروع به کامپایل انجام می شوند. بعنوان مثال دستور #include باعث می شود که تعاریف اولیه مربوط به توابعی (زیربرنامه هایی) که قصد استفاده از آنها را داریم به برنامه اضافه شود. در مثال بالا برای استفاده از توابع printf و scanf که در کتابخانه استاندارد C تعریف شده اند،- فایل سرآمد stdio.h را که این توابع در آن تعریف شده اند را استفاده کرده ایم.

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

- در زبان C هر بلوک برنامه با علامت { آغاز شده و با } پایان می یابد. این دو معادل دستورات begin و end در زبانهای دیگر ازجمله پاسکال می باشند که برای سادگی زبان انتخاب شده اند.

- دو خط بعدی به تعریف متغیرهای radius و area می پردازد. در زبان C قبل از استفاده از هر متغیری باید آن را اعلان نمایید. اعلان متغیر شامل نام و نوع متغیر است. در مثال فوق،- متغیر radius از نوع عدد صحیح(integer) و متغیر area از نوع عدد اعشاری (float) تعریف شده اند.

- توابع printf و scanf جزو کتابخانه استاندارد C محسوب می گردند و به ترتیب برای چاپ اطلاعات در خروجی استاندارد (نمایشگر) و دریافت اطلاعات از ورودی استاندارد (صفحه کلید) استفاده می شوند. برای چاپ رشته مورد نظر باید آنها را در داخل علامت " قرار داد. درمورد این توابع بعداد توضیح خواهیم داد.

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

- از آنجا که C یک زبان قالب آزاد است،- می توان با استفاده از مکان نوشتن دستورات شکل بهتری به برنامه داد. بعنوان مثال دقت کنید که پس از شروع تابع main،- دستورات حدود 3 کاراکتر جلوتر نوشته شده اند. به این نحوه نوشتن دستورات دندانه گذاری می گویند. بطور کلی هربار که بلوک جدیدی آغاز می شود،- باید آن را کمی جلوتر برد. این مسئله باعث جدا شدن بلوکها از یکدیگر و خوانایی بهتر برنامه می شود.

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

 

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



نوشته شده توسط دیونه در پنجشنبه 9 اسفند 1386 و ساعت 12:02 ب.ظ

ساختارهای کنترلی در زبان c
پنجشنبه 9 اسفند 1386

ساختارهای کنترلی

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

اما زبان C دارای 3 نوع ساختار انتخاب می باشد که عبا رتند از : ساختار if یا ساختار تک انتخابی، ساختار if / else یا ساختار دو انتخابی و ساختار switch یا ساختار چند انتخابی. علاوه براین، این زبان دارای 3 نوع ساختار تکرار بنامهای while، for و do / while نیز می باشد که هریک را بطور کامل شرح خواهیم داد.

قرارداد: توجه کنید که در هنگام تشریح یک دستور، خود دستور با رنگ آبی و عملگرهای آن مانند () با رنگ قرمز نشان داده می شوند. قسمتهایی که در داخل <> قرار می گیرند، عبارت یا دستوری هستند که باید در هنگام استفاده جایگزین گردند.

ساختار انتخاب if

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

if (<expresion>) <statement>;

نحوه کار بدینصورت است که ابتدا عبارت موجود در قسمت <expression> ارزیابی می شود. در صورتیکه درست ارزیابی گردد، دستور قسمت <statement> اجرا  خواهد  شد  و  در  صورتیکه  نادرست  باشد،  بدون  اینکه  دستور  قسمت  <statement> را اجرا کند به دستور بعدی خواهد رفت. این دستور می تواند بصورت زیر نیز استفاده گردد: 

if (<expresion>) <statement 1>;
else <statement 2>;

در اینصورت ابتدا عبارت موجود در قسمت <expression> ارزیابی می شود. در صورتیکه درست ارزیابی گردد، دستور قسمت <statement 1> اجرا خواهد شد، و در صورتیکه نادرست باشد، دستور قسمت <statement 2> اجرا خواهد شد. در هر حال فقط یکی از این دو قسمت اجرا خواهد گردید.

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

بعنوان مثال چنانچه متغیر grade حاوی نمره دانشجو باشد و بخواهیم بر مبنای نمره وی، پیغام مناسبی چاپ کنیم، می توانیم از دستور زیر استفاده کنیم:

if (grade> = 10) printf(“Passed !”);
else printf(“Failed!”);

در حالت عادی دستور if منتظر یک دستور در بدنه خود می باشد، اما چنانچه می خواهید چندین دستور را در بدنه یک دستور if دهید، باید آنها را در داخل آکولاد باز وبسته { } قرار دهید. این مجموع دستورات را یک دستور مرکب می گویند. بطور کلی در زبان C هرجا که می توان یک دستور قرار داد، می توان از یک دستور مرکب نیز استفاده کرد. به یک دستور مرکب، بلوک نیز گفته می شود. بنابراین صورت کلی دستور if به شکل زیر است:

if (<expression>) {
<statement 1> ;
<statement 2> ;
….
<statement n> ;
}
else {
<statement 1> ;
<statement 2> ;
…….
<statement m> ;
}

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

برنامه 1) برنامه ای بنویسید که ضرایب یک معادله درجه 2 را دریافت و ریشه های آن را محاسبه و چاپ نماید.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
void main() {
int a, b, c;
float x1, x2, delta;
clrscr();
printf(“Please enter a, b and c : “);
scanf(“%d %d %d”, &a, &b, &c);
if (a==0) {
printf(“wrong equation!”);
exit(1) ;
}
delta = b*b – 4*a*c;
if (delta <0)
printf(“No answer !”);
else if (delta == 0) {
x1 = -b / (2*a);
printf(“There is one answer, x = %f”,x1);
}
else {
delta = sqrt(delta);
x1 = (-b+delta) / (2*a);
x2 = (-b-delta) / (2*a);
printf(“There are two answers, x1= %4.2f and x2= %4.2f”, x1, x2);
}
}
Please enter a, b and c : 3 -7 2
There is two answers, x1 = 2.00 and x2 = 0.33

چندین نكته درمورد برنامه بالا قابل ذكر است.

1- در این برنامه از 2 تابع جدید استفاده شده است.اولی تابع sqrt كه یك عدد را به عنوان ورودی دریافت و جذر آن را باز می گرداند. این تابع در فایل math.h تعریف شده است. و دیگری تابع exit كه باعث می شود اجرای برنامه خاتمه یابد. این تابع نیز در فایل stdlib.h تعریف شده است.

2- به نحوه دندانه گذاری در برنامه دقت كنید، هرجا كه بلوك جدیدی ایجاد شده است، دستورات آن حدود 3 كاراكتر جلوتر نوشته شده اند. اینكار باعث می شود كه خوانایی برنامه افزایش یابد.

3- توجه كنید كه همانطور كه قبلا نیز گفته شد، خروجی یك عبارت مقایسه ای، یك عدد است كه 0 نشانه نادرست و هر عدد دیگر نشانه درست است. بنابراین در قسمت شرط یك دستور if می توان بجای یك عبارت مقایسه ای، هر عبارت دیگری كه یك مقدار عددی بازگرداند نیز قرار داد! بعنوان مثال می توان بجای دستور

if (a==0) …

از دستور زیر استفاده كرد:

if (!a) …

دراینصورت چنانچه a برابر صفر باشد، نادرست تلقی خواهد شد و در نتیجه نقیض آن یعنی ! ، درست محسوب می گردد.
یك روش متداول استفاده از دستور if، استفاده از if های تودرتو می باشد كه در مثال بالا نیز دیده می شود. دراینحالت مجموعه ای از عبارات if-else-if بصورت متداخل قرار داده می شوند. بعنوان نمونه به مثال زیر توجه كنید:

if (grade> = 18) printf("good!");
else if (grade> = 15) printf("medium!");
else if (grade> = 12) printf("rather weak!");
else if (grade> = 10) printf("weak");
else printf("failed!");

در چنین دستوری، كلیه شرطها بترتیب از بالا به پایین بررسی شده و به محض اینكه یكی از آنها درست باشد، دستور مربوط به آن اجرا شده و از بقیه دستورات صرفنظر می گردد. درصورتیكه هیچ یك از شرطها درست نباشد، دستور مربوط به آخرین else اجرا می گردد. درچنین حالتی توصیه می گردد كه شرطهای نادر را كه امكان وقوع آنها كم است، در انتهای كار بررسی نمایید، تا تعداد مقایسه كمتری صورت پذیرد.

مشكلی كه در مورد if های تودرتو پیش می آید، مسئله تعیین if مربوط به هر else است. بعنوان مثال در مورد دستور زیر، else به كدام if تعلق دارد؟

if (a <b)
if (c <d) <statement1>;
else <statement2>;

همانطور كه از دندانه گذاری نیز مشخص است، else مربوط به دومین if می باشد. یعنی <statement 2> درصورتی اجرا خواهد شد كه a<b درست باشد، اما c<d درست نباشد. بطور كلی طبق قوانین گرامری، هر else مربوط به نزدیكترین if قبل از خود می باشد. اما سوال این است كه اگر بخواهیم else به if اول بازگردد از چه روشی استفاده نماییم. دراینصورت می توان از یكی از دو روش زیر استفاده كرد:

if (a < b) if (a <b) {
if (c <d) <statement 1> ; if (c <d) <statement1>;
else ; }
else <statement2>; else <statement2>;

بعنوان یك مثال دیگر، به نمونه زیر دقت كنید:

if (<c1>) {
if (<c2>)
if (<c3>) <statement2>;
else <statement 3>; // this refer to if (<c3>)
}
else <statement 4>;//this refer to if <c1>

برنامه 2) برنامه ای بنویسید كه 3 عدد را دریافت و حداكثر آنها را چاپ كند.

#include <stdio.h>
void main() {
int a, b, c, max;
printf("Please enter 3 numbers :");
scanf("%d %d %d",&a, &b, &c);
if (a> b)
if (a> c) max = a;
else max= c;
else if (b> c) max = b;
else max = c;
printf("Maximum is %d",max);
}

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

همانطور كه در بخش الگوریتمها نیز گفته شد، یك ساختار تكرار باعث می شود تا زمانیكه شرط خاصی برقرار است، عملیات مشخصی تكرار گردد. دستور while نیز باعث ایجاد یك حلقه تكرار به شكل زیر می گردد:

while (<expression>) <statement>;

این  دستور  باعث  می  شود  تا  زمانیكه  شرط  موجود  در  قسمت  <expression> درست است،  دستور   قسمت  <statement> تكرار شود، و به محض اینكه شرط نادرست گردد، كنترل اجرا به دستور بعد از حلقه می رود.

بازهم دستور موجود در قسمت <statement> می تواند یك دستور مركب باشد، دراینصورت دستور بصورت زیر درخواهد آمد:

while (<expression>) {
<statement1>;
<statement2>;
…….
<statementn>;
}

برنامه 3) برنامه ای بنویسید كه یك عدد را دریافت و فاكتوریال آن را محاسبه و چاپ نماید.

#include <stdio.h>
void main() {
int i,number;
long int factorial;
printf("Please enter number :");
scanf("%d",&number);
factorial = 1;
i = 1;
while (i <= number) {
factorial *= i;
i ++;
}
printf("Factorial of %d is %ld"number,factorial);
}

برنامه 4) برنامه ای بنویسید كه یك متن را از كاربر دریافت و آن را با حروف بزرگ چاپ كند.

#include <stdio.h>
void main() {
char ch;
ch = getch() ;
while (ch != 13) {
if (ch>= 'a' && ch <= 'z')
ch -= 32;
putch(ch);
ch = getch();
}
}

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

همانگونه كه در مثال مربوط به حل مسئله فاكتوریال دیده می شود، گاهی نیاز به حلقه تكراری داریم كه به تعداد دفعات مشخصی تكرار گردد. در چنین مواقعی با استفاده از یك متغیر شمارنده، تعداد تكرارها را تا رسیدن به مقدار مورد نظر می شماریم و سپس به حلقه پایان می دهیم. به چنین حلقه هایی، تکرار تحت کنترل شمارنده یا تکرار معین می گوییم، چرا که تعداد تکرار ها از قبل مشخص است. چنین حلقه ای دارای 3 جزء اصلی می باشد:

1- مقداردهی اولیه به متغیر شمارنده حلقه
2- شرط پایان حلقه (پایان شمارش)
3- نحوه افزایش متغیر شمارنده

از آنجا که در تمام حلقه هایی که تکرار معین دارند، همین ساختار استفاده می شود؛ در اکثر زبانهای برنامه سازی یک ساختار تکرار ویژه، بنام حلقه for، برای اینکار در نظر گرفته شده است. اما در این بین، حلقه تکرار for در زبان C دارای ویژگیهای خاصی است که آنرا از سایر زبانها متمایز کرده و به آن قدرت بسیار بالایی داده است. شکل کلی این دستور بصورت زیر است:

for (<exp1> ; <exp2> ; <exp3> ) <statement>;

وظایف عبارات فوق بشرح زیر است :

1- <exp1>، مقداردهی اولیه به متغیر حلقه

2- <exp2>، شرط اجرای حلقه

3- <exp3>،نحوه افزایش متغیر حلقه

البته همانندموارد قبل بازهم قسمت <statement> می تواند یک دستور مرکب باشد. نحوه کار حلقه بدینصورت است که در ابتدای شروع حلقه <exp1> فقط برای یکبار اجرا می شود. سپس عبارت <exp2> بررسی می گردد و در صورتیکه درست ارزیابی شود (≠ 0)، آنگاه دستور <statement> اجرا شده و سپس به ابتدای حلقه باز می گردد. از اجرای دوم به بعد، ابتدا عبارت <exp3> اجرا می گردد (یعنی متغیر حلقه افزایش می یابد) و سپس عبارت <exp2> بررسی می گردد و مجددا درصورت درست بودن، حلقه تکرار می شود. اینکار تا زمانیکه مقدار عبارت <exp2> نادرست ( = 0) ارزیابی شود، تکرار می گردد. به محض اینکه این اتفاق بیفتد، کنترل اجرا به دستور پس از حلقه انتقال می یابد.
درحقیقت هر حلقه for معادل با حلقه while زیر است:

<exp1> ;
while (<exp2>) {
<statement>;
<exp3>;
}

بعنوان یک مثال ساده، تکه برنامه زیر اعداد بین 0 تا 100 را چاپ می نماید:

int count;
for (count = 0; count <= 100; count ++)
printf(“%d “,count);

اگر بخواهیم تنها مضارب 5 چاپ شوند، حلقه را به شكل زیر تغییر می دهیم:

for (count = 0; count <= 100; count += 5)

حتی می توان مضارب 5 را از آخر به اول چاپ كرد:

for (count = 100; count> = 0; count -= 5)

قسمت شرط می تواند یك شرط مركب نیز باشد، بعنوان مثال:

for (count = 0; count <100 && sw==1; count ++)

كه در اینصورت در هربار اجرای حلقه، علاوه بر مقدار شمارنده، مقدار متغیر sw نیز بررسی می گردد.

نكته آخر اینكه قسمت مقدار دهی اولیه و افزایش متغیر نیز می توانند شامل چند عبارت باشند كه در اینصورت با كاما از یكدیگر جدا می شوند. بعنوان مثال:

for (a = 0, b = 100; b – a> 50; a++, b--)

در ادامه یک مثال کاملتر برای تشریح این حلقه آمده است:

برنامه 5) برنامه ای بنویسید که تعدادی عدد را از کاربر دریافت و 2 عدد بزرگتر و مجموع آنها را محاسبه و چاپ نماید.

#include <stdio.h>
void main() {
int i, n, number;
int sum, max1, max2;
printf(“please enter n : “);
scanf(“%d”,&n);
sum = 0;
max1 = max2 = -1;
for (i=1 ; i<n ; i++) {
printf(“enter number : “);
scanf(“%d”,&number);
sum += number;
if (number> max1) {
max2 = max1;
max1 = number;
}
else if (number> max2)
max2 = number;
} //end for
printf(“Sum = %d, Maximum 1=%d, Maximum 2= d”, sum, max1, max2);
}

نكته جالب در مورد حلقه for آنستكه می توان هریك از 3 عبارت فوق را حذف كرد. به مثالهای زیر توجه كنید:

for (;i<1