loading...
دانلود سرای دانشجویی

 

پيش پردازنده (preprocessor) بخشی از کامپايلر است که قسمت هائی از برنامه را، قبل از اينکه کل آن توسط کامپايلر ترجمه شود، مورد ارزيابی قرار می دهد. برنامه نويس می تواند دستوراتی را در برنامه خود درج کند که مستقيما پيش پردازنده را فراخوانی کند به اين دستورات پيش پردازنده می گويند. پيش پردازنده ها ممکن است باعث تغيير متن برنامه قبل از تحويل آن به کامپايلر شوند.

قبلا از پيش پردازنده ها در ضميمه کردن فايل يا تعريف ثابت استفاده کرده ايد.

سه کاربرد اصلی برای پيش پردازنده ها وجود دارد:

• راهنماها
• ثابت ها
• ماکروها

کلاس های حافظه

کلاس حافظه (storage class) تعيين می کند چگونه حافظه به متغيرها توسط کامپايلر واگذار شود. فضای حافظه برای ذخيره متغيرها و توابع و طول عمر اين فضا در طول اجرای برنامه توسط کلاس حافظه مشخص می شود.

محل ذخيره و محدوده متغيرها بسته به محلی (که می تواند داخل يا خارج بدنه تابع باشد) دارد که تعريف می شوند. وقتی پيش فرض های ذخيره سازی شما را راضی نمی کنند می توانيد از کلاس های حافظه استفاده کنيد.

کلاس های حافظه در C و ++C عبارتند از:

auto •
register •
static •
extern •
typedef •
mutable •
(تنها در ++C)

auto

اگر کلمه کليدی auto را قبل از اعلان متغيری قرار دهيد صريحا نوع ذخيره سازی اتوماتيک (automatic storage) را برای متغير مدنظر گرفته ايد. متغيری که ذخيره سازی اتوماتيک دارد با خروج از بلاکی که در آن تعريف شده پاک می شود. حافظه زمان ورود به بلاک اختصاص و زمان خروج از آن آزاد می شود.


مثال. اعلان صريح يک متغير اتوماتيک.

auto int i;


دسترسی به متغير از طريق اسم آن است. بخشی از برنامه است که نام متغير در آن قابل رويت است ميدان يا حوزه (scope) ناميده می شود.

ميدان عمل متغيرهای اتوماتيک درون بلاکی است که در آن اعلان شده اند و خارج از آن قابل رويت نيستند. به همين دليل به آنها متغيرهای محلی نيز گفته می شود.

کلاس auto برای متغيرهای محلی و درون بلاک نوع پيش فرض است و نيازی به ذکر کلمه auto نيست.

نکته. کلاس auto را می توانيد برای متغيرهای درون يک بلاک يا پارامترهای تابع اعمال کنيد.
نکته. با اشاره گرها می شود به متغيرهای محلی از خارج بلاک دسترسی پيدا کرد.
نکته. اگر متغير اتوماتيک مقداردهی اوليه نشود مقدارش نامعلوم خواهد بود. اگر يک مقدار اوليه تعيين کنيد هر زمان که وارد بلاکی که متغير در آن تعريف شده شود مقدار به متغير تخصيص داده می شود.
نکته. اگر از دستور goto برای پرش به بلوکی استفاده کنيد متغيرهای اتوماتيک مقداردهی نمی شوند.
نکته. اگر متغيری درون تابع بازگشتی اعلان شود در هربار فراخوانی تابع حافظه ايجاد و مقداردهی می شود.

register

ثبات ها حافظه هائی درون خود CPU هستند که داده آنها می تواند به سرعت دسترسی شود. معمولا کامپايلر تعيين می کند چه زمانی چه داده ای بايد در ثبات ذخيره شود. با وجود اين کلاس register اين امکان را به برنامه نويس می دهد که به کامپايلر بگوييد در صورت امکان متغير اتوماتيکی را درون ثبات ذخيره کند.

