معالج كافة الاستثناءات
جزء من قسم Logic & Flow في رحلة C++ على Coddy — الدرس 52 من 56.
في بعض الأحيان قد يواجه برنامجك أخطاء غير متوقعة لا تتناسب مع أنواع الاستثناءات المحددة التي خططت لها. يوفر معالج catch-all الشامل catch(...) شبكة أمان تلتقط أي استثناء لم يتم التعامل معه بواسطة كتل catch الأكثر تحديداً.
يستخدم معالج "القبض على الكل" (catch-all) ثلاث نقاط (...) بدلاً من تحديد نوع استثناء معين. يجب وضعه بعد جميع كتل catch الأخرى لأن لغة C++ تتحقق منها بالترتيب:
try {
// Code that might throw various exceptions
} catch (std::invalid_argument& e) {
std::cout << "Invalid input!" << std::endl;
} catch (std::out_of_range& e) {
std::cout << "Number too large!" << std::endl;
} catch (...) {
std::cout << "An unexpected error occurred!" << std::endl;
}يعمل معالج "catch-all" كخيار احتياطي لأي نوع من الاستثناءات التي لم يتم التقاطها بواسطة الكتل البرمجية السابقة. وهذا مفيد بشكل خاص عند التعامل مع كود قد يطرح استثناءات لم تتوقعها، مما يضمن عدم انهيار برنامجك بسبب أخطاء غير متوقعة.
بينما لا يمكنك الوصول إلى التفاصيل المحددة للاستثناء في كتلة catch-all، لا يزال بإمكانك تقديم رسالة خطأ عامة وإجراء عمليات التنظيف للحفاظ على تشغيل برنامجك بسلاسة.
التحدي
سهلقم بإنشاء برنامج يوضح المعالجة الشاملة للاستثناءات باستخدام كتل catch متعددة، بما في ذلك معالج "التقاط الكل" (catch-all handler). سيختبر هذا التحدي فهمك لكيفية التعامل مع أنواع الاستثناءات المحددة والأخطاء غير المتوقعة التي لا تندرج تحت فئات محددة مسبقاً.
سيتم توفير المدخلات التالية:
- سلسلة نصية
testTypeتمثل نوع الاختبار المراد إجراؤه ("string_convert"، أو"math_operation"، أو"array_access"، أو"unknown_error") - سلسلة نصية
value1ستُستخدم كبيانات أساسية للعملية - سلسلة نصية
value2ستُستخدم كبيانات ثانوية لبعض العمليات
يجب أن يقوم برنامجك بما يلي:
- إنشاء دالة باسم
performTestتأخذ ثلاثة معاملات من نوع سلسلة نصية (string) - داخل الدالة، استخدم هيكل if-else للتعامل مع أنواع الاختبار المختلفة:
- إذا كان testType هو
"string_convert": استخدمstd::stoiلتحويل value1 إلى عدد صحيح واطبعه - إذا كان testType هو
"math_operation": قم بتحويل كل من value1 و value2 إلى أعداد صحيحة باستخدامstd::stoi، ثم اقسم value1 على value2 واطبع النتيجة - إذا كان testType هو
"array_access": أنشئ سلسلة نصية"Programming"، وقم بتحويل value1 إلى فهرس (index) عددي صحيح باستخدامstd::stoi، ثم استخدمstr.at(index)للوصول إلى الحرف الموجود في ذلك الفهرس واطبعه. تقوم الطريقة.at()تلقائياً برمي استثناءstd::out_of_rangeإذا كان الفهرس غير صالح — لا حاجة للتحقق اليدوي من الحدود - إذا كان testType هو
"unknown_error": قم برمي قيمة عددية صحيحة999 - في الدالة الرئيسية (main function)، استدعِ
performTestداخل كتلةtry - استخدم كتل
catchمتعددة لمعالجة الاستثناءات بهذا الترتيب الدقيق: - أولاً:
std::invalid_argument&لعمليات تحويل السلسلة النصية إلى رقم غير الصالحة - ثانياً:
std::out_of_range&للأرقام الكبيرة جداً أو فهرس السلسلة النصية الخارج عن الحدود - ثالثاً:
catch(...)كمعالج "التقاط الكل" لأي أنواع استثناءات أخرى
استخدم تنسيق المخرجات الدقيق التالي:
للعمليات الناجحة:
Success: [result_value]لأنواع الاستثناءات المختلفة:
Invalid argument caught
Out of range caught
Unknown exception caughtتذكر أن معالج "التقاط الكل" catch(...) يجب أن يوضع في النهاية لأن لغة C++ تتحقق من كتل catch بالترتيب. سيقوم هذا المعالج بالتقاط أي نوع من الاستثناءات لم يتم التعامل معه بواسطة كتل catch المحددة السابقة، بما في ذلك استثناء العدد الصحيح الذي تم رميه في حالة "unknown_error". يوفر معالج "التقاط الكل" شبكة أمان للأخطاء غير المتوقعة مع السماح بمعالجة محددة لأنواع الاستثناءات المعروفة.
ورقة مرجعية
يوفر معالج "القبض على الكل" catch(...) شبكة أمان تلتقط أي استثناء لم يتم التعامل معه بواسطة كتل catch المحددة.
يستخدم معالج "القبض على الكل" ثلاث نقاط (...) ويجب وضعه بعد جميع كتل catch الأخرى لأن لغة C++ تتحقق منها بالترتيب:
try {
// الكود الذي قد يطرح استثناءات متنوعة
} catch (std::invalid_argument& e) {
std::cout << "Invalid input!" << std::endl;
} catch (std::out_of_range& e) {
std::cout << "Number too large!" << std::endl;
} catch (...) {
std::cout << "An unexpected error occurred!" << std::endl;
}يعمل معالج "القبض على الكل" كخيار احتياطي لأي نوع من الاستثناءات التي لم يتم التقاطها بواسطة الكتل السابقة. بينما لا يمكنك الوصول إلى تفاصيل استثناء محددة في كتلة "القبض على الكل"، يمكنك تقديم رسائل خطأ عامة وإجراء عمليات التنظيف.
جرّب بنفسك
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
// مهام مطلوبة: اكتب الكود الخاص بك هنا - قم بإنشاء دالة performTest
int main() {
// قراءة المدخلات
string testType;
string value1;
string value2;
cin >> testType;
cin >> value1;
cin >> value2;
// مهام مطلوبة: اكتب الكود الخاص بك أدناه - قم بتنفيذ كتل try-catch واستدعاء performTest
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1المؤشرات والذاكرة
ما هو المؤشر؟معامل العنوان (Address-Of)معامل الوصول للقيمة (Dereference)المؤشرات الفارغة (Null Pointers)المؤشرات والمصفوفاتالذاكرة الديناميكية باستخدام 'new'تحرير الذاكرة باستخدام 'delete'مراجعة - تمارين على المؤشرات2المتجهات (المصفوفات الديناميكية)
مقدمة إلى std::vectorإنشاء Vectorإضافة العناصرالوصول إلى العناصرحجم الـ Vectorالتكرار باستخدام For Loopالـ Range-Based For Loopإزالة العناصرملخص - عمليات الـ Vector5مشروع: أداة المخزون
إعداد المشروعإضافة وتحديث العناصر8أساسيات معالجة الأخطاء
مقدمة في الاستثناءاتكتل 'try' و 'catch'الكلمة المفتاحية 'throw'أنواع الاستثناءات المختلفةمعالج كافة الاستثناءاتمراجعة - القسمة الآمنة