تبليغاتX
فناوري‌اطلاعات ، برنامه‌نويسي

برنامه نويسي ، شبكه ، سيستم عامل ، پايگاه داده ، سيستم اطلاعات جغرافيايي ، مديريت و كنترل پروژه

Information
سلام دوست عزيز . اين وبلاگ در مورد فناوري اطلاعات و علوم مرتبط با اون هست و داراي آموزش كامل و گام به گام برنامه نويسي به زبان ++C .
************************
پيشنهاد مي‌كنم از لينك‌هاي بخش مقالات فناوري اطلاعات ديدن كنيد .
************************
به اميد اينكه مطالب مفيد واقع بشه . با ارائه نظرات سازنده ي خودتون من رو در هرچه پربارتر كردن اين وب ياري كنيد .
متشكرم

مقالات فناوري اطلاعات
پیوندها
جستجوگر

طراح قالب

Powered By
BLOGFA.COM
لینک RSS
برنامه نويسي به زبان ++C (پست 51)

برنامه‌ي مثال آزمون بخش‌پذيري ناقص به نظر مي‌آيد زيرا اگر n بر d قابل تقسيم باشد ، برنامه هيچ عكس‌العملي نشان نمي‌دهد . اين نقص به كمك دستور if .. else رفع مي‌شود .

******************************************************

دستور if .. else

دستور if .. else موجب مي‌شود بسته به اينكه شرط درست باشد يا خير ، يكي از دو دستورالعمل فرعي اجرا گردد . نحو اين دستور به شكل زير است :

if  ( condition statement1 ;
else  statement2 ;

condition همان شرط مسأله است كه يك عبارت صحيح مي‌باشد و statement1 و statement2 فرمان‌هاي قابل اجرا هستند . اگر مقدار شرط غير صفر باشد ، statement1 اجرا خواهد شد وگرنه statement2 اجرا مي‌شود .

********************************************************

مثال : يك آزمون ديگر قابليت تقسيم

اين برنامه مانند برنامه‌ي مثال آزمون بخش‌پذيري است بجز اينكه دستور if با دستور if .. else جايگزين شده است :

int main()
{  int  n , d ;
   cout << " Enter two positive integers : " ;
   cin >> n >> d ;
   if ( n%d )     cout << n << " is not divisible by " << d << endl ;
   else   cout << n << " is divisible by " << d << endl ;
}

حالا وقتي در اين برنامه اعداد 56 و 7 را وارد كنيم ، برنامه پاسخ مي‌دهد كه 56 بر 7 قابل تقسيم است :

Enter two positive integers : 56  7
56 is divisible by 7

چون حاصل 7%56 برابر با صفر است ، پس اين عبارت بعنوان نادرست تفسير مي‌گردد . در نتيجه دستور بعد از if ناديده گرفته شده و دستور بعد از else اجرا مي‌شود . توجه كنيد كه if .. else به تنهايي يك دستور است ، گرچه به دو سميكولن نياز دارد .

 

نوشته شده توسط: مرضيه در دوشنبه هفتم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 50)

همه‌ي برنامه‌هايي كه تاكنون بيان شد ، به شكل ترتيبي اجرا مي‌شوند ، يعني دستورات برنامه به ترتيب از بالا به پايين و هر كدام دقيقاٌ يك بار اجرا مي‌شوند . در ادامه نشان داده مي‌شود كه چگونه از دستورالعمل‌هاي انتخاب (Selection) جهت انعطاف‌پذيري بيشتر برنامه استفاده كنيم . همچنين انواع صحيح كه در ++C وجود دارند را بيشتر بررسي مي‌كنيم .

****************************************************

دستور if

دستور if موجب مي‌شود برنامه به شكل شرطي اجرا شود . نحو آن به شكل زير است :

if  (condition)   statement ;

condition كه شرط ناميده مي‌شود ، يك عبارت صحيح است (عبارتي كه با يك مقدار صحيح برآورد مي‌شود) و statement مي‌تواند هر فرمان قابل اجرا باشد . statement وقتي اجرا خواهد شد كه condition مقدار غير صفر داشته باشد . دقت كنيد كه شرط بايد درون پرانتز قرار داده شود .

****************************************************

مثال : آزمون بخش‌پذيري

اين برنامه بررسي مي‌كند كه يك عدد صحيح مثبت ورودي بر عدد ورودي ديگر قابل تقسيم نباشد :

int main()
{   int  n , d ;
    cout << " enter two positive integers : " ;
    cin >> n >> d ;
    if ( n % d )  cout << n << " is not divisible by " << d << endl ;
}

در اولين اجرا ، اعداد 66 و 7 را وارد مي‌كنيم :

enter two positive integers : 66  7
66 is not divisible by 7

مقدار 7%66 برابر با 3 برآورد مي‌شود . چون اين مقدار ، يك عدد صحيح غير صفر است ، پس شرط به عنوان درست تفسير مي‌شود و در نتيجه دستور cout اجرا شده و پيغام عدم قابليت تقسيم چاپ مي‌شود .

برنامه‌ي بالا را دوباره اجرا مي‌كنيم و اين بار اعداد 56 و 7 را وارد مي‌كنيم :

enter two positive integers : 56  7

مقدار 7%56 برابر با صفر برآورد مي‌شود كه اين به معني نادرست تفسير مي‌گردد ، پس دستور cout ناديده گرفته شده و هيچ پيغامي روي صفحه چاپ نمي‌شود .

در ++C هر وقت يك عبارت صحيح به عنوان يك شرط استفاده شود ، مقدار 0 به معني نادرست و همه‌ي مقادير ديگر به معني درست است .

 

نوشته شده توسط: مرضيه در یکشنبه ششم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 49)

حوزه‌ي متغيرها

متغيرها بخش مهمي از هر برنامه هستند . استفاده از متغيرهايي با نوع نامناسب سبب هدر رفتن حافظه و كاهش سرعت و افزايش خطاهاي زمان اجرا مي‌شود . انتخاب نام‌هاي نامفهوم يا ناقص سبب كاهش خوانايي برنامه و افزايش خطاهاي برنامه‌نويسي مي‌شود . استفاده از متغيرها در حوزه‌‌‌ي نامناسب هم سبب بروز خطاهايي مي‌شود . "حوزه‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ي متغير (scope) محدوده‌‌‌‌‌‌‌اي است كه يك متغير خاص ، اجازه دارد در آن محدوده به كار رود يا فراخواني شود .

