Sultan_Althibity

الاستثناءات في السي بلس بلس

3 ردود في هذا الموضوع

الاستثناءات

Exception

لا بد لأي برنامج أن يقابل بعض الأخطاء ، مثل عدم القدرة على فتح ملف ما أو خطأ في قراءة ملف أو ربما إدخالات غير صحيحـة من قبل المستخدم .... مثل هذه الحالات يطلق عليها الاستثناءات ، وهي حالات متوقعـة يتوقعها المبرمج أثناء تصميمه لبرنامجه وليست كما يعتقد البعض أنها غير متوقعـة .

هذا المقال يحاول معالجـة هذا الموضوع "الاستثناءات exception " والبنود المتعلقة به .. وماذا قدمت الـ STL من فئات classes للتعامل مع هذا الموضوع.

+ تمهيد.

+ نظرة عامـة إلى الاستثناءات.

+ تعدد الأوجـه والاستثناءات ومكتبة الـ STL.

+ التعامل مع تبعات استخدام الاستثناءات.

+ التعامل مع أخطاء الذاكرة.

+ الاستثناءات في الباني constructor.

* تمهيد:

الاستثناءات هي عبارة عـن مقطع كـودي يخبر مقطع كـودي آخر بحصول خطأ أو حالة استثنائيـة دون المرور بالسير العام للبرنامج. المقطع الذي يجد خطأ ما فإنه يرميـه throw والمقطع الذي يتم إعلامـه بحصول الخطأ فإنه يقبض على الخطأ catch .

هـناك الكثير من الأسباب التي دعت إلى ظهـور مثل هذا الأسلوب من معالجـة الأخطاء ، ففي لغـة السي يتم التعامل مع الأخطاء في نفس المكتبـة ، فالدالة scanf مثلاً تعيد القيمة 0 في حال فشلها في الإدخال ولكن منشؤو المكتبات لم يتفقوا على قيمـة محددة على أنها هي التي تعاد من الدالة عـند وقوع الخطأ ، لذلك تجد مثلاً دالة تعيد القيمة -1 للدلالة على حصول خطأ ، وبعض الدوال تعيد القيمة صفر في حال نجاحها والقيمـة غير الصفر في حال فشلها ، وسبب آخر هـو عدم قدرة الدوال في لغـة السي بلس بلس على إعادة قيمـتين بدلاً من قيمـة واحدة .. حيث ستكون واحدة منها عـند حدوث خطأ ما. من الممكن القول أن الاستثناءات تعتبر طريقة أفضل من هذه الطريقـة المستخدمـة في لغـة السي بسبب الآتي:

+ الأخطاء في طريقة لغـة السي من الممكن تجاهلها أو نسيان معالجتها ولكن عـند الاستثناءات فلا يمكن حصول ذلك ، وإن حصل فإن البرنامج ينتهي أتوماتيكيا.

+ أنها تحتوي على معلومات دلالية عـن نوع الخطأ ، فقد يكون الخطأ تمرير بارامترات خاطئـة أو خطأ في وقت التنفيذ أو قصور في الذاكرة .. بينما في لغـة السي فإن البديل هـو مجمـوعـة من الأرقام ، ولكن هذه الأرقام لا يمكن أن تكون بديلاً أفضل من المعاني الدلاليـة بسبب أن الأرقام قد تعـني أي شيء آخر للمبرمجين الآخرين.

+ كم كبير من الكـود ستكتبـه في حال اعتماد على نظرة لغـة السي لمعالجـة الأخطاء بسبب أنك ستتأكد من تنفيذ جميع الأوامر ، فكل أمر سيتطلب منك ثلاثة أسطر على أقل تقدير حتى تتأكد أنه تم تنفيذه بشكل جيد وأنه سيعالج أيضاً في حال وقوع خطأ.

أيضاً هـناك بعض الميزات الأخرى ستتعرف عليها حينما ننتهي من هذا الموضوع

*نظرة عامة إلى الاستثناءات:

الخطوتان الأساسيتان لاستخدام الاستثناءات هي التالي:

1) التعرف على المقاطع الكـودية التي قد يقع فيها خطأ أو يتولد عـنها استثناء ووضعها في كتل try.

2) كتابة الكتل catch لكل نوع من الخطأ من الممكن وقوعـه في الكتلة try.

أنظر إلى هذه الأسطر من الكـود التي تبين لك البناء العظمي الأساسي للاستثناءات:

try 
{
function();
function();
}
catch(logic error/*kind of exception*/)
{
// do some Action
}
catch(bad allocation of memory)
{
//do some function
}

سنقوم الآن بكتابة مثال كـودي بسيط وهـو عبارة عـن مثال سنقوم بمعالجتها طيلـة فترة كتابة هذا الموضوع ، أنظر إلى هذا المثال:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
//////////////////////////////////
using namespace std;
/////////////////////////////////

void readIntegersFile(const string& fileName,vector<int>& Integers)
{
int tmp;
fstream file;
file.open(fileName.c_str());
while(file >> tmp)
Integers.push_back(tmp);
}
//////////////////////////////
int main()
{
const string s="numbers.txt";
vector<int> vecInt;
readIntegersFile(s , vecInt);
for(vector<int>::const_iterator ci
=vecInt.begin();
ci !=vecInt.end();ci++)
cout << *ci << "\t";
cout << endl;
return 0;
}

الدالة readIntegersFile تقرأ محتـويات ملف ما وتضع جميع هذه المحتويات في متجـه كامل ، وهي تستقبل اسم الملف الموجود فيه أعداد الـ Integer والمتجـه الذي يريد المستخدم وضع الأرقام فيـه

لم يتم تضمين معالجـة الاستثناءات في هذا الكـود .. دعـنا الآن نقوم بتضمين هذه الأوامر.

في البداية نضمن هذه المكتبـة:

#include <exception>

بعد ذلك نعدل الدالة readIntegersFile حتى تكون قادرة على رمي أخطاء عـند حصولها.

void readIntegersFile(const string& fileName,vector<int>& Integers)
{
int tmp;
fstream file;
file.open(fileName.c_str());
if (file.fail())
throw exception();
while(file >> tmp)
Integers.push_back(tmp);
}

لقد زدنا في الكـود كلمـة throw في حال فشل البرنامج في فتح الملف ، هذه الكلمـة سترمي كائن من النوع exception ليلتقطه مقطع كـودي آخر. قبل أن نتحدث عـن هذا المقطع من الكـود .. فعلينا في البداية أن نتحدث عـن الكتلة try والتي سيتم فيها تجريب الدالة readIntegersFile وفي حال رميها للاستثناء فإن مقطعاً آخر وهـو الكتلة catch ستلتقط هذا الكائن ... من الواضح أن التعديل هـنا وإضافة هذه الكتل الجديد سيتم في الدالة main ، أنظر إلى الدالة بعد التعديل:

int main()
{
const string s="numbers.txt";
vector<int> vecInt;
try {
readIntegersFile(s , vecInt);
} catch(const exception& e)
{
cerr << e.what();
}
for(vector<int>::const_iterator ci
=vecInt.begin();
ci !=vecInt.end();ci++)
cout << *ci << "\t";
cout << endl;
return 0;
}

لاحظ أننا وضعـنا استدعاء الدالة readIntegersFile داخل كتلة try لأنه هـو المقطع الكـودي الذي نتوقع حدوث خطأ فيـه .. طبعاً يجب عليك أن تعلم أننا بإمكاننا وضع الكثير من الأوامر والتعليمات داخل الكتلة try ... بعد ذلك مباشرة وضعـنا الكتلة catch والتي ستلتقط الاستثناء الذي سيحصل حينما لا يتم فتح الملف في الدالة readIntegersFile وستقوم بمعالجتـه من خلال طباعـة نوع الخطأ بواسطـة استدعاء الدالة what من الكائن e وهـو من الفئة exception .

في هذا المثال نقول أن نوع الاستثناء هـو من النوع exception ... تابع الفقرة التالية لمزيد من التعليمـات.

أنواع الاستثناءات:

في المثال السابق قمنا بإلقاء استثناء من النوع exception .. الآن سنقوم بتغيير السطر الذي يحتوي الكلمة throw في الدالة readIntegersFile بالسطر التالي:

throw 5;

لو فكرت قليلاً ستجد أنه لن يصبح بإمكان الكتلة catch إلتقاط هذا النوع من الأخطاء لأنها تستقبل الاستثناءات من النوع exception فقط ... لذلك فيجب عليك إبدالها بهذه الكتلة الجديدة:

catch (int e)
{
cerr << "Faild Opening file" << endl;
exit(1);
}

هذه الكتلة تستطيع الآن إلتقاط الاستثناء الذي ترميـه الدالة readIntegersFile في حال حصول خطأ مـا.

يتبع.......

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

يعطيك ألف عافية على الدرس المفيد وانتظر التكملة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

إستمر وبارك الله فيك

ولكن أرجو أن يكون من بين الدروس تطبيقات على exception

ونأخذ مثال عملي ونناقشة

لا ني سئمت من هذه الجملة

cerr<<e.what();

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .