البرمجة

معالجة الاستثناءات في C++ | ما هو التعامل مع الاستثناءات في C++؟

تعد معالجة الاستثناءات في لغة C++ شرطًا خاصًا يجب على المطورين التعامل معه. في البرمجة، يعد ارتكاب الأخطاء التي تؤدي إلى ظروف غير عادية تسمى الأخطاء أمرًا طبيعيًا. وعلى العموم فإن هذه الأخطاء على ثلاثة أنواع:

  • خطأ في بناء الجملة
  • خطأ منطقي 
  • خطا وقت التشغيل

ما هو التعامل مع الاستثناءات في C++؟ 

معالجة الاستثناءات في لغة C++ هي آلية تسمح للبرنامج بالتعامل مع أخطاء وقت التشغيل والمواقف الاستثنائية بطريقة منظمة ومضبوطة. 

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

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

يتم بعد ذلك اكتشاف الاستثناء الذي تم طرحه بواسطة كتل “التقاط” مناسبة، حيث يمكن للبرنامج معالجة الخطأ بأمان.

فيما يلي مخطط أساسي لكيفية عمل معالجة الاستثناءات في C++:

  1. طرح استثناء:
    عند حدوث خطأ فادح أثناء تنفيذ البرنامج، يمكنك استخدام throwالعبارة لرفع استثناء. عادةً ما يستخدم الكائن كوسيطة، والتي تكون بمثابة تمثيل للخطأ.
1 2 3 4 5 6 7#include <iostream>   void someFunction (int value) {     if (value == 0)         throw std: runtime_error (“Error: Division by zero!”);     // … other code … }
  • التقاط استثناء:
    لالتقاط استثناء، يمكنك استخدام tryكتلة. يتم وضع الكود الذي قد يؤدي إلى حدوث استثناء داخل tryالكتلة. إذا تم طرح استثناء داخل tryالكتلة، فسينتقل البرنامج فورًا إلى catchالكتلة المقابلة.
