| فناورياطلاعات ، برنامهنويسي |
برنامه نويسي ، شبكه ، سيستم عامل ، پايگاه داده ، سيستم اطلاعات جغرافيايي ، مديريت و كنترل پروژه
|
Information
![]()
سلام دوست عزيز . اين وبلاگ در مورد فناوري اطلاعات و علوم مرتبط با اون هست و داراي آموزش كامل و گام به گام برنامه نويسي به زبان ++C .
************************ پيشنهاد ميكنم از لينكهاي بخش مقالات فناوري اطلاعات ديدن كنيد . ************************ به اميد اينكه مطالب مفيد واقع بشه . با ارائه نظرات سازنده ي خودتون من رو در هرچه پربارتر كردن اين وب ياري كنيد . متشكرم مقالات فناوري اطلاعات
سيستم اطلاعات جغرافيايي
گزارش كار آزمايشگاه فيزيك2 خلاصهي كتاب سيستمهاي عامل تأليف ويليام استالينگز بانك اطلاعات چيست ؟ علل كاهش سرعت كامپيوتر فركانس بالاتر يا هسته بيشتر؟! مديريت و كنترل پروژههاي IT راه اندازي شبكه ي بي سيم تمام پیوندها پیوندها
ترفندستان (حسين)
كليك كن سرگرم ميشي يه غريب آموزش امنيت و برنامهنويسي(مهدي زارعي) وبلاگ علمي تخصصي فناوري اطلاعات اديب آموزش حرفهاي هك ترفند و آموزش (smn) ۩۞۩ تبدیل صدای مرد به زن ۩۞۩ ترفندهای کامپیوتر و موبایل و آموزش آفیس(بهزاد) آموزش حرفه اي ويروس نويسي (رضا) گل سرخ كلبه درويشي (محمد) انجمن تخصصي ويژوال بيسيك 6 (سيد كمال رضايي) : :سایت تخصصی موبایل:: (نويد) سايت تخصصي برنامه نويسي (مهدي) ترفندستان (محمد) مرکز دانلود مقاله و کتاب و فونت و سوال فؤاد (قلبها) سهيلستان سايت بزرگ موبايل و كامپيوتر حسين كوهساري عشقاي بچگي (شهر دانلود...جاوا..فيلم..عکس) خدمات انفورماتيك و اطلاع رساني ماموت: وبلاگ مقالات مهندسي مكانيك و خودرو آموزش جامع كامپيوتر وبلاگ تخصصي كامپيوتر (محمد) مهندسان عمران آموزش گام به گام دلفي برنامه نويسي ( عليرضا ) پسرهاي با معرفت بهترین وبلاگ دانلود نرم افزار اورميا هك جستجوگر
طراح قالب
|
برنامهي مثال آزمون بخشپذيري ناقص به نظر ميآيد زيرا اگر n بر d قابل تقسيم باشد ، برنامه هيچ عكسالعملي نشان نميدهد . اين نقص به كمك دستور if .. else رفع ميشود . ****************************************************** دستور if .. else دستور if .. else موجب ميشود بسته به اينكه شرط درست باشد يا خير ، يكي از دو دستورالعمل فرعي اجرا گردد . نحو اين دستور به شكل زير است : if ( condition ) statement1 ; condition همان شرط مسأله است كه يك عبارت صحيح ميباشد و statement1 و statement2 فرمانهاي قابل اجرا هستند . اگر مقدار شرط غير صفر باشد ، statement1 اجرا خواهد شد وگرنه statement2 اجرا ميشود . ******************************************************** مثال : يك آزمون ديگر قابليت تقسيم اين برنامه مانند برنامهي مثال آزمون بخشپذيري است بجز اينكه دستور if با دستور if .. else جايگزين شده است : int main() حالا وقتي در اين برنامه اعداد 56 و 7 را وارد كنيم ، برنامه پاسخ ميدهد كه 56 بر 7 قابل تقسيم است : Enter two positive integers : 56 7 چون حاصل 7%56 برابر با صفر است ، پس اين عبارت بعنوان نادرست تفسير ميگردد . در نتيجه دستور بعد از if ناديده گرفته شده و دستور بعد از else اجرا ميشود . توجه كنيد كه if .. else به تنهايي يك دستور است ، گرچه به دو سميكولن نياز دارد . همهي برنامههايي كه تاكنون بيان شد ، به شكل ترتيبي اجرا ميشوند ، يعني دستورات برنامه به ترتيب از بالا به پايين و هر كدام دقيقاٌ يك بار اجرا ميشوند . در ادامه نشان داده ميشود كه چگونه از دستورالعملهاي انتخاب (Selection) جهت انعطافپذيري بيشتر برنامه استفاده كنيم . همچنين انواع صحيح كه در ++C وجود دارند را بيشتر بررسي ميكنيم . **************************************************** دستور if دستور if موجب ميشود برنامه به شكل شرطي اجرا شود . نحو آن به شكل زير است : if (condition) statement ; condition كه شرط ناميده ميشود ، يك عبارت صحيح است (عبارتي كه با يك مقدار صحيح برآورد ميشود) و statement ميتواند هر فرمان قابل اجرا باشد . statement وقتي اجرا خواهد شد كه condition مقدار غير صفر داشته باشد . دقت كنيد كه شرط بايد درون پرانتز قرار داده شود . **************************************************** مثال : آزمون بخشپذيري اين برنامه بررسي ميكند كه يك عدد صحيح مثبت ورودي بر عدد ورودي ديگر قابل تقسيم نباشد : int main() در اولين اجرا ، اعداد 66 و 7 را وارد ميكنيم : enter two positive integers : 66 7 مقدار 7%66 برابر با 3 برآورد ميشود . چون اين مقدار ، يك عدد صحيح غير صفر است ، پس شرط به عنوان درست تفسير ميشود و در نتيجه دستور cout اجرا شده و پيغام عدم قابليت تقسيم چاپ ميشود . برنامهي بالا را دوباره اجرا ميكنيم و اين بار اعداد 56 و 7 را وارد ميكنيم : enter two positive integers : 56 7 مقدار 7%56 برابر با صفر برآورد ميشود كه اين به معني نادرست تفسير ميگردد ، پس دستور cout ناديده گرفته شده و هيچ پيغامي روي صفحه چاپ نميشود . در ++C هر وقت يك عبارت صحيح به عنوان يك شرط استفاده شود ، مقدار 0 به معني نادرست و همهي مقادير ديگر به معني درست است . حوزهي متغيرها متغيرها بخش مهمي از هر برنامه هستند . استفاده از متغيرهايي با نوع نامناسب سبب هدر رفتن حافظه و كاهش سرعت و افزايش خطاهاي زمان اجرا ميشود . انتخاب نامهاي نامفهوم يا ناقص سبب كاهش خوانايي برنامه و افزايش خطاهاي برنامهنويسي ميشود . استفاده از متغيرها در حوزهي نامناسب هم سبب بروز خطاهايي ميشود . "حوزهي متغير (scope) محدودهاي است كه يك متغير خاص ، اجازه دارد در آن محدوده به كار رود يا فراخواني شود . اصطلاح "بلوك" (block) در ++C واژهي مناسبي است كه ميتوان به وسيلهي آن حوزهي متغير را مشخص نمود . يك بلوك برنامه ، قسمتي از برنامه است كه درون يك جفت علامت كروشه { } محدود شده است . در برنامههايي كه تاكنون ديديم از بلوك استفاده كردهايم . هميشه بعد از عبارت ()int main يك كروشهي باز } گذاشتهايم و در پايان برنامه ، يك كروشهي بسته { قرار داديم . پس تمام برنامههايي كه تا كنون ذكر شد ، يك بلوك داشته . به طور كلي ميتوان گفت كه حوزهي يك متغير از محل اعلان آن شروع ميشود و تا پايان همان بلوك ادامه مييابد . خارج از آن بلوك نميتوان به متغير دسترسي داشت . همچنين قبل از اينكه متغير اعلان شود ، نميتوان آن را استفاده نمود . مثال زير را بررسي كنيد . مثال : حوزهي متغيرها برنامهي زير خطادار است : int main() برنامهي بالا دو بلوك تودرتو دارد . اولين بلوك بعد از عبارت ()int main شروع ميشود و در آخر برنامه بسته ميشود . بلوك داخلي نيز از خط پنجم آغاز ميشود و در خط دهم پايان مييابد . نحوهي تو رفتگي خطوط برنامه به درك و تشخيص شروع و پايان بلوكها كمك ميكند . خط پنجم تا دهم تورفتگي بيشتري دارد ، يعني اين خطوط تشكيل يك بلوك ميدهند . همچنين خط دهم به بعد تورفتگي به اندازهي خط سوم و چهارم دارد ، يعني مجموعهي اين خطوط هم در يك حوزهي مشترك قرار دارند . اولين خطا در خط سوم رخ داده . متغير x در خط چهارم اعلان شده است . پس حوزهي x از خط چهارم به بعد شروع ميشود ، در حالي كه در خط سوم متغير x فراخواني شده و اين خارج از محدودهي x است . دومين خطا در خط ششم اتفاق افتاده است . متغير y در خط هفتم اعلان شده . پس حوزهي y از خط هفتم به بعد است ، در حالي كه در خط ششم y فراخواني شده و اين خارج از محدودهي y است . سومين خطا كه در خط دوازدهم روي داده نيز مربوط به y است . گرچه y در خطوط قبلي تعريف شده اما اين تعريف در يك بلوك داخلي بوده است . اين بلوك داخلي ، در خط دهم به پايان رسيده است . پس تمام تعاريفي كه در اين بلوك وجود داشته نيز فقط تا خط دهم اعتبار دارد . يعني حوزهي y فقط از خط هفتم تا خط دهم است . لذا نميتوان در خط دوازدهم كه خارج از محدودهي y است ، آن را به كار برد . مثال بالا مطلب ظريفي را بيان ميكند : ميتوانيم در يك برنامه ، چند متغير متفاوت با يك نام داشته باشيم به شرطي كه در حوزههاي مشترك نباشند . مثال زير اين موضوع را به خوبي نشان ميدهد : مثال : متغيرهاي تودرتو int x = 11 ; // this x is global خروجي برنامه : In block inside main() : x = 33 در برنامهي بالا سه شيء متفاوت با نام x وجود دارد . اولين x كه مقدار 11 دارد يك متغير سراسري است زيرا داخل هيچ بلوكي قرار ندارد . پس حوزهي آن سراسر برنامه (حتي خارج از بلوك ()main ) است . دومين x درون بلوك ()main با مقدار 22 تعريف شده است . پس حوزهي آن تا پايان بلوك ()main است . اين x حوزهي x قبلي را كور ميكند . يعني درون بلوك ()main فقط x دوم ديده ميشود و x اول مخفي ميشود . پس اگر درون اين بلوك به x ارجاع كنيم ، فقط x دوم را خواهيم ديد . سومين x در يك بلوك داخلي تعريف شده است . حوزهي اين x فقط تا پايان همان بلوك است . اين x حوزهي هر دو x قبلي را كور ميكند . پس اگر درون اين بلوك x را فراخواني كنيم ، فقط x سوم را خواهيم ديد . وقتي از اين بلوك خارج شويم ، x فبلي آزاد ميشود و دوباره ميتوان به مقدار آن دسترسي داشت . اگر از بلوك ()main نيز خارج شويم ، x اول آزاد خواهد شد . برنامه را از اول دنبال كنيد و خروجي را بررسي كنيد تا متوجه شويد كه كدام x معتبر بوده است . در خط دهم از عملگر :: استفاده شده ، به آن عملگر جداسازي حوزه ميگويند . در مورد اين عملگر در آينده توضيح خواهم داد . در اينجا فقط ميگوييم با عملگر جداسازي حوزه ميتوان به يك شيء كه خارج از حوزهي فعلي است دسترسي پيدا كنيم . پس x:: يعني متغير x كه در حوزهي بيروني است . ميبينيد كه تعريف چند متغير در يك برنامه با نام يكسان به شيوهي بالا ، ممكن و مجاز است . اما سعي كنيد از اين كار اجتناب كنيد زيرا برخي از كامپايلرها اجازهي اين كار را نميدهند . اگر هم اينطور نباشد ، هميشه مجبوريد به خاطر بسپاريد كه الان داخل كدام حوزه هستيد و كدام متغير مورد نظر شماست . اين طوري راحتتريد ؟ اختيار با شماست ! حوزهي متغيرها متغيرها بخش مهمي از هر برنامه هستند . استفاده از متغيرهايي با نوع نامناسب سبب هدر رفتن حافظه و كاهش سرعت و افزايش خطاهاي زمان اجرا ميشود . انتخاب نامهاي نامفهوم يا ناقص سبب كاهش خوانايي برنامه و افزايش خطاهاي برنامهنويسي ميشود . استفاده از متغيرها در حوزهي نامناسب هم سبب بروز خطاهايي ميشود . "حوزهي متغير (scope) محدودهاي است كه يك متغير خاص ، اجازه دارد در آن محدوده به كار رود يا فراخواني شود . اصطلاح "بلوك" (block) در ++C واژهي مناسبي است كه ميتوان به وسيلهي آن حوزهي متغير را مشخص نمود . يك بلوك برنامه ، قسمتي از برنامه است كه درون يك جفت علامت كروشه { } محدود شده است . در برنامههايي كه تاكنون ديديم از بلوك استفاده كردهايم . هميشه بعد از عبارت ()int main يك كروشهي باز } گذاشتهايم و در پايان برنامه ، يك كروشهي بسته { قرار داديم . پس تمام برنامههايي كه تا كنون ذكر شد ، يك بلوك داشته . به طور كلي ميتوان گفت كه حوزهي يك متغير از محل اعلان آن شروع ميشود و تا پايان همان بلوك ادامه مييابد . خارج از آن بلوك نميتوان به متغير دسترسي داشت . همچنين قبل از اينكه متغير اعلان شود ، نميتوان آن را استفاده نمود . مثال زير را بررسي كنيد . مثال : حوزهي متغيرها برنامهي زير خطادار است : int main() برنامهي بالا دو بلوك تودرتو دارد . اولين بلوك بعد از عبارت ()int main شروع ميشود و در آخر برنامه بسته ميشود . بلوك داخلي نيز از خط پنجم آغاز ميشود و در خط دهم پايان مييابد . نحوهي تو رفتگي خطوط برنامه به درك و تشخيص شروع و پايان بلوكها كمك ميكند . خط پنجم تا دهم تورفتگي بيشتري دارد ، يعني اين خطوط تشكيل يك بلوك ميدهند . همچنين خط دهم به بعد تورفتگي به اندازهي خط سوم و چهارم دارد ، يعني مجموعهي اين خطوط هم در يك حوزهي مشترك قرار دارند . اولين خطا در خط سوم رخ داده . متغير x در خط چهارم اعلان شده است . پس حوزهي x از خط چهارم به بعد شروع ميشود ، در حالي كه در خط سوم متغير x فراخواني شده و اين خارج از محدودهي x است . دومين خطا در خط ششم اتفاق افتاده است . متغير y در خط هفتم اعلان شده . پس حوزهي y از خط هفتم به بعد است ، در حالي كه در خط ششم y فراخواني شده و اين خارج از محدودهي y است . سومين خطا كه در خط دوازدهم روي داده نيز مربوط به y است . گرچه y در خطوط قبلي تعريف شده اما اين تعريف در يك بلوك داخلي بوده است . اين بلوك داخلي ، در خط دهم به پايان رسيده است . پس تمام تعاريفي كه در اين بلوك وجود داشته نيز فقط تا خط دهم اعتبار دارد . يعني حوزهي y فقط از خط هفتم تا خط دهم است . لذا نميتوان در خط دوازدهم كه خارج از محدودهي y است ، آن را به كار برد . مثال بالا مطلب ظريفي را بيان ميكند : ميتوانيم در يك برنامه ، چند متغير متفاوت با يك نام داشته باشيم به شرطي كه در حوزههاي مشترك نباشند . مثال زير اين موضوع را به خوبي نشان ميدهد : مثال : متغيرهاي تودرتو int x = 11 ; // this x is global خروجي برنامه : In block inside main() : x = 33 در برنامهي بالا سه شيء متفاوت با نام x وجود دارد . اولين x كه مقدار 11 دارد يك متغير سراسري است زيرا داخل هيچ بلوكي قرار ندارد . پس حوزهي آن سراسر برنامه (حتي خارج از بلوك ()main ) است . دومين x درون بلوك ()main با مقدار 22 تعريف شده است . پس حوزهي آن تا پايان بلوك ()main است . اين x حوزهي x قبلي را كور ميكند . يعني درون بلوك ()main فقط x دوم ديده ميشود و x اول مخفي ميشود . پس اگر درون اين بلوك به x ارجاع كنيم ، فقط x دوم را خواهيم ديد . سومين x در يك بلوك داخلي تعريف شده است . حوزهي اين x فقط تا پايان همان بلوك است . اين x حوزهي هر دو x قبلي را كور ميكند . پس اگر درون اين بلوك x را فراخواني كنيم ، فقط x سوم را خواهيم ديد . وقتي از اين بلوك خارج شويم ، x فبلي آزاد ميشود و دوباره ميتوان به مقدار آن دسترسي داشت . اگر از بلوك ()main نيز خارج شويم ، x اول آزاد خواهد شد . برنامه را از اول دنبال كنيد و خروجي را بررسي كنيد تا متوجه شويد كه كدام x معتبر بوده است . در خط دهم از عملگر :: استفاده شده ، به آن عملگر جداسازي حوزه ميگويند . در مورد اين عملگر در آينده توضيح خواهم داد . در اينجا فقط ميگوييم با عملگر جداسازي حوزه ميتوان به يك شيء كه خارج از حوزهي فعلي است دسترسي پيدا كنيم . پس x:: يعني متغير x كه در حوزهي بيروني است . ميبينيد كه تعريف چند متغير در يك برنامه با نام يكسان به شيوهي بالا ، ممكن و مجاز است . اما سعي كنيد از اين كار اجتناب كنيد زيرا برخي از كامپايلرها اجازهي اين كار را نميدهند . اگر هم اينطور نباشد ، هميشه مجبوريد به خاطر بسپاريد كه الان داخل كدام حوزه هستيد و كدام متغير مورد نظر شماست . اين طوري راحتتريد ؟ اختيار با شماست ! انواع ديگري از خطاهاي زمان اجرا دوباره به برنامهي محاسبهي ريشهها برگرديم . به اجراي زير نگاه كنيد : enter the coefficients of a quadratic equation : در اين اجرا سعي شده تا معادلهي 1x2+2x+3=0 حل شود . اين معادله جواب حقيقي ندارد زيرا دلتا منفي است . وقتي برنامه اجرا شود ، تابع ()sqrt تلاش ميكند جذر يك عدد منفي را بگيرد ولي موفق نميشود . در اين حالت پاسخ IND داده ميشود (IND مخفف عبارت Is Not Digit است ، يعني پاسخ عددي نيست) . پس هر محاسبهي ديگري كه از اين مقدار استفاده كند ، همين پاسخ IND را خواهد داشت . به همين دليل در همهي خروجيها پاسخ IND آمده است . سرانجام به اجراي زير دقت كنيد : enter the coefficients of a quadratic equation : در اين اجرا كوشش شده تا معادلهي 0x2+2x+5=0 حل شود . اين معادله داراي جواب x=2.5 است اما برنامه نميتواند اين جواب را بيابد و با پاسخهاي عجيبي روبرو ميشويم . علت اين است كه a صفر است و در حين اجراي برنامه ، سعي ميشود عددي بر صفر تقسيم شود . در چنين حالتي دوباره پاسخ IND بدست ميآيد . سه نشانهي IND و INF و INF- ثابتهاي عددي هستند . يعني ميتوانيد اين مقادير را در محاسبات به كار ببريد اما نتيجه معمولاٌ بيفايده است . مثلاٌ ميتوانيد عددي را با INF جمع كنيد يا از آن تفريق نماييد اما نتيجه بازهم INF خواهد بود . مثال : خطاي گرد كردن پنهان برنامهي زير با استفاده از رابطهي معادلات درجهي دوم ، ريشههاي اين معادلات را پيدا ميكند : # include < cmath > // defines the sqrt () function اين برنامه ضرايب a و b و c را براي معادلهي ax2+bx+c=0 ميگيرد و سپس سعي ميكند ريشههاي x1 و x2 را پيدا كند . براي اين كار سه متغير a و b و c از نوع float تعريف شدهاند تا بتوانند مقادير اعشاري را نيز از ورودي بگيرند . خط هشتم تا سيزدهم برنامهي بالا مقادير a و b و c را دريافت ميكنند (دقت كنيد كه از كاراكتر خاص 't\' در پيغامهاي خروجي استفاده شده تا قبل از هر ورودي ، هفت جاي خالي قرار بگيرد . ولي خود حرف t چاپ نميشود) . پس از دريافت ضرايب ، يك بار ديگر شكل كلي معادلهاي كه مورد نظر كاربر بوده است چاپ ميشود . در خط يازدهم ، رابطهي دلتا يعني b2-4ac تشكيل شده است . اين مقدار درون متغير ديگري كه d نام دارد و از نوع float است ، قرار گرفته . در خط بعدي مقدار جذر دلتا با استفاده از تابع ()sqrt محاسبه شده است . تابع ()sqrt جذر عددي كه درون پرانتزهايش قرار ميگيرد را به دست ميدهد . اين تابع در سرفايل <cmath> تعريف شده . پس راهنماي پيش پردازندهي : # include < cmath > به ابتداي برنامه افزوده شده است . مقدار جذر دلتا درون متغير ديگري بنام sqrtd نگهداري شده تا با استفاده از آن در خطوط بعدي مقدار x1 و x2 بدست آيد . در چهار خط آخر برنامه ، مقادير x1 و x2 كه بدست آمده است دوباره در معادله جايگذاري ميشود تا بررسي شود كه آيا جواب معادله صفر ميشود يا خير . بدين وسيله صحت پاسخهاي x1 و x2 تحقيق ميشود . خروجي زير نشان ميدهد كه برنامه معادلهي 2x2+1x-3=0 را حل كرده است : enter the coefficients of a quadratic equation : ميبينيد كه برنامه ، پاسخهاي x1=1 و x2=-1.5 را پيدا كرده است و آزمون پاسخ نيز جواب صفر داده است . خروجي ديگري از برنامه نشان ميدهد كه برنامه تلاش كرده معادلهي 2x2+8.001x+8.002=0 را حل كند ولي شكست ميخورد : enter the coefficients of a quadratic equation : مقدار x1 كه در اجراي بالا آمده ، در آزمون شركت كرده و پاسخ بسيار نزديك به صفر داده است . اما مقدار x2 در آزمون شكست خورده زيرا جواب معادله به ازاي آن صفر نيست . چه چيزي باعث شده معادله جواب غلط بدهد ؟ جواب باز هم در خطاي گرد كردن است . x2 يك پاسخ گرد شده است نه يك پاسخ دقيق . اين پاسخ گرد شده دوباره در يك محاسبهي ديگر شركت مي كند . پاسخ اين محاسبه هم گرد شده است . پس انحراف از جواب افزايش مييابد و نتيجهاي دور از انتظار به بار ميآورد . خطاي گرد كردن خطاي گرد كردن (Round-off) نوع ديگري از خطاست كه اغلب وقتي رايانهها روي اعداد حقيقي محاسبه ميكنند ، رخ ميدهد . براي مثال عدد 3/1 ممكن است بصورت 0.333333 ذخيره شود كه دقيقاٌ معادل 3/1 نيست . به اين اختلاف ، خطاي گرد كردن ميگويند . اين خطا از آنجا ناشي ميشود كه اعدادي مثل 3/1 مقدار دقيق ندارند و رايانه نميتواند اين مقدار را پيدا كند ، پس با اين اختلاف اندك ، نزديكترين عدد قابل محاسبه را بجاي چنين اعدادي محاسبه ميكند . در بعضي حالات ، اين اختلاف اندك ميتواند مشكلات حادي را ايجاد كند . مثال : خطاي گرد كردن اين برنامه ، محاسبات سادهاي را انجام ميدهد تا خطاي گرد كردن را نشان ميدهد : int main() خروجي برنامه : x = 333.333 منطق برنامه به اين شكل است كه ابتدا مقدار x برابر با 3/1000 ميباشد . سپس قسمت صحيح x يعني 333 از آن كسر ميشود و حاصل كه برابر با 3/1 است در y قرار ميگيرد . حالا y در 3 ضرب ميشود تا حاصل برابر با 1 شود . اين مقدار از 1 كم ميشود و حاصل در z قرار ميگيرد . انتظار اين است كه z صفر باشد اما پاسخ برنامه به ما ميگويد كه z ضفر نيست ! اشكال برنامهي بالا در كجاست ؟ منطق برنامه كه درست است ، پس جايي در محاسبات بايد غلط باشد . مشكل در مقدار y است . رايانه مقدار 3/1 را برابر با 0.333333 محاسبه نموده است ، حال آنكه ميدانيم اين مقدار دقيقاٌ برابر با 3/1 نيست . اين خطا از آنجا ناشي ميشود كه رايانه نميتواند مقدار دقيق 3/1 را پيدا كند چون اين مقدار به تعداد نامتناهي اعشار 3 دارد ، پس رايانه اين مقدار را گرد ميكند و مقدار نسبتاٌ درست 0.333333 را ميدهد . اين مقدار در محاسبات بعدي استفاده ميشود اما چون دقيق نيست ، پاسخهاي بعدي نيز به تناسب بر ميزان خطا ميافزايد . نتيجه اين است كه مقدار z صفر نميشود ، هرچند كه بسيار نزديك به صفر باشد . مثال بالا نكتهي مهمي را در استفاده از متغيرهاي مميز شناور نشان ميدهد : "هيچگاه از متغير مميز شناور براي مقايسهي برابري استفاده نكنيد " زيرا در متغيرهاي مميز شناور ، خطاي گرد كردن سبب ميشود كه پاسخ با آنچه مورد نظر شماست متفاوت باشد . در حالت بالا گرچه مقدار z بسيار نزديك صفر است ، اما رايانه همين مقدار كوچك را صفر نميداند . پس مقايسهي برابري شكست ميخورد .
سرريز عددي
نوع صحيح long يا نوع مميز شناور double محدودهي وسيعي از اعداد را ميتوانند نگهداري كنند . به بيان سادهتر ، متغيري كه از نوع long يا double باشد ، گنجايش زيادي دارد . اما حافظهي رايانهها متناهي است . يعني هر قدر هم كه يك متغير گنجايش داشته باشد ، بالاخره مقداري هست كه از گنجايش آن متغير بيشتر باشد . اگر سعي كنيم در يك متغير ، مقداري قرار دهيم كه از گنجايش آن متغير فراتر باشد ، متغير سرريز (overflow) ميشود . مثل يك ليوان كه اگر بيش از گنجايش آن در ليوان آب بريزيم ، سرريز ميشود . در چنين حالتي ميگوييم كه خطاي سرريزي رخ داده است . مثال : سرريزي عدد صحيح اين برنامه بطور مكرر n را در 1000 ضرب ميكند تا سرانجام سرريز شود : int main() خروجي برنامه : n = 1000 اين مثال نشان ميدهد رايانهاي كه اين برنامه را اجرا كرده است ، نميتواند بيشتر از 1,000,000,000 را با 1000 بطور صحيح ضرب كند . ************************************************** مثال : سرريزي عدد مميز شناور اين برنامه شبيه چيزي است كه در مثال قبل ذكر شد . بطور مكرر x را به توان ميرساند تا اينكه سرريز شود : int main() خروجي برنامه بشكل زير است : x = 1000 مثال بالا نشان ميدهد كه اين رايانه نميتواند x را با شروع از 1000 بيش از سه بار مجذور كند . آخرين خروجي يعني INF نمادي است كه به معناي بينهايت ميباشد (اين نماد مخفف INFINITY است). به تفاوت سرريزي عدد صحيح و سرريزي مميز شناور دقت كنيد . وقتي يك عدد صحيح سرريز شود ، عدد سرريز شده به يك مقدار منفي گرايش مييابد اما وقتي كه يك عدد مميز شناور سرريز شود ، نماد INF به معناي بينهايت را به دست ميدهد ، نشانه اي مختصر و مفيد . برخي از خطاهاي برنامهنويسي اكنون كه انواع متغير در ++C را شناختيم ، ميتوانيم از اين انواع در برنامههاي مفيدتر و جديتر استفاده كنيم . اما بايد دقت نمود كه اگر از متغيرها بشكل نادرست يا كنترل نشده استفاده كنيم ، برنامه دچار خطا ميشود . البته عوامل ديگري نيز هست كه باعث ميشود اجراي برنامه مختل گردد ، مثل استفاده از متغيري كه تعريف نشده يا جا انداختن سميكولن انتهاي دستورها . اين قبيل خطاها كه اغلب خطاهاي نحوي هستند و توسط كامپايلر كشف ميشوند ، "خطاهاي زمان كامپايل" ناميده ميشوند و براحتي ميتوان آنها را رفع نمود . اما خطاهاي ديگري نيز وجود دارند كه كشف آنها به راحتي ممكن نيست و كامپايلر نيز چيزي راجع به آن نميداند . به اين خطاها ، خطاي زمان اجرا ميگويند . برخي از خطاهاي زمان اجرا سبب ميشوند كه برنامه بطور كامل متوقف شود و از كار بيفتد. در چنين حالتي متوجه ميشويم كه خطايي رخ داده است و در صدد كشف و رفع آن برميآييم . برخي ديگر از خطاهاي زمان اجرا ، برنامه را از كار نمياندازند بلكه برنامه همچنان كار ميكند اما پاسخهاي عجيب و نادرست ميدهد . اين نوع خطا در حالات خاصي رخ ميدهد و گاهي سبب گيج شدن برنامهنويس ميگردد .در بخشهاي بعدي برخي از خطاهاي رايج زمان اجرا را نشان ميدهيم تا در برنامههايتان از آنها پرهيز كنيد . دست كم اگر با پاسخهاي غير منتظره و غلط مواجه شديد ، محل رخ دادن خطا را راحتتر پيدا كنيد . |
Technology
آرشیو
هفته اوّل آبان 1388
هفته سوم شهریور 1388 هفته سوم مرداد 1388 هفته چهارم تیر 1388 هفته دوم فروردین 1388 هفته اوّل بهمن 1387 هفته سوم مهر 1387 هفته چهارم شهریور 1387 هفته سوم شهریور 1387 هفته دوم شهریور 1387 هفته اوّل شهریور 1387 هفته چهارم مرداد 1387 هفته سوم مرداد 1387 هفته دوم مرداد 1387 هفته اوّل مرداد 1387 هفته چهارم تیر 1387 هفته سوم تیر 1387 هفته دوم تیر 1387 هفته دوم اسفند 1386 هفته سوم بهمن 1386 هفته چهارم دی 1386 هفته دوم دی 1386 آمار وبلاگ
» تعداد بازدیدها:
» مرورگر: امکانات اضافي
|
© All Rights Reserved by mrz-it.Blogfa.com ©