کامپايلر مجبور به اجرای اين درخواست نيست زيرا اندازه و تعداد ثبات های موجود در سيستم محدود است و تعداد کمی از متغيرها می توانند حقيقتا در ثبات ها قرار گيرند. اگر کامپايلر ثباتی را اختصاص ندهد با متغيرثباتی مانند متغير اتوماتيک برخورد می کند.


مثال. اعلان متغير از کلاس ثبات.

register int var;


نکته. متغيرهای ثباتی نوعی متغير اتوماتيک محسوب می شوند.
نکته. متغيرهای ثبات بايد درون يک بلاک يا به صورت پارامتر تابع اعلان شده باشند.
نکته. ذخيره سازی کلاس ثبات از نوع اتوماتيک است يعنی با ورود به بلاک ايجاد و در انتها از بين می رود.
نکته. متغيرهای ثبات را می توان مقداردهی اوليه داد.
نکته. در C اشاره گر به متغير ثبات نمی توانيد داشته باشيد. اما C++ اجازه می دهد آدرس متغير از نوع ثبات را بگيريد.
نکته. کلاس ثبات را نمی توانيد برای اشيای درون فضای اسمی استفاده کنيد.

static

متغيرهایئی که با کلاس static اعلان می شوند طول عمر ذخيره ايستا (static storage duration) دارند. بدين معنی که حافظه ثابتی از زمان شروع اجرای برنامه به آنها اختصاص داده می شود و تا پايان اجرای برنامه آزاد نمی شود.


مثال. اعلان و مقداردهی متغيری از کلاس ايستا.

static int staticInt = 5;


متغيرهای static به حياط خود حتی بعد از خروج از بلاکی که در آن تعريف شده اند ادامه می دهند. بنابراين مقدار متغير در تابع بين فراخوانی های مکرر همان تابع حفظ می شود.


مثال. فرض کنيد متغير x در تابع ()f اعلان شده است که تا زمان اجرای برنامه باقی می ماند.

#include <iostream.h>
int f(void) {
   static int x = 0;
   x++;
   return x;
}
int main(void) {
   int j;
   for (j = 0; j < 5; j++) {
      cout << "Value of f(): " << f() << endl;
   }
   return 0;
}

چون x از نوع static است هربار صفر نمی شود، بلکه مقدار قبلی خود را در تابع حفظ می کند. خروجی برنامه به صورت زير خواهد بود:

Value of f(): 1
Value of f(): 2
Value of f(): 3
Value of f(): 4
Value of f(): 5


نکته. متغير static درون بلاک تنها يکبار مقداردهی می شود در حاليکه متغير auto هربار که اجرا وارد بلاک شود مقداردهی می شود.
نکته. اگر يک متغير static صريحا مقداردهی نشود مقداراوليه صفر را می گيرد.
نکته. کلاس static مادام العمر هستند اما مشابه auto می توان ميدان آنها را محدود به بلاک کرد.
نکته. کلاس static می تواند برای متغيرهای اتوماتيک و خارجی هم استفاده بشود.

extern

کلمه کليدی extern برای توصيف متغيری است که خارجی تعريف شده است. متغيرهای خارجی بيرون از هر بلاکی درون يک فايل اعلان می شوند و می توانند خارج از فايلی که در آن تعريف شده است استفاده شوند.

با کلاس extern متغيرها و توابعی را می توان تعريف کرد که در چندين فايل قابل دسترسی هستند.


مثال. اگر برنامه شامل چندين فايل منبع file1.cpp، file2.cpp و file3.cpp باشد. متغيری که در فايل file1.cpp تعريف است در دو فايل ديگر همراه با کلمه extern بايد ذکر شود تا قابل دسترسی باشد.


حافظه چنين متغيرهائی زمان شروع اجرای برنامه اختصاص داده می شود و تا انتهای برنامه باقی می ماند. ميدان متغيرهای خارجی سراسری است يعنی در کل متن فايل بعد از خطی که اعلان شده اند قابل دسترسی هستند.

متغيرهای خارجی ممکن مانند متغيرهای اتوماتيک با يک مقدار ثابت مقداردهی شوند. مقداردهی در زمان کامپايل تنها يکبار وقتی حافظه اختصاص داده می شود انجام می شود.

چون هر تابعی در برنامه می تواند به متغير خارجی دسترسی پيدا کند اشکال زدائی برنامه سخت تر خواهد شد. به همين علت شايد بهتر باشد از متغيرهای خارجی استفاده نشود. اما گاهی متغيرهای خارجی باعث ساده تر شدن پياده سازی الگوريتم می شود.

نکته. در اکثر کامپايلرها مقداراوليه صفر به متغيرهای خارجی داده می شود.
نکته. اگر تابعی متغيرمحلی هم نام با خارجی داشته باشد درون تابع ارجاع به متغير محلی خواهد بود.
نکته. در عمل بهتر است کليه اعلانات extern در يک فايل هدر جمع شده و فايل با راهنمای include# ضميمه شود.
نکته. در ++C اعلان خارجی نمی تواند در داخل کلاس ظاهر شود.

typedef

اعلان typedef به شما اجازه می دهد شناسه های خودتان را تعريف کنيد که می توانند جای نوع داده نظير int يا float را بگيرند. يک اعلان typedef محلی برای ذخيره نمی گيرد و نوع داده جديدی نيست بلکه مترادفی برای انواع داده يا ترکيبی از آنهاست.

Typedef بخاطر شباهت های گرامری در دسته شاخص های کلاس حافظه گروه بندی می شود.


مثال. عبارت زير LENGTH را مترادف با int اعلان می کند.

typedef int LENGTH;
LENGTH length, width, height;

اعلان زير معادل مثال قبل است:

int length, width, height;

مثال. اعلان يک ساختمان توسط typedef. متغيرهای chicken، cow، horse و whale از نوع ساختمان WEIGHT تعريف شده اند.

typedef struct {
   int scruples;
   int drams;
   int grains;
   } WEIGHT;
WEIGHT chicken, cow, horse, whale;

مثال. يک کلاس توسط typedef بدون نام تعريف شده و يک نام مستعار Trees را گرفته. چنين کلاس هائی نمی توانند سازنده و مخرب داشته باشند. ()Trees نمی تواند سازنده برای کلاس باشد.

typedef class {
   Trees();
   } Trees;


mutable

کلاس ذخيره mutable تنها روی اعضای داده ای يک کلاس می تواند اعمال شود و باعث می شود اين اعضا حتی اگر در کلاس به صورت const تعريف شده اند قابل تغيير باشند.


مثال. در اين برنامه کامپايلر اجازه نمی دهد انتساب var2.y=2345 انجام بشود زيرا var2 به صورت يک ثابت تعريف شده است. اما var2.x=345 اجرا می شود چون A::x به صورت mutable اعلان شده است.

class A {
   public:
      A() : x(4), y(5) { };
      mutable int x;
      int y;
};
int main() {
   const A var2;
   var2.x = 345;
   // var2.y = 2345;
}

نکته. کلاس mutable را نمی توانيد همراه با static يا const اعلان کنيد.

فضای اسمی std

کليه کتابخانه های استاندارد ++C درون يک فضای اسمی قرارداده شده اند که std نام دارد. ممکن است راهنمای زير را در خيلی از برنامه ها مشاهده کنيد. اين خط بيان می کند که می خواهيد کليه عناصر درون فضای اسمی std در اختيار قرار بگيرد.

using namespace std;

بين فضای اسمی و نحوه ضميمه کردن فايل هدر ارتباط وجود دارد. اگر فايل هدر را به شکل include# <iostream.h> با پسوند .h ضميمه کنيد به معنی دو خط زير خواهد بود:

#include <iostream>
using namespace std;

اگر پسوند .h صريحا ذکر نشود راهنمای using را بايد اضافه کنيد.


مثال. استفاده از cout.

#include <iostream>
int main() {
   std::cout << "Hello ";
   using namespace std;
   cout << "World." << endl;
}

فضای اسمی

وقتی يک برنامه به اندازه معينی می رسد معمولا به چند قطعه شکسته می شود، هر تکه ممکن است توسط افراد يا گروه متفاوتی ساخته و تکميل شود. زبان C تنها يک مکان برای نگهداری اسامی کليه شناسه ها و توابع دارد. يعنی برنامه نويسان بايد درباره نامگذاری اسامی محتاط باشند تا برخوردی پيش نيايد.

++C مکانيسمی برای جلوگيری از اين تصادم دارد: فضای اسمی (namespace). هر مجموعه از تعاريف که در يک کتابخانه يا يک برنامه قرار دارند درون يک فضای اسمی مجزا جا می گيرند. اعلان اسامی مشابه در فضاهای اسمی متفاوت هيچ برخوردی پيش نمی آورد.

فضای اسمی ناحيه ای است که يک شناسه اضافی را به اسامی عناصر درون خود الحاق می کند. هر نام بدليل اضافه شدن شناسه فضای اسمی منحصر بفرد خواهد شد. بنابراين می توان اسامی مشابه در فضاهای اسمی متفاوت حتی در يک فايل داشت. مادامی که اسامی مشابه در فضاهای اسمی مجزا هستند مشکلی در برنامه بروز نمی کند.

کلمه کليدی namespace يک نام منحصربفرد را برای يک فضای اسمی تعريف می کند. شکل کلی تعريف فضای اسمی به صورت زير است:

namespace identifier
{
   [ declaration-list ]
}

identifier شناسه فضای اسمی است که برای ارجاع به اعضای آن استفاده می شود. declaration-list اعضای فضای اسمی هستند که حتما بايد درون آکولاد محصور شوند. اعضا می تواند شامل اعلان متغير، تابع، اشيا و فضای اسمی باشد.

به نام هرکدام از اعضا شناسه فضای اسمی توسط عملگر حوزه (::) اضافه می شود.

مثال. دو متغير x در دو فضای اسمی. يکی one::x و ديگری two::x خواهد شد.


namespace one {
   int x;
}
namespace two {
   float x;
}
int main() {
   one::x++;
}


نکته. شناسه فضای اسمی در واحدی که استفاده می شود بايد يکتا باشد.
نکته. اعلان فضاهای اسمی می توانند تودرتو باشند.
نکته. عملگر حوزه (::) که قبل از آن شناسه ای نباشد به ناحيه سراسری اشاره می کند.


مثال. فضای اسمی B درون A تعريف شده است.

int i;
namespace A {
   int j;
   namespace B {
      int j, k;
   }
}
int main() {
   A::j++;        //A's j
   A::B::j++;   // B's j
   ::i++;          // the global i
}


می توانيد از فضای اسمی بدون شناسه به عنوان راهی برای اعلان متغيرهای ايستای سراسری بهره ببريد. فضای اسمی بدون نام شکل کلی زير را دارد.

namespace { declaration-list }

که در حقيقت مثل اين است که به صورت زير تعريف شده باشد.

namespace unique { declaration-list }
using namespace unique;

برخلاف نواحی تعريفی ديگر تعريف يک فضای اسمی می تواند در چندين قسمت درون يک واحد (مانند فايل) تقسيم شود. البته اعضای يک فضای اسمی شناسه دار می توانند در خارج از آن تعريف شوند به شرطی که بعد از تعريف فضای اسمی قرار بگيرد.


مثال. تعريف اعضای فضای اسمی در دو قسمت.

namespace A { // declare namespace A variables
   int i;
   int j;
}
namespace A { // declare namespace A functions
   void func(void);
   int int_func(int i);
}

مثال. توابع f() و g() متعلق به فضای اسمی V هستند که خارج از ان تعريف شده اند.

namespace X { void f() { } }
namespace V {
   void f();
}
void V::f() { }   // ok
void V::g() { }   // g() is not yet a member of V
namespace V {
   void g();
}

راهنمای using

فضای اسمی ابزار ساده و سودمندی است اما حضورشان به اين معنی است که شما قبل نوشتن برنامه بايد مواظب باشيد. تنها کافی نيست فايل هدری را پيوست کنيد و توابع و اشيای آن را استفاده کنيد. برای مواجه نشدن با خطای کامپايلر هنگام ترجمه برنامه بايد کامپايلر را مطلع کنيد که می خواهيد از اعلانات درون فضای اسمی استفاده کنيد. چون کامپايلر نمی تواند داده هائی که دربرنامه اعلان کرده ايد را پيدا کند.

با کلمه کليدی using به کامپايلر می گوييد از اعلانات يا تعاريف کدام فضای اسمی می خواهيد استفاده کنيد.

راهنمای using اجازه می دهد اعضای فضای اسمی بدون ذکر شناسه فضای اسمی استفاده شوند. البته استفاده از شناسه برنامه را خواناتر می کند. اما راهنمای using راه کوتاهتری برای ارجاع به اعضای فضای اسمی را فراهم می کند.


مثال. استفاده از راهنمای using .

namespace A {
   int i;   // A::i
   int j;   // A::j
}
namespace B {
   int i;   // B::i
}
using namespace A;
void h() {
   i++;        // A::i++
   B::i++;   // B::i++
   j++;        // A::j++
}


نکته. اگر متغير محلی هم نام با متغير فضای اسمی باشد متغير فضای اسمی مخفی می شود.
نکته. داشتن يک متغير فضای اسمی همنام با متغير سراسری خطا دارد.
نکته. راهنمای using را در ابتدای متن برنامه قرار دهيد.

بلاک های try-catch

مديريت استثنا بر اساس مفاهيمی که گفته شد توسط سه دستور try، catch و throw‌ عمل می کند. بلاک کدی می خواهيم استثناهای آن را بگيريم با دستور try مشخص می شود. درون بلاک می توان هر خطائی با دستور throw گير افتاده و از بين می رود. بلاک catch که محلی برای کد مديريت خطا است بلافاصله بعد از بلاک try قرار می گيرد.

فرم کلی به صورت زير است:

try {
   ...
   ...
   throw Exception;
   ...
   ...
   }
catch( Exception e ) {
   ...
   ...
   }


مثال. هر استثنائی که موقع دسترسی به فايل test.txt رخ دهد گرفته و پيغام مناسب نمايش داده می شود.

#include <fstream.h>
#include <iostream.h>
int main () {
   try {
      char buffer[256];
      ifstream myfile ("test.txt");
      while (! myfile.eof() ) {
         myfile.getline (buffer,100);
         cout << buffer << endl;
      }
   }
   catch(…) {
      cout << “There was an error !n”;
   }
   return 0;
}


سه نقطه درون پرانتز catch به معنی اینستکه کلیه خطاها توسط این بلاک مديريت می شود. می توان انواع مختلفی از خطاها را هندل کرد.

وقتی استثنائی رخ می دهد کنترل به بلاک catch منتقل می شود بنابراين دستورات بعد از throw اجرا نخواهد شد. در بلاک catch کد بايد به نحوی باشد که اجرای برنامه را به صورت معمول ادامه يابد يا در صورت برطرف نشدن خطا با exit يا abort خاتمه پيدا کند. اگر بلاک catch اجرای برنامه را به پايان نرساند کنترل اجرا به دستور بعد از بلاک try-catch منتقل می شود.

نکته. بین دو بلاک هیچ چیز نباید باشد.
نکته. در صورت گير انداختن يک استثنا دستورات بعد از throw اجرا نخواهد شد.
نکته. يک استثنا را می توان به تابعی که تابع جاری را صدا زده است انداخت تا مديريت شود .