1 2 3 4 5 6 7 8 9 10 11int main () {     try {         int x = 10;         int y = 0;         some Function (x / y);     } catch (const std: runtime_error& e) {         std: cout << “Exception caught: ” << e. what () << std: endl;     }     // … other code …     return 0; }
  • معالجة الاستثناء:
    تتعامل الكتلة catchمع الاستثناء الذي تم اكتشافه. وهو يحدد نوع الاستثناء الذي يمكنه التقاطه بين قوسين، متبوعًا بكتلة من التعليمات البرمجية التي تعالج الحالة الاستثنائية.
  • كتل التقاط متعددة:
    يمكن أن يكون لديك catchكتل متعددة للتعامل مع أنواع مختلفة من الاستثناءات. سيتم تنفيذ الكتلة الأولى catchالتي تطابق نوع الاستثناء الذي تم طرحه، وسيتم تخطي الكتل الأخرى.
1 2 3 4 5 6 7 8 9try {     // code that may throw exceptions } catch (const SomeExceptionType& e) {     // handle SomeExceptionType } catch (const AnotherExceptionType& e) {     // handle AnotherExceptionType } catch (…) {     // handle any other exception that is not caught by previous catch blocks }
  • أمان الاستثناء:
    يشير أمان الاستثناء إلى مفهوم ضمان بقاء حالة البرنامج متسقة حتى في حالة طرح استثناء. تعد كتابة التعليمات البرمجية الآمنة للاستثناء أمرًا ضروريًا لمنع تسرب الموارد والحفاظ على سلامة البيانات.

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

عندما لا يحدث أي شرط استثناء، سيتم تنفيذ التعليمات البرمجية بشكل عادي. سيتم تجاهل المعالجات.

مثال بسيط لفهم المعالجة الاستثنائية في C++

#include <iostream>

int main () {

    try {

        // Code that may throw an exception

        int numerator = 10;

        int denominator = 0;

        int result = numerator / denominator;

        std: cout << “Result: ” << result << std: endl;

    }

    catch (const std: exception& e) {

        std: cout << “Exception occurred: ” << e. what () << std: endl;

    }

    return 0;

}

في هذا المثال، قد يؤدي بسط/مقام عملية القسمة إلى استثناء std: exception عندما يكون المقام صفرًا. تحتوي كتلة المحاولة على التعليمات البرمجية التي قد تطرح استثناءً، وتلتقط كتلة الالتقاط الاستثناء وتتعامل معه بشكل مناسب.

لماذا التعامل مع الاستثناءات؟ 

تعد معالجة الاستثناءات مفهومًا حاسمًا في البرمجة يسمح للمطورين بالتعامل مع المواقف غير المتوقعة أو الاستثنائية التي قد تحدث أثناء تنفيذ البرنامج. 

وغالبا ما يشار إلى هذه الحالات الاستثنائية باسم “الاستثناءات”. فيما يلي بعض الأسباب التي تجعل معالجة الاستثناءات مهمة:

  • إدارة الأخطاء: عندما يواجه أحد البرامج خطأً أو حالة غير متوقعة، دون معالجة الاستثناءات، فقد يتعطل أو ينتج عنه نتائج غير صحيحة. توفر معالجة الاستثناءات طريقة منظمة للتعامل مع الأخطاء وتسمح للمطورين بالتعامل معها بأمان.
  • المتانة: معالجة الاستثناءات تعزز من قوة البرنامج. من خلال التقاط الاستثناءات والتعامل معها، يمكن للمطورين منع البرنامج بأكمله من الإنهاء فجأة وتزويد المستخدمين برسائل خطأ ذات معنى، مما يجعل البرنامج أكثر سهولة في الاستخدام.
  • فصل الاهتمامات: تفصل معالجة الاستثناءات بوضوح بين تدفق البرنامج العادي وأخطاء تشغيل التعليمات البرمجية. يؤدي هذا الفصل إلى تسهيل قراءة التعليمات البرمجية وفهمها وصيانتها.
  • التصحيح: معالجة الاستثناءات تساعد في تصحيح التعليمات البرمجية. عند طرح استثناء، يمكن للبرنامج تسجيل تفاصيل حول الخطأ، مما يساعد المطورين على تحديد السبب الجذري للمشكلة وإصلاحه.
  • الاسترداد الجميل: في حالات معينة، يمكن للبرامج التعافي من الاستثناءات ومتابعة التنفيذ بدلاً من التعطل. على سبيل المثال، يمكن لخادم الويب اكتشاف استثناء ناتج عن خطأ من جانب العميل والاستجابة برمز خطأ HTTP مناسب بدلاً من إيقاف التشغيل.
  • استقرار البرنامج: من خلال التعامل مع الاستثناءات بشكل مناسب، يمكن للمطورين التأكد من بقاء البرنامج مستقرًا وموثوقًا حتى عند مواجهة ظروف أو مدخلات غير متوقعة.
  • العمليات الآمنة من الفشل: تعتبر معالجة الاستثناءات ذات أهمية خاصة عند التعامل مع العمليات الهامة مثل إدخال/إخراج الملفات أو اتصالات الشبكة أو معاملات قاعدة البيانات. تتيح معالجة الاستثناءات بشكل صحيح إمكانية التراجع عن المعاملات أو تنفيذ مهام التنظيف الضرورية الأخرى للحفاظ على سلامة البيانات.
  • النمطية: تسمح معالجة الاستثناءات بالتصميم المعياري وتعزز إمكانية إعادة استخدام التعليمات البرمجية. يمكن للوظائف أو الأساليب طرح استثناءات، ويمكن لرمز الاتصال التقاطها والتعامل معها وفقًا لذلك.

الكلمات الرئيسية الأساسية في معالجة الاستثناءات

تقع معالجة الاستثناءات في لغة C++ حول الكلمات الرئيسية الثلاث التالية: 

  • يرمي
  • يمسك
  • يحاول

ما هي محاولة رمي الصيد في C++؟

في C++، tryو throw، و، catchهي كلمات رئيسية تستخدم لمعالجة الاستثناءات. تتيح معالجة الاستثناءات للمطورين التعامل مع الأخطاء أو المواقف الاستثنائية بأمان وتوفير طريقة منظمة لإدارة الحالات غير المتوقعة أثناء تنفيذ البرنامج.

وفيما يلي شرح موجز لكل كلمة رئيسية:

  • محاولة: يتم تضمين التعليمات البرمجية التي قد تثير استثناءً في كتلة المحاولة. تأتي بعده كتلة صيد واحدة أو أكثر. يبحث البرنامج عن كتلة الالتقاط التي تطابق كتلة المحاولة عند طرح استثناء داخل كتلة المحاولة من أجل معالجة الاستثناء.
  • رمي: لرفع أو طرح استثناء بشكل صريح، استخدم الكلمة الأساسية رمي. في كتلة المحاولة، يتم استخدامها بشكل متكرر عند ظهور ظروف استثنائية. يخرج عنصر التحكم من كتلة المحاولة عند استيفاء بيان الرمي لتحديد موقع كتلة التقاط مناسبة لمعالجة الاستثناء.
  • catch: catchتتبع الكتلة الكتلة tryويتم استخدامها لالتقاط الاستثناءات ومعالجتها. يحتوي على تعليمات برمجية يتم تنفيذها عند طرح نوع معين من الاستثناءات داخل tryالكتلة المرتبطة. يمكن استخدام كتل متعددة catchلأنواع استثناءات مختلفة.
1 2 3 4 5 6 7 8 9 10try {     // Code that might throw an exception     // If an exception is thrown, control jumps to the corresponding catch block } catch (ExceptionType1 e) {     // Code to handle ExceptionType1 } catch (ExceptionType2 e) {     // Code to handle ExceptionType2 } catch (…) {     // Catch-all block to handle any other unhandled exceptions (optional) }

كيف تعمل محاولة الالتقاط في C++؟

في C++، تتم معالجة الاستثناءات باستخدام try-catchالآلية. يسمح لك بالتقاط ومعالجة الاستثناءات التي تحدث أثناء تنفيذ البرنامج. تحتوي الكتلة tryعلى التعليمات البرمجية التي قد تؤدي إلى استثناء، وتتعامل مع الاستثناء في حالة حدوثه. وإليك كيف يعمل:

  • الكود الذي قد يطرح استثناءً موجود داخل tryكتلة. في حالة حدوث استثناء داخل هذه الكتلة، يتم إيقاف تنفيذ التعليمات البرمجية داخل tryالكتلة على الفور، ويبحث البرنامج عن catchكتلة مطابقة للتعامل مع الاستثناء.
  • بعد طرح استثناء، يبحث البرنامج عن catchكتلة مطابقة. الكتلة المطابقة catchهي تلك التي يمكنها التعامل مع نوع الاستثناء المحدد الذي تم طرحه. إذا تم العثور على كتلة مطابقة catch، فسيتم تنفيذ التعليمات البرمجية الموجودة داخل تلك الكتلة.
  • إذا لم catchيتم العثور على كتلة مطابقة ضمن النطاق الحالي، يتحرك البرنامج لأعلى مكدس الاستدعاءات، ويبحث عن catchالكتلة المناسبة في وظائف الاستدعاء. تستمر هذه العملية حتى catchيتم العثور على كتلة مطابقة أو حتى يصل البرنامج إلى المستوى الأعلى للبرنامج (أي main () الوظيفة).
  • بمجرد catchالعثور على كتلة مطابقة، يتم تنفيذ التعليمات البرمجية الموجودة داخل تلك الكتلة، ويستمر البرنامج في التنفيذ من النقطة التي تلي الكتلة مباشرة try-catch.

فيما يلي مثال لتوضيح استخدام try-catch:

#include <iostream>

int main () {

    try {

        // Code that might throw an exception

        int num1, num2;

        std: cout << “Enter two numbers: “;

        std: cin >> num1 >> num2;

        if (num2 == 0) {

            throw std: runtime_error (“Divide by zero exception”);

        }

        int result = num1 / num2;

        std: cout << “Result: ” << result << std: endl;

    }

    catch (const std: exception& e) {

        // Exception handling code

        std: cout << “Exception caught: ” << e. what () << std: endl;

    }

    return 0;

}

مثال 1: كتلة التعليمات البرمجية المتعددة

#include <iostream>

int main () {

    try {

        // Code that may throw an exception

        int numerator = 10;

        int denominator = 0;

        int result = numerator / denominator;

        std: cout << “Result: ” << result << std: endl;

    }

    catch (const std: runtime_error& e) {

        std: cout << “Runtime error occurred: ” << e. what () << std: endl;

    }

    catch (const std: exception& e) {

        std: cout << “Exception occurred: ” << e. what () << std: endl;

    }

    return 0;

}

لقد أضفنا هنا catchكتلة إضافية للتعامل مع نوع معين من الاستثناءات، std: runtime_errorقبل التقاط الاستثناء الأكثر عمومية std: exception. يجب اكتشاف أنواع الاستثناءات المحددة قبل الأنواع الأكثر عمومية.

example2: طرح استثناء مخصص

#include <iostream>

#include <stdexcept>

void checkAge (int age) {

    if (age < 0) {

        throw std: invalid_argument (“Age cannot be negative.”);

    }

    else if (age < 18) {

        throw std:out_of_range (“You must be at least 18 years old.”);

    }

    else {

        std: cout << “Access granted.” << std: endl;

    }

}

int main () {

    try {

        int userAge = 15;

        checkAge(userAge);

    }

    catch (const std: exception& e) {

        std: cout << “Exception occurred: ” << e. what () << std: endl;

    }

    return 0;

}

في هذا المثال، checkAgeتطرح الدالة استثناءات مخصصة، std: invalid_argumentبناءً std:out_of_rangeعلى قيمة العمر المتوفرة. tryتستدعي الكتلة الوظيفة، checkAgeوإذا تم طرح استثناء، فسيتم اكتشافه ومعالجته في الكتلة catch.

كيفية استخدام حاول الالتقاط في C ++؟

تعد Try-catch كلمة رئيسية مهمة أثناء أداء الظروف الاستثنائية.
في كتلة المحاولة، تطرح الكلمة الأساسية “رمي” استثناءً عندما يكتشف الكود وجود مشكلة، مما يتيح لنا إنشاء خطأ مخصص.
الآن تأتي الكلمة الأساسية “catch” في الصورة، أي أن الكلمة الأساسية “catch” تسمح لك بتحديد كتلة من التعليمات البرمجية ليتم تنفيذها في حالة حدوث خطأ في كتلة المحاولة.

كيف يمكنك التقاط الاستثناءات في C++؟

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

كيفية طرح استثناء في C++؟

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

عندما يتم طرح استثناء، سيتوقف البرنامج عن تنفيذ الكتلة الحالية من التعليمات البرمجية ويبدأ البحث عن معالج الاستثناء المناسب (كتلة الالتقاط) للتعامل مع الاستثناء.

لرمي استثناء في C++، عادةً ما تتبع الخطوات التالية:

تحديد فئة استثناء مخصصة (اختياري):
يمكنك إنشاء فئة استثناء مخصصة خاصة بك عن طريق الوراثة من فئة std: exception القياسية أو أي من فئاتها المشتقة. هذه الخطوة اختيارية، حيث يمكنك أيضًا استخدام فئات الاستثناءات القياسية التي توفرها مكتبة C++ القياسية.

رمي الاستثناء:
استخدم الكلمة الأساسية throw متبوعة بكائن الاستثناء الذي تريد طرحه. إذا قمت بإنشاء فئة استثناء مخصصة، فيمكنك إنشاء كائن من تلك الفئة وتمريره إلى عبارة الرمي.

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

فيما يلي مثال لكيفية طرح استثناء والتقاطه في C++:

#include <iostream>

// Custom exception class (optional)

class MyException: public std: exception {

public:

    virtual const char* what () const noexcept override {

        return “My custom exception occurred!”;

    }

};

int main () {

    try {

        int age;

        std: cout << “Enter your age: “;

        std: cin >> age;

        if (age < 0) {

            // Throw a custom exception

            throw MyException ();

        }

        // Other code that may throw exceptions

        // …

    } catch (const MyException& ex) {

        std: cout << “Caught custom exception: ” << ex. what () << std: endl;

    } catch (const std: exception& ex) {

        // Catch other exceptions derived from std: exception

        std: cout << “Caught standard exception: ” << ex. what () << std: endl;

    } catch (…) {

        // Catch any other unhandled exceptions (not recommended, but can be useful for debugging)

        std: cout << “Caught unknown exception.” << std: endl;

    }

    return 0;

}


في هذا المثال، إذا أدخل المستخدم عمرًا سلبيًا، فسيتم طرح كائن MyException، وسيتم التقاطه بواسطة كتلة الالتقاط المقابلة.

الاستثناءات القياسية لـ C++

في C++، يمكنك إنشاء الاستثناءات الخاصة بك المعرفة من قبل المستخدم لمعالجة حالات خطأ محددة في التعليمات البرمجية الخاصة بك. تسمح لك الاستثناءات المعرفة من قبل المستخدم بتحديد أنواع الاستثناءات المخصصة التي ترث من std: exceptionفئة C++ القياسية أو أي من فئاتها المشتقة. يمكّنك هذا من طرح أنواع استثناءات محددة تمثل حالات خطأ مختلفة والتقاطها.

فيما يلي دليل خطوة بخطوة حول كيفية تحديد واستخدام الاستثناءات المعرفة من قبل المستخدم في C++:

الخطوة 1: تحديد فئة الاستثناء المخصصة الخاصة بك

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15#include <exception> #include <string>   class MyException: public std: exception { public:     MyException (const std: string& message): message_(message) {}       // Override the what () method to provide error description     const char* what () const noexcept override {         return message_.c_str ();     }   private:     std: string message_; };

الخطوة 2: طرح الاستثناء المعرف من قبل المستخدم
يمكنك طرح الاستثناء المخصص في التعليمات البرمجية الخاصة بك عند مواجهة حالة خطأ معينة. على سبيل المثال:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19#include <iostream>   double divideNumbers (double numerator, double denominator) {     if (denominator == 0) {         throw MyException (“Division by zero is not allowed.”);     }     return numerator / denominator; }   int main () {     try {         double result = divideNumbers (10.0, 0.0);         std: cout << “Result: ” << result << std: endl;     } catch (const MyException& ex) {         std: cout << “Error: ” << ex. what () << std: endl;     }       return 0; }

في هذا المثال، قمنا بتعريف MyExceptionفئة مخصصة واستخدمناها لطرح استثناء عند القسمة على صفر في الدالة divideNumbers. في mainالدالة، نلتقط الاستثناء ونتعامل معه عن طريق طباعة رسالة الخطأ.

الخطوة 3: التعامل مع الاستثناء المحدد من قبل المستخدم
عند طرح استثناء، يمكنك التقاطه باستخدام tryكتلة ومعالجته باستخدام catchكتلة مقابلة. في هذا المثال، نلتقط MyExceptionرسالة الخطأ الخاصة بها ونطبعها باستخدام what () الطريقة.

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

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

ما هي الاستثناءات القياسية لـ C++؟

توفر استثناءات C++ القياسية قائمة بالاستثناءات القياسية المحددة في <exception> والتي يمكننا استخدامها في برامجنا.
يتم ترتيب هذه الاستثناءات في التسلسل الهرمي لفئة الوالدين والطفل:

الاستثناءات المحددة من قبل المستخدم 

في C++، يمكنك إنشاء الاستثناءات الخاصة بك المعرفة من قبل المستخدم لمعالجة حالات خطأ محددة في التعليمات البرمجية الخاصة بك. تسمح لك الاستثناءات المعرفة من قبل المستخدم بتحديد أنواع الاستثناءات المخصصة التي ترث من std: exceptionفئة C++ القياسية أو أي من فئاتها المشتقة. يمكّنك هذا من طرح أنواع استثناءات محددة تمثل حالات خطأ مختلفة والتقاطها.

فيما يلي دليل خطوة بخطوة حول كيفية تحديد واستخدام الاستثناءات المعرفة من قبل المستخدم في C++:

الخطوة 1: تحديد فئة الاستثناء المخصصة الخاصة بك

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15#include <exception> #include <string>   class MyException: public std: exception {public:     MyException (const std: string& message): message_(message) {}       // Override the what () method to provide error description     const char* what () const noexcept override {         return message_.c_str ();     }   private:     std: string message_; };

الخطوة 2: طرح الاستثناء المعرف من قبل المستخدم
يمكنك طرح الاستثناء المخصص في التعليمات البرمجية الخاصة بك عند مواجهة حالة خطأ محددة. على سبيل المثال:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19#include <iostream>   double divideNumbers (double numerator, double denominator) {    if (denominator == 0) {  throw MyException (“Division by zero is not allowed.”); }     return numerator / denominator;} int main () { try { double result = divideNumbers (10.0, 0.0);  std: cout << “Result: ” << result << std: endl;    } catch (const MyException& ex) {  std: cout << “Error: ” << ex. what () << std: endl;    }       return 0;}

في هذا المثال، قمنا بتعريف MyExceptionفئة مخصصة واستخدمناها لطرح استثناء عند القسمة على صفر في الدالة divideNumbers. في mainالدالة، نلتقط الاستثناء ونتعامل معه عن طريق طباعة رسالة الخطأ.

الخطوة 3: التعامل مع الاستثناء المحدد من قبل المستخدم
عند طرح استثناء، يمكنك التقاطه باستخدام tryكتلة ومعالجته باستخدام catchكتلة مقابلة. في هذا المثال، نلتقط MyExceptionرسالة الخطأ الخاصة بها ونطبعها باستخدام what () الطريقة.

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

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

يقودنا هذا إلى نهاية مدونة معالجة الاستثناءات في لغة C++. نأمل أن يساعدك هذا على تحسين مهاراتك في لغة C++. 

لمعرفة المزيد حول البرمجة والمفاهيم الأخرى ذات الصلة، قم بمراجعة الدورات التدريبية في  Great Learning Academy . 

اغتنم الفرص التي تنتظرك من خلال مجموعتنا الديناميكية من الدورات المجانية. سواء كنت مهتمًا بالأمن السيبراني أو الإدارة أو الحوسبة السحابية أو تكنولوجيا المعلومات أو البرامج، فإننا نقدم مجموعة واسعة من المجالات الخاصة بالصناعة. 

اكتسب المهارات والخبرات الأساسية لتزدهر في المجال الذي اخترته وتطلق العنان لإمكاناتك الكاملة.

المصدر: mygreatlearning

قد يهمك:

متجر سلة

الإنترنت المظلم

شركة كتابة محتوى

أفضل شركة استضافة مواقع

سيو

اشتراك نتفلكس

الذكاء الاصطناعي

مقالات ذات صلة

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *