الفريق العربي للهندسة العكسية

نسخة كاملة : 2.11 التحويلات Conversions
أنت حالياً تتصفح نسخة خفيفة من المنتدى . مشاهدة نسخة كاملة مع جميع الأشكال الجمالية .

R333T

[صورة مرفقة: dark.jpg]
رحلة في عالم البرمجة: إتقان أساسيات البرمجة وتطبيقاتها باستخدام لغة C++

https://www.youtube.com/playlist?list=PL...qaKxmAKHrq


# الفصل 0 : تمهيد # الفصل 1 : # الفصل 2 : 


التحويلات Conversions.
رأينا أنه لا يمكننا إضافة الرموز مباشرة أو مقارنة double بـ int.
ومع ذلك، يوفر C++ طرقًا غير مباشرة للقيام بكليهما.
عند الحاجة إليها في التعبير، يتم تحويل char إلى int وتحويل int إلى double.
على سبيل المثال:
char c = 'x';
int i1 = c; // i1 gets the integer value of c
int i2 = c + 1000; // i2 gets the integer value of c added to 1000
double d = i2 + 7.3; // d gets the floating-point value of i2 plus 7.3


هنا، i1 يحصل على القيمة 120، وهي القيمة الصحيحة للحرف 'x' في مجموعة الرموز الشائعة المكونة من 8 بت، ASCII.
هذه طريقة بسيطة للحصول على التمثيل العددي لحرف.
للحصول على قيمة i2، يتم إجراء الإضافة باستخدام الحساب الحسابي الصحيح ويعطي القيمة 1120.
يُقال إن ال char تم ترقيته إلى int قبل الإضافة.
بالمثل، عندما يكون هناك مزيج من القيم العائمة والقيم الصحيحة، يتم ترقية الأعداد الصحيحة إلى العائمة لإعطاء نتائج غير متوقعة.
هنا، d يحصل على القيمة 1127.3.

تحويلات البيانات تنقسم إلى نوعين
• توسيع widening: التحويلات التي تحتفظ بالمعلومات، مثل char إلى int.
• تضييق narrowing: التحويلات التي قد تفقد المعلومات، مثل int إلى char.

يقوم التحويل التوسيعي بتحويل قيمة إلى قيمة متساوية أو إلى أفضل تقريب لقيمة متساوية.
عادةً، التحويلات التوسيعية تكون نعمة للمبرمج وتبسط كتابة الشفرة.
لسوء الحظ، يسمح C++ أيضًا بالتحويلات التضييقية الضمنية.
بالتضييق، نعني أن القيمة يتم تحويلها إلى قيمة من نوع آخر لا تتساوى مع القيمة الأصلية.
فكر في int و char.
التحويلات من char إلى int لا تواجه مشاكل مع التضييق.
ومع ذلك، يمكن لـ char أن تحتوي فقط على قيم صحيحة صغيرة جدًا.
غالبًا، يكون char بحجم 8 بت وهذا يعني بايت واحد، بينما يكون int بحجم 4 بايتات لذا حجم int هو 4 × حجم char لذلك مثل هذا سوف يفقد تلك القيمة:
char: 0000 0000
int:  0000 0000 0000 0000 0000 0000 0000 0000


لا يمكننا وضع عدد كبير، مثل 1000، في char لأن الحد الأقصى لحجم char هو 255.
هذه التحويلات تسمى التضييق لأنها تضع قيمة في كائن قد يكون صغيرًا جدًا (''ضيق'') لاستيعاب كل شيء.
لسوء الحظ، التحويلات مثل double إلى int و int إلى char يتم قبولها بشكل افتراضي من قبل معظم المترجمات على الرغم من أنها تضييقية.



لماذا يمكن أن يكون هذا مشكلة؟ لأننا في كثير من الأحيان لا نشتبه أن التحويل التضييقي - الذي يدمر المعلومات - قيد التنفيذ.

فكر في:
double x = 2.7;
// ... lots of code ...
int y = x; // y becomes 2


بحلول الوقت الذي نسند فيه x إلى y قد نكون قد نسينا أن x كانت double، أو أن التحويل من double إلى int يقوم بتقليص (يقرر دائمًا القرب، نحو الصفر) بدلاً من استخدام التقريب التقليدي 4/5 (التقريب نحو العدد الصحيح الأقرب).
ما يحدث محدد تمامًا، ولكن ليس هناك شيء في y = x؛ لتذكيرنا بأن المعلومات (ال.7) تتم حذفها.
للحصول على فهم للتحويلات والسبب في أن التحويلات التضييقية يجب تجنبها، قم بالتجربة.
فكر في هذا البرنامج الذي يظهر كيفية تنفيذ التحويلات من double إلى int وتحويلات من int إلى char على جهازك:
int main()
{
    double d = 0;
    while (cin>>d) { // repeat the statements below as long as we type in numbers
        int i = d; // try to squeeze a floating-point value into an integer value
        char c = i; // try to squeeze an integer into a char
        cout << "d==" << d // the original double
        << " i=="<< i // double converted to int
        << " c==" << c // int value of char
        << " char(" << c << ")\n"; // the char
    }
}



جرب هذا
قم بتشغيل هذا البرنامج مع مجموعة متنوعة من المدخلات:
• قيم صغيرة (مثل 2 و 3).
• قيم كبيرة (أكبر من 127، أكبر من 1000).
• قيم سلبية.
• 56، 89، و 128.
• قيم غير صحيحة (مثل 56.9 و 56.2).
ستجد أن العديد من المداخل تنتج نتائج "غير معقولة" عند التحويل.
بشكل أساسي، نحن نحاول وضع غالون في وعاء باليت (حوالي 4 لتر في كوب 500 ملليلتر).

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

عندما نحتاج حقًا إلى التضييق، يمكننا استخدام narrow<T>(x) للتحقق مما إذا كان يمكن تضييق x إلى T دون فقدان المعلومات.
عندما نريد التقريب، يمكننا استخدام round_to<int>(x).
لأسباب تاريخية وعملية، تقدم C++ أربع تسميات للتهيئة:

على سبيل المثال:
int x0 = 7.8; // narrows, some compilers warn
int x1 {7.8}; // error : {} doesn’t narrow
int x2 = {7.8}; // error : ={} doesn’t narrow (the redundant = is allowed)
int x3 (7.8); // narrows, some compilers warn



تعود تسميات = و ={} إلى الأيام الأولى من C.
نستخدم التهيئة = عندما يقوم تهيئة ببساطة بنسخ مبدئها وتهيئة {} و ={} للتهيئة المعقدة أكثر وعندما
نريد حماية الوقت التشغيلي ضد التضييق.
int x = 7;
double d = 7.7;
string s = "Hello, World\n";
vector v = {1, 2, 3, 5, 8 };
pair p {"Hello",17};


نحتفظ التهيئة () بالتهيئة في حالات قليلة جدًا.

 Cafe