مثال. خطا در تابع گرفته می شود اما به برنامه اصلی برای مديريت ارسال می شود.

#include <iostream.h>
float divide_number(float , float);
int main() {
   float dividend,divisor,answer;
   try {
      cout << "Please enter a number n";
      cin >> dividend;
      cout << "Please enter a number n";
      cin >> divisor;
      answer = divide_number(dividend,divisor);
      cout << dividend << " divided by ";
      cout << divisor << " is " << answer;
      }
   catch(...) {
      cout << "oops, there is an error!";
      }
   return 1;
}
float divide_number(float num1, float num2) {
   try {
      float answer;
      answer = num1/num2;
      return answer;
      }
   catch(...) {
      throw;
   }
}


هر دستور try می تواند با چندين دستور catch در ارتباط باشد. هر کدام برای نوع مختلفی از استثنا. نوع داده ای که در دستور catch مشخص شده است با استثنای تطبيق داده می شود سپس بخش مربوطه به اجرا در می آيد و از بقيه صرفنظر می شود. هر نوع داده ای از جمله کلاس های تعريف شده در برنامه می تواند بدام انداخته شود.


مثال. اعداد صحیح توسط catch گرفته می شود. اگر تقسیم بر صفر باشد یک عدد صحیح به بلاک catch داده می شود. بلاک catch استثنا از نوع صحيح را می گيرد.

#include <iostream.h>
int main(){
   int answer, divisor, dividend;
   try {
      cout << "Please enter an integer n";
      cin >> divisor;
      cout << "Please enter another integer n";
      cin >> dividend;
      if(dividend ==0) throw 0;
      answer = divisor/dividend;
      cout << answer;
      return 0;
      }
   catch (int i) {
      cout << "You cannot divide by zero";
      }
}

مثال. کاربرد مديريت استثناها در استفاده از حافظه پويا.

try {
   NodePtr = new ListNodeClass(Item, NextPtr);
   if (NodePtr == NULL) {
      throw "Cannot allocate memory";
   }
   NodePtr = GetNode(Item, Front->Next);
   }
catch(char * Str) {
   cout << "Error: Could not insert at front " << Str << endl;
   throw;
   }

مثال. مديريت استثنا با چند بلاک catch.


try{
   cin >> test;
   if (test == 0 ) throw test;
   if (test == 1 ) throw 'a';
   if (test == 0 ) throw 123.5;
   }
catch(float FloatNum){
   cout << "Caught an exception with float value: " << FloatNum << endl;
   }
catch(int IntNum) {
   cout << "Caught an exception with int value: " << IntNum << endl;
   }
catch(...){ // catch anything else
   cout << "Caught an exception with type not int or float" << endl;
   }


وقتی چندین خطا را پاسخ می دهید سلسله مراتب خطاها اهمیت دارد. خطاها با ترتیبی که در سلسله مراتب نشان داده شده است باید در تله انداخته شوند یعنی اگر شما run-time-error را گیر انداختید نمی توانید عبارت catch دیگری برای file access error داشته باشید چون خطاهائی که در سلسله مراتب بالاتر هستند کلیه خطاهای پایینی را در بر دارند.

Exception – the parent class for all exception class
   Login-error – the parent class of a variety of logic error
      invalid-argumet
      out-of-range
   Runtime-error – the parent of class for a variety of rumtime error
      overflow-error
      FileAccessError
      range-error

مديريت استثناها

قبل از اينکه سيستم مديريت استثناها معرفی شود برنامه های کامپيوتری کاملا بدون خطا نبودند. البته برای گرفتن خطاها روش هائی وجود داشت که معمول ترين آن بررسی مقداری بود که توسط توابع برگردانده می شد و نحوه اجرای آن را بيان می کرد. کدی که تابع را فراخوانی می کرد مقدار بر گشتی را چک می کرد و مطابق با آن عمل می کرد (اگر با استفاده از Windows API برنامه نوشته باشيد با اين روش آشنا هستيد).