اصطلاح "بلوك" (block) در ++C واژه‌ي مناسبي است كه مي‌توان به‌ وسيله‌ي آن حوزه‌ي متغير را مشخص نمود . يك بلوك برنامه ، قسمتي از برنامه است كه درون يك جفت علامت كروشه { } محدود شده است . در برنامه‌هايي كه تاكنون ديديم از بلوك استفاده كرده‌ايم . هميشه بعد از عبارت ()int main يك كروشه‌ي باز } گذاشته‌ايم و در پايان برنامه ، يك كروشه‌ي بسته { قرار داديم . پس تمام برنامه‌هايي كه تا كنون ذكر شد ، يك بلوك داشته . به‌ طور كلي مي‌توان گفت كه حوزه‌ي يك متغير از محل اعلان آن شروع مي‌شود و تا پايان همان بلوك ادامه مي‌يابد . خارج از آن بلوك نمي‌توان به متغير دسترسي داشت . همچنين قبل از اينكه متغير اعلان شود ، نمي‌توان آن را استفاده نمود .

مثال زير را بررسي كنيد .

مثال : حوزه‌ي متغيرها

برنامه‌ي زير خطادار است :

int main()
{ // illustrates the scope of variables :
      x = 11 ;          // ERROR : this is not in the scope of x
      int x ;           
      {
      x = 22 ;          // OK : this is in the scope of x
      y = 33 ;          // ERROR : this is not in the scope of y
      int y ;
      x = 44 ;          // OK : this is in the scope of x
      }
      x = 66 ;          // OK : this is in the scope of x
      y = 77 ;          // ERROR : this is not in the scope of y
      return 0 ;
}

برنامه‌ي بالا دو بلوك تودرتو دارد . اولين بلوك بعد از عبارت ()int main شروع مي‌شود و در آخر برنامه بسته مي‌شود . بلوك داخلي نيز از خط پنجم آغاز مي‌شود و در خط دهم پايان مي‌يابد . نحوه‌ي تو رفتگي خطوط برنامه به درك و تشخيص شروع و پايان بلوك‌ها كمك مي‌كند . خط پنجم تا دهم تورفتگي بيشتري دارد ، يعني اين خطوط تشكيل يك بلوك مي‌دهند . همچنين خط دهم به بعد تورفتگي به اندازه‌ي خط سوم و چهارم دارد ، يعني مجموعه‌ي اين خطوط هم در يك حوزه‌ي مشترك قرار دارند .

اولين خطا در خط سوم رخ داده . متغير x در خط چهارم اعلان شده است . پس حوزه‌ي x از خط چهارم به بعد شروع مي‌شود ، در حالي كه در خط سوم متغير x فراخواني شده و اين خارج از محدوده‌ي x است .

دومين خطا در خط ششم اتفاق افتاده است . متغير y در خط هفتم اعلان شده . پس حوزه‌ي y از خط هفتم به بعد است ، در حالي كه در خط ششم y فراخواني شده و اين خارج از محدوده‌ي y است .

سومين خطا كه در خط دوازدهم روي داده نيز مربوط به y است . گرچه y در خطوط قبلي تعريف شده اما اين تعريف در يك بلوك داخلي بوده است . اين بلوك داخلي ، در خط دهم به پايان رسيده است . پس تمام تعاريفي كه در اين بلوك وجود داشته نيز فقط تا خط دهم اعتبار دارد . يعني حوزه‌ي y فقط از خط هفتم تا خط دهم است . لذا نمي‌توان در خط دوازدهم كه خارج از محدوده‌ي y است ، آن را به كار برد .

مثال بالا مطلب ظريفي را بيان مي‌كند : مي‌توانيم در يك برنامه ، چند متغير متفاوت با يك نام داشته باشيم به شرطي كه در حوزه‌هاي مشترك نباشند . مثال زير اين موضوع را به خوبي نشان مي‌دهد :

مثال : متغيرهاي تودرتو

int x = 11 ;               // this x is global
int main()
{ // illustrates the nested and parallel scopes :
      int x = 22 ;
      { // begin scope of internal block
            int x = 33 ;
            cout << " In block inside main() : x = " << x << endl ;
      }                         // end scope of internal block
      cout << " In main() : x = " << x << endl ;
      cout << " In main() :   ::x = " << ::x << endl ;
      return 0 ;
}                               // end scope of main()

خروجي برنامه :

In block inside main() : x = 33
In main() : x = 22
In main() :   ::x = 11

در برنامه‌ي بالا سه شيء متفاوت با نام 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 كه در حوزه‌ي بيروني است .

مي‌بينيد كه تعريف چند متغير در يك برنامه با نام يكسان به شيوه‌ي بالا ، ممكن و مجاز است . اما سعي كنيد از اين كار اجتناب كنيد زيرا برخي از كامپايلرها اجازه‌ي اين كار را نمي‌دهند . اگر هم اينطور نباشد ، هميشه مجبوريد به خاطر بسپاريد كه الان داخل كدام حوزه هستيد و كدام متغير مورد نظر شماست . اين طوري راحت‌تريد ؟ اختيار با شماست !

 

نوشته شده توسط: مرضيه در یکشنبه ششم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 49)

حوزه‌ي متغيرها

