در قسمت قبل با مبحث بسیار مهم cast کردن آشنا شدید و دانستید که چگونه میتوان نوعهای مختلف را به یکدیگر تبدیل کرد. در این قسمت قصد داریم با عملگرهای منطقی و بیتی و آرایهها که یکی دیگر از مباحث مهم در برنامهنویسی هستند آشنا شویم.
عملگرهای منطقی (Logical Operators)
در عملگرهای منطقی ما با عملوندهایی از جنس بولین سروکار داریم که در نهایت نتیجه از جنس bool خواهد بود. عملگرهای منطقی شامل AND و OR و XOR و NOT هستند که بهترتیب با علامتهای & و | و ^ و ! مشخص میشوند.
در شکل زیر جدول درستی عملگرهای منطقی را میبینید:
بدیهی است که باید این جدول را به ذهن خود بسپارید. خروجی XOR زمانی برابر با true است که یکی و تنها یکی از عملوندها true باشد.
به مثال زیر دقت کنید:
using System; class Example { static void Main() { bool p, q; p = true; q = false; if (p & q) Console.WriteLine("this won't execute"); if (!(p & q)) Console.WriteLine("!(p & q) is true"); if (p | q) Console.WriteLine("p | q is true"); if (p ^ q) Console.WriteLine("p ^ q is true"); } }
با مقایسهی برنامهی بالا با جدول درستی، متوجه خواهید شد که چه اتفاقی در حال افتادن است. با اعمال عملگرهای منطقی بهروی عملوندهای بولین، نتیجهای از جنس بولین حاصل خواهد شد که موجب اجرا یا عدم اجرای دستور if میشود.
عملگر Implication
یکی دیگر از عملگرهای منطقی عملگر implication است. این عملگر نیز پاسخی از نوع بولین دارد. در این عملگر تنها زمانی که عملوند سمت چپ برابر با true و عملوند سمت راست برابر با false است، پاسخ برابر با false میشود:
نتیجهای که از این عملگر گرفته میشود این است: اگر مقدار p برابر با true است آنگاه مقدار q نیز باید true باشد. عملیات implication از طریق الگوی زیر انجام میشود:
!p | q
به مثال زیر توجه کنید:
using System; class Example { static void Main() { bool p, q; p = true; q = true; Console.WriteLine("p is " + p + ", q is " + q + ""); Console.WriteLine("" + p + " implies " + q + " is " + (!p | q) + ""); Console.WriteLine(); p = true; q = false; Console.WriteLine("p is " + p + ", q is " + q + ""); Console.WriteLine("" + p + " implies " + q + " is " + (!p | q) + ""); Console.WriteLine(); p = false; q = false; Console.WriteLine("p is " + p + ", q is " + q + ""); Console.WriteLine("" + p + " implies " + q + " is " + (!p | q) + ""); Console.WriteLine(); p = false; q = true; Console.WriteLine("p is {0}, q is {1}", p, q); Console.WriteLine("{0} implies {1} is {2}", p, q, (!p | q)); Console.WriteLine(); } }
در مثال بالا حالتهای مختلف implication را مشاهده میکنید. همانطور که میبینید تنها زمانی که عملوند سمت چپ برابر با true و عملوند سمت راست برابر با false است، پاسخ برابر با false میشود.
عملگرهای منطقی Short-Circuit یا اتصال کوتاه
سیشارپ ورژن مخصوصی برای AND و OR تدارک دیده که به Short-Circuit یا اتصال کوتاه معروف هستند. استفاده از Short-Circuit موجب میشود کد بهینهتر و پر سرعتتری داشته باشید. همانطور که میدانید در AND اگر عملوند اول False باشد آنگاه جواب False است و در OR اگر عملوند اول True باشد پاسخ True خواهد بود. کاری که Short-Circuit انجام میدهد این است که در این موارد، بقیهی حالتها را ارزیابی نکرده و مستقیماً جواب نهایی را میدهد در صورتیکه در AND و OR معمولی همهی حالتها بررسی میشوند. علامت Short-Circuit AND بهصورت && و علامت Short-Circuit OR بهصورت || است که همچنین با عناوین Conditional AND و Conditional OR نیز شناخته میشوند.
به نمونهی زیر توجه کنید:
using System; class Example { static void Main() { int i; bool someCondition = false; i = 0; // Here, i is still incremented even though the if statement fails. if (someCondition & (++i < 100)) Console.WriteLine("this won't be displayed"); Console.WriteLine("if statement executed: " + i); // displays 1 // In this case, i is not incremented because the short-circuit // operator skips the increment. if (someCondition && (++i < 100)) Console.WriteLine("this won't be displayed"); Console.WriteLine("if statement executed: " + i); // still 1 !! } }
در این برنامه متغیر iدر ابتدا برابر صفر است. در دستور شرطی if بهدلیل وجود عملگر AND معمولی، هردو عملوند آن ارزیابی میشوند بنابراین i یک واحد افزایش مییابد. در دستور if بعدی بهدلیل وجود Short-Circuit AND عملوند اول ارزیابی میشود که بهدلیل False بودن، دیگر عملوند دوم ارزیابی نشده و i افزایش پیدا نمیکند.
عملگرهای بیتی (The Bitwise Operators)
عملگرهای بیتی مستقیماً روی بیتهای عملوندشان کار میکنند و تنها برای مقادیر صحیح تعریف شدهاند و نمیتوانند برای نوعهای bool، float و double بهکار گرفته شوند. این عملگرها برای اعمالی چون برنامهنویسی در سطوح پایین سیستم بهکار میروند. عملگرهای بیتی شامل AND و OR و XOR و NOT هستند که بهترتیب با نشانههای & و | و ^ و ~ نشان داده میشوند. تفاوت عملگرهای بیتی با عملگرهای منطقی در این است که عملگرهای بیتی مستقیماً روی تک تک بیتهای عملوندشان کار میکنند. جدول زیر خروجی هر عملگر را با استفاده از صفر و یک نشان میدهد:
به نمونهی زیر توجه کنید:
using System; class Example { static void Main() { int i = 25; // Bits of i: 00011001 int j = 30; // Bits of j: 00011110 int resutl = i & j; // (00011001) & (00011110) produce 00011000 Console.WriteLine("First Number: {0}\nSecond Number: {1}", i, j); Console.WriteLine(); Console.WriteLine("Result of AND Operation: " + resutl); // Result is 00011000 that means 24 resutl = i | j; // (00011001) | (00011110) produce 00011111 Console.WriteLine("Result of OR Operation: " + resutl); // Result is 00011111 that means 31 resutl = i ^ j; // (00011001) | (00011110) produce 00000111 Console.WriteLine("Result of XOR Operation: " + resutl); // Result is 00000111 that means 7 resutl = ~i; // ~(00011001) produces 11100110 Console.WriteLine("Result of NOT Operation: " + resutl); // Result is 11100110 that means -26 } }
معادل صفر و یک متغیرهای i و j در قسمت کامنتها نوشته شده است. این صفر و یکها طبق جدول با یکدیگر AND و OR و XOR و NOT میشوند و مقادیر جدیدی را تولید میکنند.
دو عملگر بیتی دیگر با نامهای Shift left و Shift right وجود دارند که بهترتیب با نمادهای >> و << نشان داده میشوند. توسط این دو عملگر میتوانید بیتها به سمت چپ یا راست انتقال دهید.
فرم کلی این دو عملگر بهشکل زیر است:
value << num-bits value >> num-bits
در اینجا value عددی است که قصد داریم بیتهای آنها را به تعداد num-bits به چپ یا راست شیفت دهیم.
به نمونهی زیر دقت کنید:
int result = 2 << 1; // 0010 becomes 0100 (Left shift) Console.WriteLine(result);
در Shift right/Shift left بیتها از مکان فعلی خودشان بهاندازه یک بیت به چپ/راست انتقال مییابند. در مثال بالا بیتهای عدد 2 را بهاندازه یک بیت به سمت چپ انتقال دادهایم که موجب شده است عدد 2 به عدد 4 تبدیل شود.
int result = 8 >> 1; // 1000 becomes 0100 (Right shift) Console.WriteLine(result);
در اینجا بیتهای عدد 8 را بهاندازه یک بیت به سمت راست انتقال دادهایم که موجب شده است عدد 8 به 4 تبدیل شود. بنابراین نتیجه میگیریم که یه بیت شیفت به چپ مقدار را دو برابر و یک بیت شیفت به راست مقدار را نصف میکند. در پروژهایی با مقیاس بزرگ از این روش (بهجای استفاده از ضرب و تقسیم معمولی) برای بالا بردن سرعت برنامه استفاده میکنند.
آرایه
آرایه مجموعهای از متغیرها با نوعی مشخص است که همهگی با یک نام شناخته میشوند. در سیشارپ آرایهها میتوانند یک بعد یا بیشتر از یک بعد داشته باشند اما با این حال آرایه یک بعدی رایجترین نوع آرایه است.
آرایه یک بعدی
آرایه یک بعدی لیستی از متغیرهای مرتبط به هم است. تصور کنید که میخواهید لیستی از نام کتابهای برنامهنویسی خودتان را داشته باشید. بنابراین شما باید آرایهای از جنس string داشته باشید تا نام کتابهای خود را در آن قرار دهید. برای تعریف آرایه یک بعدی نیاز است که جنس ، اسم و اندازه آرایه را مشخص کنید.
آرایه یک بعدی از طریق الگوی زیر تعریف میشود:
type[] array-name = new type[size];
در اینجا type مشخص کنندهی جنس آرایه و size مشخص کنندهی تعداد عناصری است که میتوان در این آرایه قرار داد. array-name نیز نام آرایه را مشخص میکند.
به نمونهی زیر توجه کنید:
int[] myArray = new int[10];
در اینجا ما آرایهای با نام myArray از جنس int تعریف کردهایم که 10 عنصر را میتواند در خود نگهداری کند. توجه داشته باشید که عنصرهای این آرایه همهگی باید از جنس int باشند.
آرایهای که تعریف کردیم را در شکل زیر میتوانید ببینید:
برای دسترسی به هر خانهی آرایه نیاز است که شماره index آن خانه را صدا بزنید. در سیشارپ شماره index اول آرایهها برابر با صفر است. در اینجا که اندازهی myArray برابر با 10 است، index های آن از شماره 0 تا 9 هستند. بنابراین برای دسترسی به خانهی اول آرایه باید اسم آرایه و در جلوی آن شماره index خانهی اول آرایه که در براکت باز و بسته قرار دارد را بنویسید.
دسترسی به خانهی اول:
myArray[0]
دسترسی به خانهی آخر:
myArray[9]
برای مقداردهی به خانههای آرایه بدین صورت عمل میکنیم:
myArray[0] = 20; myArray[1] = 13; myArray[2] = 16; . . .
به مثال زیر توجه کنید:
using System; class Example { static void Main() { int[] myArray = new int[10]; myArray[0] = 20; myArray[1] = 13; myArray[2] = 16; myArray[3] = 36; myArray[4] = 160; myArray[5] = 180; myArray[6] = 340; myArray[7] = 8; myArray[8] = 55; myArray[9] = 123; for (int i = 0; i < 10; i++) { Console.WriteLine("myArray[" + i + "]: " + myArray[i]); } } }
در این مثال ابتدا خانههای آرایه را با مقادیر دلخواه پر کردهایم و سپس از طریق حلقهی for یکی یکی مقدار هر خانهی آرایه را نمایش دادهایم:
شکل آرایه بعد از پر شدن:
در قسمت بعد با مثالهای بیشتری از آرایه آشنا خواهید شد.
فرشید
2 December 2012
سلام و ممنون از آموزشهای مفید ، در صورت امکان من برنامه ای را میخوام که عددی مثل n را دریافت کنه و n لول از مثلث خیام (پاسکال )را نشان دهد؟
داوود
2 December 2012
با سلام؛
بازهم مثل همیشه ممنون از آموزشهای خوبتون؛ این جلسه خیلی پربار و جذاب بود.
متشکرم
mmr
4 December 2012
سلام
و سپاس
1)برنامه شكل زير چگونه نوشته مي شود
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
2) *
* * *
* * * * *
* * *
*
مسعود درویشیان
4 December 2012
به قسمتهای چهاردهم و پانزدهم مراجعه کنید.
محمد فر
4 April 2013
سلام.یه سئوال داشتم.اگر بجای عدد صحیح از یک مقدار اعشاری یا کاراکتر برای عملگرها استفاده کنیم چه می شود؟
در مورد بولی چطور؟
مسعود درویشیان
4 April 2013
متوجه سوالتون نشدم!
محمد فر
4 April 2013
عملوندهامون بجای اعداد صحیح،کاراکتر باشند یا اعشاری؟
اگر مقادیر بولی باشند چی میشه؟
مسعود درویشیان
4 April 2013
نه مشکلی نداره ولی واسه بولین نمیشه
رضا
11 December 2013
سلام جناب درویشیان
با تشکر فراوان می خواستم اگه مقدور باشه در مورد اینکه
عملگر Implication دقیقا چی هست و چه جور جاهایی می تونه کاربرد داشته باشه قدری بیشتر توضیح بدید .
البته سوالهای دیگری هم در این قسمت دارم که اگه خودم نتونستم به جواب برسم مجددا به شما زحمت میدم.
بازم از لطفتون ممنونم و دوست دارم به نوبه ی خودم بگم واقعا مطالبتون به من داره کمک میکنه.
رشته ی تحصیلی من (البته چند ساله که دانشگاه تموم شده) هیچ ربطی به علومی مثل برنامه نویسی نداره.
ولی من همیشه اشتیاق زیادی برای یادگیریش داشتم.
و الان که فرصتی پیش اومده که به این مسئله بپردازم این شانس خوب نصیبم شده که از مطالب شما استفاده کنم که واقعا برام مفیده.
اینارو گفتم که بدونید زحمتی که می کشید به افرادی از شاخه های مختلف با مشکلات زمانی و روزمره گیهای مختلف کمک میکنه. و هستند در میان مخاطبها کسانی که دورادور قدر محبت شما رو می دونند.
موفق و سرافراز باشید
مسعود درویشیان
14 December 2013
سلام ممنون از لطفتون
همونطور که میدونید عملگر Implication فقط زمانی جوابش false میشه که عملوند اول true و عملوند دوم false باشه و تمام حالتهای دیگه جوابشون true هست. از همین خاصیتاش میتونید توی موقعیتهای خیلی خاص استفاده کنید که فکر نمیکنم فعلاً بهش نیازی پیدا کنید.
Arash
27 May 2014
سلام.اول هر مثالی که میزنی بنویس که این مثال چیکار میکنه یا چه خروجی به ما میده
محمد
24 August 2014
چرا برای ساخت آرایه دوبار تایپ براش تعریف شده و چرا تو تایپ اول یه اکولاد داریم؟؟؟؟
Kemal
30 October 2018
سلام در بازا یکی برنامه ساخته که همه قسمت های شمارو گذاشته اسم برنامش زنگ سی شارپه و سی قسمتش پولیه من دلم برای مردم ایران میسوزه که میرن سی قسمتو میخرن با اینکه نوشته ی اصلیش اینجاس و میرن از اونی که بهب نام خودش زده تشکر میکنند لطفا یک کاری کنید من که اعصابم خورد میه میبینم کلاه بردارا این کارارو میکنن دمتون گرم