مفهوم کلی مديريت استثناها ساده است. هر زمان که استثنائی شناسائی می شود يک فلگ فرضی خطا بالا می رود. سيستمی همواره مراقب اين فلگ خطاست. و درصورت بالا رفتن فلگ کد مديريت خطا فراخوانی می شود. بالا رفتن فلگ خطا را اصطلاحا گير انداختن (throwing) خطا می نامند. وقتی خطائی به دام انداخته می شود سيستم با گرفتن خطا (catching) عکس العمل نشان می دهد. محاصره کردن بلاکی از کد حساس به خطا و مديريت استثنا را سعی کردن (trying) به اجرای بلاک می نامند.

دلايل خوبی برای استفاده از مديريت استثناها وجود دارد. مهمترين آن جداکردن کد مديريت خطا از کد برنامه است. وقتی استثنائی گرفته می شود مسيری موازی اجرا طی می شود و با اجرای نرمال کد برنامه تداخلی ندارد. اين باعث می شود نوشتن کد ساده تر شود چون مجبور نيستيد برای هر خطائی چک داشته باشيد. علاوه بر اين يک استثنا نمی تواند نديده گرفته شود و تضمين می کند که با خطا برخورد کند. و چون جلوی سقط ناخواسته برنامه را می گيرد اتکاپذيری برنامه را بالا می برد.

از مزايای ديگر مديريت استثناها اين است که خطا می تواند خارج از محدوده تابع گيرانداخته شود. يعنی اگر درونی ترين تابع خطائی داشته باشد اين خطا می تواند تا تابع بالائی که دارای بلاک trying است منتشر شود که به برنامه نويس اجازه می دهد کد مديريت خطا را در هر جا مثل تابع اصلی قرار بدهد.

 

خطاها را به سه دسته می توان تقسیم کرد:

• خطاهای گرامری (syntax error). خطاهائی که با رعايت نکردن قواعد زبان برنامه نويسی توسط کامپايلر تشخيص داده می شوند. مثلا بجای if(x!=y) بنویسید if(x<>y). کامپایلر کد برنامه را تا وقتی خطای گرامری وجود دارد کامپایل نمی کند.
• خطاهای زمان اجرا (runtime error). هر وقفه ای که در جریان عادی اجرای برنامه پیش آید که معمولا باعث سقط برنامه می شود. مثلا باز کردن فایلی که وجود ندارد یا تقسیم بر صفر. این خطاها استثنا (exception) نامیده می شوند.
• خطاهای منطقی (login error). وقتی برنامه کامپایل و اجرا می شود اما به دليل خطائی در منطق برنامه نتایج غلطی تولید می کند. سخت ترین نوع خطا است که معمولا به آن bug هم گفته می شود.

برای رفع خطا ابتدائی ترین کاری که می شود کرد تست کلیه برنامه و کشف و برطرف سازی خطا است. کنترل مناسب خطاها از سقط برنامه جلوگيری می کند. کامپایلر خطاهای گرامری را مشخص می کند. مديريت استثناها خطاهای زمان اجرا را بر عهده دارند بنابراين خطاهای منطقی بزرگترین مشکل برنامه نویس خواهد بود.

تعداد صفحات : 425

اطلاعات کاربری
آمار سایت
  • کل مطالب : 4247
  • کل نظرات : 0
  • افراد آنلاین : 4
  • تعداد اعضا : 2926
  • آی پی امروز : 107
  • آی پی دیروز : 187
  • بازدید امروز : 579
  • باردید دیروز : 2,391
  • گوگل امروز : 16
  • گوگل دیروز : 32
  • بازدید هفته : 6,833
  • بازدید ماه : 2,970
  • بازدید سال : 116,883
  • بازدید کلی : 8,295,577
  • کدهای اختصاصی