متغيرها بخش مهمي از هر برنامه هستند . استفاده از متغيرهايي با نوع نامناسب سبب هدر رفتن حافظه و كاهش سرعت و افزايش خطاهاي زمان اجرا مي‌شود . انتخاب نام‌هاي نامفهوم يا ناقص سبب كاهش خوانايي برنامه و افزايش خطاهاي برنامه‌نويسي مي‌شود . استفاده از متغيرها در حوزه‌‌‌ي نامناسب هم سبب بروز خطاهايي مي‌شود . "حوزه‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ي متغير (scope) محدوده‌‌‌‌‌‌‌اي است كه يك متغير خاص ، اجازه دارد در آن محدوده به كار رود يا فراخواني شود .

اصطلاح "بلوك" (block) در ++C واژه‌ي مناسبي است كه مي‌توان به‌ وسيله‌ي آن حوزه‌ي متغير را مشخص نمود . يك بلوك برنامه ، قسمتي از برنامه است كه درون يك جفت علامت كروشه { } محدود شده است . در برنامه‌هايي كه تاكنون ديديم از بلوك استفاده كرده‌ايم . هميشه بعد از عبارت ()int main يك كروشه‌ي باز } گذاشته‌ايم و در پايان برنامه ، يك كروشه‌ي بسته { قرار داديم . پس تمام برنامه‌هايي كه تا كنون ذكر شد ، يك بلوك داشته . به‌ طور كلي مي‌توان گفت كه حوزه‌ي يك متغير از محل اعلان آن شروع مي‌شود و تا پايان همان بلوك ادامه مي‌يابد . خارج از آن بلوك نمي‌توان به متغير دسترسي داشت . همچنين قبل از اينكه متغير اعلان شود ، نمي‌توان آن را استفاده نمود .

مثال زير را بررسي كنيد .

مثال : حوزه‌ي متغيرها

برنامه‌ي زير خطادار است :

int main()
{ // illustrates the scope of variables :
      x = 11 ;          // ERROR : this is not in the scope of x
      int x ;           
      {
      x = 22 ;          // OK : this is in the scope of x
      y = 33 ;          // ERROR : this is not in the scope of y
      int y ;
      x = 44 ;          // OK : this is in the scope of x
      }
      x = 66 ;          // OK : this is in the scope of x
      y = 77 ;          // ERROR : this is not in the scope of y
      return 0 ;
}

برنامه‌ي بالا دو بلوك تودرتو دارد . اولين بلوك بعد از عبارت ()int main شروع مي‌شود و در آخر برنامه بسته مي‌شود . بلوك داخلي نيز از خط پنجم آغاز مي‌شود و در خط دهم پايان مي‌يابد . نحوه‌ي تو رفتگي خطوط برنامه به درك و تشخيص شروع و پايان بلوك‌ها كمك مي‌كند . خط پنجم تا دهم تورفتگي بيشتري دارد ، يعني اين خطوط تشكيل يك بلوك مي‌دهند . همچنين خط دهم به بعد تورفتگي به اندازه‌ي خط سوم و چهارم دارد ، يعني مجموعه‌ي اين خطوط هم در يك حوزه‌ي مشترك قرار دارند .

اولين خطا در خط سوم رخ داده . متغير x در خط چهارم اعلان شده است . پس حوزه‌ي x از خط چهارم به بعد شروع مي‌شود ، در حالي كه در خط سوم متغير x فراخواني شده و اين خارج از محدوده‌ي x است .

دومين خطا در خط ششم اتفاق افتاده است . متغير y در خط هفتم اعلان شده . پس حوزه‌ي y از خط هفتم به بعد است ، در حالي كه در خط ششم y فراخواني شده و اين خارج از محدوده‌ي y است .

سومين خطا كه در خط دوازدهم روي داده نيز مربوط به y است . گرچه y در خطوط قبلي تعريف شده اما اين تعريف در يك بلوك داخلي بوده است . اين بلوك داخلي ، در خط دهم به پايان رسيده است . پس تمام تعاريفي كه در اين بلوك وجود داشته نيز فقط تا خط دهم اعتبار دارد . يعني حوزه‌ي y فقط از خط هفتم تا خط دهم است . لذا نمي‌توان در خط دوازدهم كه خارج از محدوده‌ي y است ، آن را به كار برد .

مثال بالا مطلب ظريفي را بيان مي‌كند : مي‌توانيم در يك برنامه ، چند متغير متفاوت با يك نام داشته باشيم به شرطي كه در حوزه‌هاي مشترك نباشند . مثال زير اين موضوع را به خوبي نشان مي‌دهد :

مثال : متغيرهاي تودرتو

int x = 11 ;               // this x is global
int main()
{ // illustrates the nested and parallel scopes :
      int x = 22 ;
      { // begin scope of internal block
            int x = 33 ;
            cout << " In block inside main() : x = " << x << endl ;
      }                         // end scope of internal block
      cout << " In main() : x = " << x << endl ;
      cout << " In main() :   ::x = " << ::x << endl ;
      return 0 ;
}                               // end scope of main()

خروجي برنامه :

In block inside main() : x = 33
In main() : x = 22
In main() :   ::x = 11

در برنامه‌ي بالا سه شيء متفاوت با نام 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 كه در حوزه‌ي بيروني است .

مي‌بينيد كه تعريف چند متغير در يك برنامه با نام يكسان به شيوه‌ي بالا ، ممكن و مجاز است . اما سعي كنيد از اين كار اجتناب كنيد زيرا برخي از كامپايلرها اجازه‌ي اين كار را نمي‌دهند . اگر هم اينطور نباشد ، هميشه مجبوريد به خاطر بسپاريد كه الان داخل كدام حوزه هستيد و كدام متغير مورد نظر شماست . اين طوري راحت‌تريد ؟ اختيار با شماست !

 

نوشته شده توسط: مرضيه در یکشنبه ششم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 48)

