عملگرها

عملگر، نمادی است كه به كامپایلر می گوید تا عملیات محاسباتی یا منطقی خاصی را برروی یك یا چند عملوند، انجام دهد. به عملگرهایی كه فقط یك عملوند دارند، عملگر یكانی می گوییم و همواره عملگر در سمت چپ عملوند قرار می گیرد(مانند عدد -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 || b!=0

!

NOT منطقی

اگر عملوند درست باشد، نادرست و اگر نادرست باشد، درست برمی گرداند.

! (a==1 || b<10)

همانطور که قبلا نیز گفته شد مقدار بازگشتی این عملگرها، درست (1) یا نادرست (0) می باشد. اولویت این عملگرها بترتیب عبارتست از :

1- عملگر !

2- عملگر &&

 3- عملگر ||

عملگر شرطی

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

عبارت2 : عبارت1 ? شرط

نحوه کار بدینصورت است که درصورت درست بودن شرط عبارت1 و در غیراینصورت عبارت 2 بازگردانده می شود. مثال :

a = (k<10) ? 100 : 50;

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

if(k<10) a=100;
else a=50;

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


c += (a>0 &&a<10) ? ++a : a/b;
که معادل است با :
if (a>0 &&a<10) {
a= a + 1;
c = c + a;
}
else c = c + a/b;


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

چند نکته درمورد عملگرها


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

شکل نامناسب

result=a-b*c/d+f*g;

شکل بهتر

result = a – b * c / d + f * g

شکل کاملا مناسب

result = a – ( b * c / d) + (f * g)


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

 

اولویت

عملگر

شرکت پذیری

1

()

از چپ به راست

2

++   --   !   +   -

از راست به چپ

3

%   /   *

از چپ به راست

4

-   +

از چپ به راست

5

>>   <<

از چپ به راست

6

>=   >   <=   <

از چپ به راست

7

=!   ==

از چپ به راست

8

&&

از چپ به راست

9

||

از چپ به راست

10

?:

از راست به چپ

11

=%   =/   =*   =-   =+   =

از راست به چپ

12

,

از چپ به راست

 

خواندن و نمایش اطلاعات

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

اما در عوض دارای تعدادی تابع (زیربرنامه) استاندارد می باشد كه تقریبا تمامی كامپایلرها از آنها حمایت می كنند. این كار به كامپایلر این امكان را می دهد كه بر حسب نوع سخت افزار موردنظر، توابع ورودی و خروجی را طراحی نماید. این توابع در یك فایل سرآمد بنام stdio.h تعریف شده اند و بنابراین قبل ازاینكه بتوانید از این توابع استفاده نمایید، باید این فایل را نیز با استفاده از #include در برنامه خود بگنجانید.

تابع نمایش در خروجی

برای نمایش اطلاعات در خروجی از تابع printf استفاده می شود. این تابع رشته موردنظر شما را به خروجی استاندارد (كه در حالت عادی همان صفحه نمایش یا مانیتور است) می فرستد. شكل كلی این تابع بصورت زیر است:

printf(< لیست متغیرها > , < رشته کنترلی >) ;

رشته كنترلی همان متنی است كه قصد چاپ آن را داریم، با ذكر این نكته كه در قسمتهایی كه باید مقدار یك متغیر چاپ شود، از یك مشخصه تبدیل استفاده می شود. هر مشخصه تبدیل از یك علامت % بعلاوه یك كاراكتر كه نوع متغیر مورد نظر را نشان می دهد تشكیل می گردد. مشخصه تبدیل های متداول عبارتند از :

مفهوم

مشخصه تبدیل

كاراكتر

%c

عدد صحیح در مبنای 10

%d

عدد اعشاری بدون نماد علمی

%f

عدد اعشاری با نماد علمی

%e

عدد اعشاری با حالت كوتاهتر بین e و f

%g

رشته

%s

عدد صحیح بزرگ

%ld

عدد اعشاری بزرگ

%lf  %le  %lg

عدد صحیح در مبنای 8

%o

عدد صحیحی در مبنای 16

%x

عدد صحیح بدون علامت

%u

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

#include
void main() {
int age = 20;
floate average = 18.23;
printf("You are %d years old and your average is %f \n",age,average);
}
You are 20 years old and your average is 18.230000

دقت كنید كه علامت \n انتهای رشته كنترلی باعث می شود كه خروجی بعدی برنامه (در صورت وجود) در خط بعد چاپ شود. البته ممكن است نحوه چاپ عدد اعشاری به شكل فوق چندان برای شما دلخواه نباشد و بخواهید تعداد ارقام اعشاری قابل نمایش را محدود كنید. برای اینكار باید از مشخصه طول میدان استفاده كنید. مشخصه طول میدان برای اعداد به شكل زیر استفاده می شود:

برای اعداد صحیح از %nd استفاده می كنیم كه n تعداد ارقام را نشان می دهد (مثلا %3d). در اینصورت برای هر متغیر n رقم درنظر گرفته می شود. اگر اندازه عدد از n كوچكتر باشد، به سمت چپ آن فضای خالی اضافه می شود و اگر اندازه عدد بیش از n رقم باشد، طول میدان نادیده گرفته شده و عدد بطور كامل چاپ می شود.

برای اعداد اعشاری از %n.mf استفاده می كنیم كه n اندازه كل عدد (شامل علامت ممیز) و m تعداد ارقام اعشار است (مثلا %5.2f). در صورتیكه تعداد ارقام اعشاری عدد موردنظر از m بیشتر باشد، عدد به m عدد اعشار گرد می شود و در صورتیكه از m كمتر باشد، در سمت راست آن 0 قرار داده می شود.

البته موارد دیگری نیز در مورد نحوه چاپ وجود دارد كه برای اطلاع از آنها می توانید به قسمت Help كامپایلر خود مراجعه نمایید.

آخرین نكته درمورد تابع printf اینكه این تابع مقدار بازگشتی نیز دارد كه درصورت موفقیت عمل چاپ، تعداد كاراكترهای چاپ شده و درصورت عدم موفقیت مقدار -1 را باز می گرداند. البته معمولا از این مقدار بازگشتی صرفنظر می گردد.