|
سه اصل را فراموش نکن؛ احترام به خویشتن، احترام به دیگران و پذیرش مسوولیت کلیه اعمالی که انجام میدهی. |
علوم كامپيوتر
برنامه نويسي
درس دوم #C – عبارات، انواع و متغيرها در #C
| درس دوم #C – عبارات، انواع و متغيرها در #C |
|
|
| 06 فروردين 1385 ساعت 12:06 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
در اين درس به معرفي عبارات، انواع و متغيرها در زبان C# ميپردازيم. هدف از اين درس بررسي موارد زير است :
متغيرها، به بيان بسيار ساده، مكانهايي جهت ذخيره اطلاعات هستند. شما اطلاعاتي را در يك متغير قرار ميدهيد و از اين اطلاعات بوسيله متغير در عبارات C# استفاده مينماييد. كنترل نوع اطلاعات ذخيره شده در متغيرها بوسيله تعيين كردن نوع براي هر متغير صورت ميپذيرد. C# زباني بسيار وابسته به انواع است، بطوريكه تمامي عملياتي كه بر روي دادهها و متغيرها در اين زبان انجام ميگيرد با دانستن نوع آن متغير ميسر ميباشد. قوانيني نيز براي تعيين اينكه چه عملياتي بر روي چه متغيري انجام شود نيز وجود دارد.(بسته به نوع متغير) انوع ابتدايي زبان C# شامل : يك نوع منطقي(Boolean) و سه نوع عددي اعداد صحيح(integer)، اعداد اعشاري(Floating points) و اعداد دسيمال(Decimal) ميباشد.(به انواع Boolean از اينرو منطقي ميگوييم كه تنها داراي دو حالت منطقي صحيح(True) و يا غلط(False) ميباشند.)
مثال 1 – نشان دادن مقادير منطقي (Boolean) using System; class Booleans { public static void Main() { bool content = true; bool noContent = false; Console.WriteLine("It is {0} that C# Persian provides C# programming language content.", content); Console.WriteLine("The statement above is not {0}.", noContent); } } در اين مثال، مقادير منطقي متغيرهاي Boolean به عنوان قسمتي از جمله در خروجي نمايش داده ميشوند. متغيرهاي bool تنها ميتوانند يكي از دو مقدار true يا false را داشته باشند، يعني همانند برخي از زبانهاي برنامهسازي مشابه، مانند C و يا C++، مقدار عددي نميپذيرند، زيرا همانگونه كه ميدانيد در اين دو زبان هر مقدار عددي صحيح مثبت بغير از صفر به عنوان true و عدد صفر به عنوان false در نظر گرفته ميشود و در حقيقت نوع bool در اين دو زبان نوعي integer ميباشند. اما در زبان C# انواع bool يكي از دو مقدار true يا false را ميپذيرند. خروجي برنامه بالا به صورت زير است : It is True that C# Persian provides C# programming language content. The statement above is not False. جدول زير تمامي انواع عددي صحيح C#، اندازه آنها و رنج قابل قبول آنها را نشان ميدهد.
از اين انواع براي محاسبات عددي استفاده ميگردد. يك نوع ديگر را نيز ميتوان در اين جدول اضافه نمود و آن نوع char است. هر چند شايد از نظر بسياري از دوستاني كه با زبانهاي ديگر برنامهسازي كار كردهاند اين تقسيم بندي غلط به نظر آيد، اما بايد گفت كه در زبان C# نوع char نيز نوع خاصي از انواع عددي است كه رنجي بين صفر تا 65535 دارد و اندازه آن نيز 16 بيتي است، اما به جاي نمايش دادن مقادير عددي تنها ميتواند بيان كننده يك كاراكتر باشد. در آينده در اين مورد بيشتر توضيح خواهم داد. جدول زير تمامي انواع عددي اعشاري زبان C# را نمايش ميدهد.
انواعي از نوع floating point هنگامي استفاده ميشوند كه محاسبات عددي به دقتهاي اعشاري نياز داشته باشند. همچنين براي منظورهاي تجاري استفاده از نوع decimal بهترين گزينه است. اين نوع تنها در زبان C# وجود دارد و در زبانهاي مشابه به آن نظير Java چنين نوعي در نظر گرفته نشده است. در يك زبان برنامهسازي نتايج بوسيله ايجاد يك سري عبارت توليد ميگردند. عبارات از تركيب متغيرها و عملگرها در دستورالعملهاي يك زبان ايجاد ميگردند.(توجه نماييد كه عبارت معادل expression و دستورالعمل معادل statement ميباشد كه ايندو با يكديگر متفاوت ميباشند.) جدول زير عملگرهاي موجود در زبان C#، حق تقدم آنها و شركتپذيري آنها را نشان ميدهد.
شركتپذيري از چپ بدين معناست كه عمليات از چپ به راست محاسبه ميشوند. شركتپذيري از راست بدين معناست كه تمامي محاسبات از راست به چپ صورت ميگيرند. به عنوان مثال در يك عمل تساوي، ابتدا عبارات سمت راست تساوي محاسبه شده و سپس نتيجه به متغير سمت چپ تساوي تخصيص داده ميشود. مثال 2- عملگرهاي يكاني (Unary) using System; class Unary { public static void Main() { int unary = 0; int preIncrement; int preDecrement; int postIncrement; int postDecrement; int positive; int negative; sbyte bitNot; bool logNot; preIncrement = ++unary; Console.WriteLine("Pre-Increment: {0}", preIncrement); preDecrement = --unary; Console.WriteLine("Pre-Decrement: {0}", preDecrement); postDecrement = unary--; Console.WriteLine("Post-Decrement: {0}", postDecrement); postIncrement = unary++; Console.WriteLine("Post-Increment: {0}", postIncrement); Console.WriteLine("Final Value of Unary: {0}", unary); positive = -postIncrement; Console.WriteLine("Positive: {0}", positive); negative = +postIncrement; Console.WriteLine("Negative: {0}", negative); bitNot = 0; bitNot = (sbyte)(~bitNot); Console.WriteLine("Bitwise Not: {0}", bitNot); logNot = false; logNot = !logNot; Console.WriteLine("Logical Not: {0}", logNot); } } به هنگام محاسبه عبارات، دو عملگر x++ و x—(كه در اينجا كاراكتر x بيان كننده آن است كه عملگرهاي ++ و – در جلوي عملوند قرار ميگيرند post-increment و post-decrement) ابتدا مقدار فعلي عملوند (operand) خود را باز ميگرداند و سپس به عملوند خود يك واحد اضافه كرده يا از آن يك واحد ميكاهند. عملگر ++ يك واحد به عملوند خود اضافه ميكند و عملگر – يك واحد از عملوند خود ميكاهد. بدين ترتيب عبارت x++ معادل است با عبارت x=x+1 و يا x+=1 اما همانطور كه گفته شد بايد توجه داشته باشيد كه اين عملگرها(++ و --) ابتدا مقدار فعلي عملوند خود را برگشت ميدهند و سپس عمل خود را روي آنها انجام ميدهند. بدين معني كه در عبارت x=y++ در صورتيكه در ابتداي اجراي برنامه مقدار x=0 و y=1 باشد، در اولين اجراي برنامه مقدار x برابر با 1 يعني مقدار y ميشود و سپس به متغير y يك واحد افزوده ميشود، در صورتيكه اگر اين عبارت را بصورت x=++y بنويسيم در اولين اجراي برنامه، ابتدا به مقدار متغير y يك واحد افزوده ميشود و سپس اين مقدار به متغير x تخصيص داده ميشود كه در اين حالت مقدار متغير x برابر با 2 ميشود.(در مورد عملگر – نيز چنين است.) پس با اين توضيح ميتوان گفت كه دو عملگر ++x و –x ابتدا به عملوند خود يك واحد اضافه يا يك واحد از آن كم ميكنند و سپس مقدار آنها را باز ميگردانند. در مثال 2، مقدار متغير unary در قسمت اعلان برابر با 0 قرار گرفته است. هنگاميكه از عملگر ++x استفاده ميكنيم، به مقدار متغير unary يك واحد افزوده ميشود و مقدارش برابر با 1 ميگردد و سپس اين مقدار، يعني 1، به متغير preIncrement تخصيص داده ميشود. عملگر –x مقدار متغير unary را به 0 باز ميگرداند و سپس اين مقدار را به متغير preDecrement نسبت ميدهد. هنگاميكه از عملگر x-- استفاده ميشود، مقدار متغير unary، يا همان مقدار صفر، به متغير postDecrement تخصيص داده ميشود و سپس از مقدار متغير unary يك واحد كم شده و مقدار اين متغير به 1- تغيير ميكند. سپس عملگر x++ مقدار متغير unary، يعني همان 1-، را به متغير postIncrement تخصيص ميدهد و سپس يك واحد به مقدار متغير unary ميافزايد تا مقدار اين متغير برابر با 0 (صفر) شود. مقدار متغير bitNot در هنگام اعلان برابر با صفر است. با استفاده از عملگر نقيض بيتي (~) (يا عملگر مكملگيري) متغير bitNot بعنوان يك بايت در نظر گرفته ميشود و مقدار آن منفي يا نقيض ميشود. در عمليات بيتي نقيض بدين معناست كه تمامي يكها به صفر و تمامي صفرها به يك تبديل شوند. در اين حالت نمايش باينري عدد صفر يا همان 00000000 به نقيض آن يعني 11111111 تبديل ميگردد. در اين مثال به عبارت (sbyte)(~bitNot) توجه نماييد. هر عملي كه بر روي انواع short،unshort ، byte و sbyte انجام شود، مقداري از نوع int را باز ميگرداند. بمنظور اينكه بتوانيم نتيجه دلخواه را به متغير bitNot تخصيص دهيم بايد از فرمت (Type) operator استفاده نماييم كه در آن Type نوعي است ميخواهيم نتيجه ما به آن نوع تبديل شود و operator عملي است كه بر روي متغير صورت ميپذيرد. به بيان ديگر چون ميخواهيم مقدار متغير bitNot بصورت بيتي در نظر گرفته شود، پس بايد نتيجه عمل ما بصورت بيتي در آن ذخيره شود كه استفاده از نوع sbyte باعث ميشود تا نتيجه به فرم بيتي (يا بايتي) در متغير ما ذخيره شود. بايد توجه نماييد كه استفاده از فرمت (Type) يا در اصطلاح عمل Casting، در مواقعي كه ميخواهيم تغييري از يك نوع بزرگتر به نوع كوچكتر ايجاد نماييم، مورد استفاده قرار گيرد، چرا كه در اين حالات ممكن است با از دست دادن اطلاعات مواجه باشيم. در اين مثال چون ميخواهيم نوع بزرگتر int را به(32 بيتي) به نوع كوچكتر sbyte (8 بيتي) تبديل نماييم، بدين منظور بايد بطور صريح از عمل Casting استفاده نماييم تا اطلاعاتي در اين تبديل از بين نرود. در مورد تبديل انواع كوچكتر به انواع بزرگتر(مثلا تبديل sbyte به int) نيازي به استفاده از عمل Casting نيست چرا كه امكان از بين رفتن اطلاعات وجود ندارد. در ضمن بايد به يك نكته مهم توجه نماييد و آن تبديل انواع علامتدار(Signed) و بدون علامت(Unsigned) به يكديگر است. در اين حالت خطر بسيار مهمي دادههاي شما را تهديد مينمايد. بحث در مورد مسائل پيچيدهتر در مورد تبديل انواع علامتدار و و بدون علامت به يكديگر در اينجا نميگنجد و سعي ميكنم تا آنها را در مطالب بعدي و در جاي لازم مورد بحث و بررسي قرار دهم.(در صورتيكه برخي از مطالب اين قسمتها براي شما به خوبي قابل درك نيست، نگران نباشيد چراكه در آينده در مثالهايي كه خواهيد ديد تمامي اين مطالب را در عمل نيز حس كرده و با آنها آشنا خواهيد شد.) عملگر بعدي كه در اين برنامه مورد استفاده قرار گرفته است، عملگر نقيض منطقي يا همان "!" است كه امكان تغيير مقدار يك متغير Boolean را از true به false و بالعكس را فراهم ميآورد. در مثال بالا(مثال شماره 2) مقدار متغير logNot پس از استفاده از عملگر "!" از false به true تغيير كرده است. با توجه به توضيحات اخير خروجي زير از برنامه مثال 2 مورد انتظار است : Pre-Increment: 1 Pre-Decrement 0 Post-Decrement: 0 Post-Increment -1 Final Value of Unary: 0 Positive: 1 Negative: -1 Bitwise Not: -1 Logical Not: True مثال 3 – عملگرهاي دوتايي using System; class Binary { public static void Main() { int x, y, result; float floatResult; x = 7; y = 5; result = x+y; Console.WriteLine("x+y: {0}", result); result = x-y; Console.WriteLine("x-y: {0}", result); result = x*y; Console.WriteLine("x*y: {0}", result); result = x/y; Console.WriteLine("x/y: {0}", result); floatResult = (float)x/(float)y; Console.WriteLine("x/y: {0}", floatResult); result = x%y; Console.WriteLine("x%y: {0}", result); result += x; Console.WriteLine("result+=x: {0}", result); } } خروجي اين برنامه به فرم زير است : x+y: 12 x-y: 2 x*y: 35 x/y: 1 x/y: 1.4 x%y: 2 result+=x: 9 مثال 3 استفادههاي متفاوتي از عملگرهاي دوتايي را نشان ميدهد.(منظور از عملگر دوتايي، عملگري است كه داراي دو عملوند ميباشد مانند عملگر جمع "+"). بسياري از عملگرهاي مورد استفاده در اين مثال عملگرهاي رياضي هستند و نتيجه عمل آنها مشابه عملي است كه از آنها در رياضيات ديدهايد. از نمونه اين عملگرها ميتوان به عملگرهاي جمع "+"، تفريق "-"، ضرب "*" و تقسيم "/" اشاره نمود. متغير floatResult از نوع اعشاري يا float تعريف شده است. در اين مثال نيز صريحاً از عمل Casting جهت اسفاده از دو متغير x و y كه از نوع int هستند، براي انجام عملي كه نتيجهاش از نوع float است، استفاده كردهايم. در اين مثال از عملگر "%" نيز استفاده كردهايم. اين عملگر در عمليات تقسيم كاربرد دارد و باقيمانده تقسيم را برميگرداند. يعني دو عملوند خود را بر يكديگر تقسيم ميكند و باقيمانده اين تقسيم را برميگرداند. در اين مثال همچنين فرم جديدي از عمل انتساب را بصورت result+=x مشاهده مينماييد. استفاده از عملگرهاي انتسابي كه خود تركيبي از دو عملگر هستند، جهت سهولت در امر برنامهنويسي مورد استفاده قرار ميگيرند. عبارت فوق معادل result = result+x ميباشد. يعني مقدار قبلي متغير result با مقدار متغير x جمع ميشود و نتيجه در متغير result قرار ميگيرد. يكي ديگر از انواعي كه تا كنون با آن سر و كار داشتهايم نوع رشتهاي (string) است. يك رشته، از قرار گرفتن تعدادي كاراكتر در كنار يكديگر كه داخل يك زوج كوتيشن " " قرار گرفتهاند، ايجاد ميگردد. بعنوان مثال "Hi This is a string type". در اعلان متغيرها نيز در صورت تعريف متغيري از نوع رشتهاي، در صورت نياز به تخصيص مقدار به آن، حتماً كاراكترهايي كه ميخواهيم بعنوان يك رشته به متغيرمان نسبت دهيم را بايد داخل يك زوج كوتيشن " " قرار دهيم. به مثال زير توجه نماييد. string Name; … Name = "My name is Meysam"; همانطور كه در اين مثال مشاهده مينماييد، متغيري از نوع رشتهاي تحت نام Name تعريف شده است و سپس در جايي از برنامه كه نياز به تخصيص مقدار براي اين متغير وجود دارد، عبارت مورد نظر را داخل دو كوتيشن قرار داده و به متغير خود تخصيص دادهايم. رشتهها از پر كاربرد ترين انواع در زبانهاي برنامهسازي جهت ايجاد ارتباط با كاربر و دريافت اطلاعات از كاربر ميباشند.(همانطور كه در درس قبل اول نيز گفته شد، دستور Console.ReadLine() يك رشته را از ورودي دريافت مينمايد.) در مثالهايي كه در طي درسهاي اين سايت خواهيد ديد، نمونههاي بسياري از كاربرد انواع مختلف و نيز نوع رشتهاي را خواهيد ديد. يكي ديگر از انواع دادهاي در زبان C#، آرايهها (Arrays) ميباشند. يك آرايه را به عنوان مخزني براي نگهداري اطلاعات در نظر ميگيريم كه داراي ليستي از محلهايي است كه در آنها اطلاعات ذخيره شده است و از طريق اين ليست ميتوان به اطلاعات آنها دسترسي پيدا نمود. به هنگام اعلان آرايهها بايد نوع، اندازه و تعداد بعد آنها را نيز معين نمود.
مثال 4- آرايهها و عمليات بر روي آنها using System; class Array { public static void Main() { int[] myInts = { 5, 10, 15 }; bool[][] myBools = new bool[2][]; myBools[0] = new bool[2]; myBools[1] = new bool[1]; double[,] myDoubles = new double[2, 2]; string[] myStrings = new string[3]; Console.WriteLine("myInts[0]: {0}, myInts[1]: {1}, myInts[2]: {2}", myInts[0], myInts[1], myInts[2]); myBools[0][0] = true; myBools[0][1] = false; myBools[1][0] = true; Console.WriteLine("myBools[0][0]: {0}, myBools[1][0]: {1}", myBools[0][0], myBools[1][0]); myDoubles[0, 0] = 3.147; myDoubles[0, 1] = 7.157; myDoubles[1, 1] = 2.117; myDoubles[1, 0] = 56.00138917; Console.WriteLine("myDoubles[0, 0]: {0}, myDoubles[1, 0]: {1}", myDoubles[0, 0], myDoubles[1, 0]); myStrings[0] = "Joe"; myStrings[1] = "Matt"; myStrings[2] = "Robert"; Console.WriteLine("myStrings[0]: {0}, myStrings[1]: {1}, myStrings[2]: {2}", myStrings[0], myStrings[1], myStrings[2]); } } خروجي مثال 4 بصورت زير است : myInts[0]: 5, myInts[1]: 10, myInts[2]: 15 myBools[0][0]: True, myBools[1][0]: True myDoubles[0, 0]: 3.147, myDoubles[1, 0]: 56.00138917 myStrings[0]: Joe, myStrings[1]: Matt, myStrings[2]: Robert
در اين مثال انواع مختلفي از آرايهها اعلان شدهاند. در ابتدا يك آرايه تك بعدي، سپس آرايهاي دندانهدار و در نهايت نيز يك آرايه دو بعدي در اين مثال اعلان شدهاند. اولين اعلان در اين برنامه مربوط به اعلان آرايه تك بعدي myInts ميباشد كه از نوع int بوده و داراي 3 عضو ميباشد كه تعداد اين اعضا با اعلان چند مقدار در داخل { } معين شده است. همانطور كه از اين اعلان دريافت ميشود، آرايه تك بعدي بصورت زير تعريف ميشود : type[] arrayName; كه در آن type نوع آرايه و arrayName نام آرايه ايست كه تعريف مينمائيم. اما در ابتدا گفته شد كه به هنگام اعلان آرايهها اندازه آنها نيز بايد مشخص شود. براي تعيين اندازه آرايه، يعني تعدا عناصري كه آرايه در خود جاي ميدهد، ميتوان به چند روش عمل نمود. اولين و سادهترين روش كه در اين مثال نيز آورده شده است، تخصيص مقاديري به آرايه در داخل يك زوج { } است. بسته به نوع آرايه، تعداد عناصري كه داخل اين زوج { } قرار ميگيرند، تعداد عناصر آرايه ميباشند و مقادير عناصر آرايه نيز همان مقاديري است كه داخل { } قرار گرفته است. به عنوان مثال | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||