انواع ديگري از خطاهاي زمان اجرا

دوباره به برنامه‌ي محاسبه‌ي ريشه‌ها برگرديم . به اجراي زير نگاه كنيد :

enter the coefficients of a quadratic equation :
       a : 1
       b : 2
       c : 3
the equation is : 1 * x * x + 2 * x + 3 = 0
the solution are :
       x1 = nan
       x2 = nan
check :
       a*x1*x1 + b*x1 + c = IND
       a*x2*x2 + b*x2 + c = IND

در اين اجرا سعي شده تا معادله‌ي 1x2+2x+3=0 حل شود . اين معادله جواب حقيقي ندارد زيرا دلتا منفي است . وقتي برنامه اجرا شود ، تابع ()sqrt تلاش مي‌كند جذر يك عدد منفي را بگيرد ولي موفق نمي‌شود . در اين حالت پاسخ IND داده مي‌شود (IND مخفف عبارت Is Not Digit است ، يعني پاسخ عددي نيست) . پس هر محاسبه‌ي ديگري كه از اين مقدار استفاده كند ، همين پاسخ IND را خواهد داشت . به همين دليل در همه‌ي خروجي‌ها پاسخ IND آمده است .

سرانجام به اجراي زير دقت كنيد :

enter the coefficients of a quadratic equation :
       a : 0
       b : 2
       c : 5
the equation is : 0*x*x + 2*x + 5 = 0
the solutions are :
       x1 = IND
       x2 = -INF
check :
       a*x1*x1 + b*x1 + c = IND

در اين اجرا كوشش شده تا معادله‌ي 0x2+2x+5=0 حل شود . اين معادله داراي جواب x=2.5 است اما برنامه نمي‌تواند اين جواب را بيابد و با پاسخ‌هاي عجيبي روبرو مي‌شويم . علت اين است كه a صفر است و در حين اجراي برنامه ، سعي مي‌شود عددي بر صفر تقسيم شود . در چنين حالتي دوباره پاسخ IND بدست مي‌آيد .

سه نشانه‌ي IND و INF و INF- ثابت‌هاي عددي هستند . يعني مي‌توانيد اين مقادير را در محاسبات به كار ببريد اما نتيجه معمولاٌ بي‌فايده است . مثلاٌ مي‌توانيد عددي را با INF جمع كنيد يا از آن تفريق نماييد اما نتيجه بازهم INF خواهد بود .

 

نوشته شده توسط: مرضيه در یکشنبه ششم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 47)

مثال : خطاي گرد كردن پنهان

برنامه‌ي زير با استفاده از رابطه‌ي معادلات درجه‌ي دوم ، ريشه‌هاي اين معادلات را پيدا مي‌كند :

# include < cmath >   // defines the sqrt () function
# include < iostream >
using namespace std ;
int main()
{ // implements the quadratic formula
float a , b , c ;
cout << " enter the coefficients of a quadratic equation : " << endl ;
cout << " \ ta " ;
cin >> a ;
cout << " \ tb " ;
cin >> b ;
cout << " \ tc " ;
cin >> c ;
cout << " the equation is : " << a << " * x * x + " << b << " * x + " << c << " = 0 " << endl;
float d = b * b - 4 * a * c ;   // discriminant
float sqrtd = sqrt ( d ) ;
float x1 = ( ( - b + sqrtd ) / ( 2 * a ) ) ;
float x2 = ( ( - b - sqrtd ) / ( 2 * a ) ) ;
cout << " the solution are : " << endl ;
cout << " \ tx1 = " << x1 << endl ;
cout << " \ tx2 = " << x2 << endl ;
cout << " check : " << endl ;
cout << " \ ta + x1 * x1 + b * x1 + c = " << a * x1 * x1 + b * x1 + c << endl ;
cout << " \ ta + x2 * x2 + b * x2 + c = " << a * x2 * x2 + b * x2 + c << endl ;
return 0 ;
}

اين برنامه ضرايب 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 :
       a : 2
       b : 1
       c : -3
the equation is : 2 * x * x + -3 = 0
the solutions are :
       x1 = 1
       x2 = -1.5
check :
       a * x1 * x1 + b * x1 + c = 0
       a * x2 * x2 + b * x2 + c = 0

مي‌بينيد كه برنامه ، پاسخ‌هاي x1=1 و x2=-1.5 را پيدا كرده است و آزمون پاسخ نيز جواب صفر داده است . خروجي ديگري از برنامه نشان مي‌دهد كه برنامه تلاش كرده معادله‌ي 2x2+8.001x+8.002=0 را حل كند ولي شكست مي‌خورد :

enter the coefficients of a quadratic equation :
       a : 2
       b : 8.001
       c : 8.002
the equation is : 2 * x * x + 8.001 * x + 8.002 = 0
the solutions are :
       x1 = -1.9995
       x2 = -2.00098
check :
       a * x1 * x1 + b * x1 + c = 5.35749e-11
       a * x2 * x2 + b * x2 + c = -2.96609e-1

مقدار x1 كه در اجراي بالا آمده ، در آزمون شركت كرده و پاسخ بسيار نزديك به صفر داده است . اما مقدار x2 در آزمون شكست خورده زيرا جواب معادله به ازاي آن صفر نيست . چه چيزي باعث شده معادله جواب غلط بدهد ؟ جواب باز هم در خطاي گرد كردن است . x2 يك پاسخ گرد شده است نه يك پاسخ دقيق . اين پاسخ گرد شده دوباره در يك محاسبه‌ي ديگر شركت مي كند . پاسخ اين محاسبه هم گرد شده است . پس انحراف از جواب افزايش مي‌يابد و نتيجه‌اي دور از انتظار به بار مي‌آورد .

 

نوشته شده توسط: مرضيه در شنبه پنجم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 46)

خطاي گرد كردن

خطاي گرد كردن (Round-off) نوع ديگري از خطاست كه اغلب وقتي رايانه‌ها روي اعداد حقيقي محاسبه مي‌كنند ، رخ مي‌دهد . براي مثال عدد 3/1 ممكن است بصورت 0.333333 ذخيره شود كه دقيقاٌ معادل 3/1 نيست . به اين اختلاف ، خطاي گرد كردن مي‌گويند . اين خطا از آنجا ناشي مي‌شود كه اعدادي مثل 3/1 مقدار دقيق ندارند و رايانه نمي‌تواند اين مقدار را پيدا كند ، پس با اين اختلاف اندك ، نزديك‌ترين عدد قابل محاسبه را بجاي چنين اعدادي محاسبه مي‌كند . در بعضي حالات ، اين اختلاف اندك مي‌تواند مشكلات حادي را ايجاد كند .

مثال : خطاي گرد كردن

اين برنامه ، محاسبات ساده‌اي را انجام مي‌دهد تا خطاي گرد كردن را نشان مي‌دهد :

int main()
{ // illastrates round-off error:
double x = 1000/3.0 ;
cout << " x = " << x << endl ;   // x = 1000/3
double y = x - 333.0 ;   
cout << " y = " << y << endl ;   // y = 1/3
double z = 3 * y - 1.0 ;
cout << " z = " << z << endl ;   // z = 3 (1/3) - 1
if ( z == 0 )  cout << " z == 0.\ n " ;
else cout << " z does not equal 0.\ n " ;   // z != 0
return 0 ;
}

خروجي برنامه :

x = 333.333
y = 0.333333
z = -5.68434e-14
z does not equal 0.

منطق برنامه به اين شكل است كه ابتدا مقدار 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 بسيار نزديك صفر است ، اما رايانه همين مقدار كوچك را صفر نمي‌داند . پس مقايسه‌ي برابري شكست مي‌خورد .

 

 

 

نوشته شده توسط: مرضيه در شنبه پنجم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 45)
سرريز عددي

نوع صحيح long يا نوع مميز شناور double محدوده‌ي وسيعي از اعداد را مي‌توانند نگهداري كنند . به بيان ساده‌تر ، متغيري كه از نوع long يا double باشد ، گنجايش زيادي دارد . اما حافظه‌ي رايانه‌ها متناهي است . يعني هر قدر هم كه يك متغير گنجايش داشته باشد ، بالاخره مقداري هست كه از گنجايش آن متغير بيشتر باشد . اگر سعي كنيم در يك متغير ، مقداري قرار دهيم كه از گنجايش آن متغير فراتر باشد ، متغير سرريز (overflow) مي‌شود . مثل يك ليوان كه اگر بيش از گنجايش آن در ليوان آب بريزيم ، سرريز مي‌شود . در چنين حالتي مي‌گوييم كه خطاي سرريزي رخ داده است .

مثال : سرريزي عدد صحيح

اين برنامه بطور مكرر n را در 1000 ضرب مي‌كند تا سرانجام سرريز شود :

int main()
{ // prints n until it overflows:
int n = 1000 ;
cout << " n = " << n << endl ;
n *= 1000 ;  // multiplies n by 1000
cout << " n = " << n << endl ;
n *= 1000 ;  // multiplies n by 1000
cout << " n = " << n << endl ;
n *= 1000 ;  // multiplies n by 1000
cout << " n = " << n << endl ;
return 0 ;
}

خروجي برنامه :

n = 1000
n = 1000000
n = 1000000000
n = - 727379968

اين مثال نشان مي‌دهد رايانه‌اي كه اين برنامه را اجرا كرده است ، نمي‌تواند بيشتر از 1,000,000,000 را با 1000 بطور صحيح ضرب كند .

**************************************************

مثال : سرريزي عدد مميز شناور

اين برنامه شبيه چيزي است كه در مثال قبل ذكر شد . بطور مكرر x را به توان مي‌رساند تا اينكه سرريز شود :

int main()
{ // prints x until it overflows
float x = 1000.0 ;
cout << " x = " << x << endl ;
x *= x ;  // multiplies n by itself ; i . e , it squares x
cout << " x = " << x << endl ;
x *= x ;  // multiplies n by itself ; i . e , it squares x
cout << " x = " << x << endl ;
x *= x ;  // multiplies n by itself ; i . e , it squares x
cout << " x = " << x << endl ;
x *= x ;  // multiplies n by itself ; i . e , it squares x
cout << " x = " << x << endl ;
return 0 ;
}

خروجي برنامه بشكل زير است :

x = 1000
x = 1e + 06
x = 1e + 12
x = 1e + 24
x = INF

مثال بالا نشان مي‌دهد كه اين رايانه نمي‌تواند x را با شروع از 1000 بيش از سه بار مجذور كند . آخرين خروجي يعني INF نمادي است كه به معناي بينهايت مي‌باشد (اين نماد مخفف INFINITY است).

به تفاوت سرريزي عدد صحيح و سرريزي مميز شناور دقت كنيد . وقتي يك عدد صحيح سرريز شود ، عدد سرريز شده به يك مقدار منفي گرايش مي‌يابد اما وقتي كه يك عدد مميز شناور سرريز شود ، نماد INF به معناي بينهايت را به دست مي‌دهد ، نشانه اي مختصر و مفيد .

نوشته شده توسط: مرضيه در شنبه پنجم مرداد 1387|+|
برنامه نويسي به زبان ++C (پست 44)

برخي از خطاهاي برنامه‌نويسي

اكنون كه انواع متغير در ++C را شناختيم ، مي‌توانيم از اين انواع در برنامه‌هاي مفيدتر و جدي‌تر استفاده كنيم . اما بايد دقت نمود كه اگر از متغيرها بشكل نادرست يا كنترل نشده استفاده كنيم ، برنامه دچار خطا مي‌شود . البته عوامل ديگري نيز هست كه باعث مي‌شود اجراي برنامه مختل گردد ، مثل استفاده از متغيري كه تعريف نشده يا جا انداختن سميكولن انتهاي دستورها . اين قبيل خطاها كه اغلب خطاهاي نحوي هستند و توسط كامپايلر كشف مي‌شوند ، "خطاهاي زمان كامپايل" ناميده مي‌شوند و براحتي مي‌توان آن‌ها را رفع نمود . اما خطاهاي ديگري نيز وجود دارند كه كشف آن‌ها به راحتي ممكن نيست و كامپايلر نيز چيزي راجع به آن نمي‌داند . به اين خطاها ، خطاي زمان اجرا مي‌گويند . برخي از خطاهاي زمان اجرا سبب مي‌شوند كه برنامه بطور كامل متوقف شود و از كار بيفتد. در چنين حالتي متوجه مي‌شويم كه خطايي رخ داده است و در صدد كشف و رفع آن برمي‌آييم . برخي ديگر از خطاهاي زمان اجرا ، برنامه را از كار نمي‌اندازند بلكه برنامه همچنان كار مي‌كند اما پاسخ‌هاي عجيب و نادرست مي‌دهد . اين نوع خطا در حالات خاصي رخ مي‌دهد و گاهي سبب گيج شدن برنامه‌نويس مي‌گردد .در بخش‌هاي بعدي برخي از خطاهاي رايج زمان اجرا را نشان مي‌دهيم تا در برنامه‌هايتان از آنها پرهيز كنيد . دست كم اگر با پاسخ‌هاي غير منتظره و غلط مواجه شديد ، محل رخ دادن خطا را راحت‌تر پيدا كنيد .                     

 

نوشته شده توسط: مرضيه در سه شنبه یکم مرداد 1387|+|
Technology
آرشیو
آمار وبلاگ
» تعداد بازدیدها:
» مرورگر:
امکانات اضافي

© All Rights Reserved by mrz-it.Blogfa.com ©