Muhammad Aladdin

المشرفون
  • عدد المشاركات

    2,492
  • تاريخ الانضمام

  • تاريخ اخر زياره

السمعه بالموقع

884 ممتاز جدا

عن Muhammad Aladdin

  • الرتبة
    مشرف قسمي C/Cpp و Windows API
  • تاريخ الميلاد 06/19/1985

حقول إضافية

  • الشهادة لا إله إلا الله محمد رسول الله

معلومات الملف الشخصي

  • الجنس ذكر
  • الدولة : الدولة الإسلامية
  • اهتمامات Operating Systems & Compilers
  1. السطر: Rectangle() = default ;يعنى انك تريد من المترجم ان يقوم بتوليد كود المشيد الإفتراضي بدلا من ان تكتبه بنفسك، وهو يماثل عدم وجود أى مشيد داخل الفئه أو ان تكتب مشيد ذات محتوى فارغ (أى لا يقوم بفعل اى شئ).   هذا الكود يعمل مع مترجمات C++11 فما بعد.       و الله ولي التوفيق
  2. "الكائنات الثابته" لها اكثر من معني، فقد تكون كائنات معرفة داخل فئه أو داخل دالة و يوجد اختلاف بينهم، أيضا الدوال الثابته هى التى يتم تعريفها داخل الفئه و يتم تحديد انها const و هى لا تقوم بتغيير حالة الكائن التى يتم إستخدامها منه.   الكائنات الثابته داخل الدوال: عند التصريح عنها لابد من وضع قيمة افتراضية لها كالتالي: struct bag{ int value; bag() : value(0) {} bag(int i) : value(i) {}};int main(){ //const int i; // ERROR: incomplete definition const int i2 = 10; // OK const int i3(); // ERROR: it thinks that i3 is a function // that return const int and takes no argument const bag o; // OK: calling default constructor const bag o2(); // ERROR: it thinks that o2 is a function // that return const bag and takes no argument const bag o3(7); // OK: calling overloaded constructor}الكائنات الثابته داخل الفئات: هذه الشرح فيها يطول لأن لها حالات بين نوع مركب و نوع أولي (و حتى النوع الأولي إما مشتق من رقم صحيح أو غير ذلك) و إذا كان تم تعريفه بـ static أو لا، يفضل أن تقرأ فضل يتحدث عن ثوابت الفئات لهذا الأمر.   الدوال الثابته: يتم تعريفها داخل الفئات ليتم الإعلام انها لا تغير من حالة الكائن و تستخدم مع الكائنات العاديه و هى الوحيده التى يمكن استدعائها من كائن معرف بأنه ثابت: #include <iostream>using namespace std;struct bag{ bag() : value(0) {} bag(int i) : value(i) {} void set_value(int i) { value = i; } int get_value() const { return value; } private: int value;};int main(){ bag b(10); cout << "b = " << b.get_value() << endl; b.set_value(15); cout << "b = " << b.get_value() << endl; const bag b2(13); cout << "b2 = " << b2.get_value() << endl; // b2.set_value(17); // ERROR: b2 has type 'const bag' and set_value is not marked const}و الله ولي التوفيق
  3. لغز بسيط

    الكود المكتوب ينتج unspecified behavior و ذلك لأن ترتيب الحصول على نتيجة الدالة inci يحدده المترجم، أنظر هذا المثال.     و الله ولي التوفيق
  4. دالة لتحويل double إلى money string

    هى أحد الإضافات الجديدة للإصدار C++11.     و الله ولي التوفيق
  5. طلب مساعدة في كتابة كود برمجي

    أنظر موضوع تمرين على استخدام القوائم بإستخدام ++C     و الله ولي التوفيق
  6. قراءة شطر من السطر

      أنظر شرح الدالة و المثال موجود فى أخر الشرح     و الله ولي التوفيق
  7. إستخدام مصفوفة كجزء من مصفوفة

    لغة C لا تحتوى على مرجع و لنها تحتوى على المؤشرات، لذا لا يمكن.     و الله ولي التوفيق
  8. ما هي HLA ?

    هو Assembler و كان الهدف منه تعليم مبرمجي اللغات عالية المستوى لغة الأسمبلي بشكل مبسط، يمكنك القراءة عنه من هنا.   ملحوظة: إن اردت تعلم الأسمبلي بشكل جيد فقم بتحميل نفس الكتاب - The Art of Assembly Language - نسخة 16 بت، حيث فيه يستخدم كود الأسمبلي فعليا و ليس HLA.       و الله ولي التوفيق
  9. ترتيب بيانات قائمة عادية

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

    عندما كتبت هذا السؤال كنت أعلم ان القليل من سيقوم بالرد عوضا عن الحل لأن مثل هذه الأسئلة قلما تحتاج إليها، و لكن المشكلة هنا ليست فى احتياجك إليها من عدمه و لكن المشكلة تكمن فى ان فهمك الراسخ لبعض الأساسيات أمر هام جدا و هو ما اغلبنا يقوم بتجاوزه او الأسوء ان اغلب الكتب البرمجيه - إن لم يكونوا جميعهم - يتجاوزوا عن شرحهم. فإن كنت درست ++C لفتره طويله فستعرف ما اتكلم عنه من خلال قرائتك للأسطر التالية.   عندما نتكلم عن المصفوفات فأغلب ما تجد نفسك تتعامل معه هو المصفوفات الديناميكية، لأنها فى النهايه مؤشر ذات نوع محدد يمكنك تحويله لمؤشر ذات نوع أخر و التلاعب به كما تشاء، و لكن المصفوفات العاديه - التى توضع فى الـ stack - قليل ما يتم التلاعب بها.   قبل ان اضع الحل لابد ان تفهم كيفية عمله، فى المعتاد عندما تقابل الكود التالي: int* pفأنت تقرأه p هو مؤشر لقيمة أو أكثر من نوع int، و إذا سُئلت عن نوع المتغير p ستقول مؤشر لـ int، التعريف التالي: int p[7];يقرأ p هو مصفوفة من 7 عناصر بنوع int، الصعوبه هنا تكمن فى نوع المتغير p حيث العديد يجيب بأن نوع p هو int و ذلك لأنهم اعتادوا أن النوع دائما يكون تعريفه فى أقصى اليسار من المتغير - مثل المؤشرات و المراجع - و لكن من درس اللغه جيدا سيعرف ان نوع p هو مصفوفة من 7 عناصر بنوع int، و يمكنك كتابة typedef لوصف المصفوفة كالتالي: typedef int array7[7];و عند إستخدامه: array7 p;و هو يماثل نفس تعريف المصفوفة الذى نستخدمه طول الوقت.     لنأت لموضوع تحويل الأنواع، عند إستخدام المؤشرات يمكنك تحويل نوع مؤشر لنوع مؤشر أخر كالتالي: int* a = new int[10];char* p = (char*)a;كما ترى المؤشر p سيسمح لك بالتعامل مع المكان الذى يشير إليه المؤشر a على مستوى البايت[1]، و لكن ماذا سيحدث إذا تحرير و إعادة حجز الذاكره التى يشير إليها المتغير a، حينها المؤشر p أصبح تالف لأن قيمة المؤشر p هى موقع الذاكره الذى تم حجزه أول مره - الموجود بالكود - و ليس موقع المتغير a داخل الذاكره حيث إذا كان p هو موقع a بالذاكرة حينها مهما كانت عنوان الذاكره الموجود بـ a فسيكون نفس العنوان داخل p.   يمكن إستخدام مؤشر لمؤشر لإتمام هذه العملية كالتالي: int* a = new int[10];char** p = (char**)&a;إستخدام مؤشر لمؤشر هو الإسلوب الأمثل فى هذه الحالة، و لكن لازال يعيبه انه يشير لمكان محدد فإذا كان محتوى المؤشر a هو عنوان لمكان أخر فستحتاج لمستوى جديد من المؤشرات. لغة ++C لديها إضافه جميله لهذا الأمر تسمى مرجع، و المرجع يختلف كثيرا عن المؤشرات و توجد بعض الامور داخل اللغه لا يمكن تنفيذها إلا بإستخدام المراجع.   على خلاف المؤشر فالمرجع لا عنوان له، أى أنه لا يحجز مساحه بالذاكره، أنظر الكود التالي: int a = 10;int& b = a;b = 12;cout << boolalpha << (&a == &b) << endl;السبب فى ان المرجع لا عنوان له يعود ان قيمة المرجع النهائية هي قيمة المتغير الغير مرجع الذى يشير له: int a = 10;int& b = a;int& c = b;int& d = c;d = 12;cout << hex << &a << endl;cout << hex << &b << endl;cout << hex << &c << endl;cout << hex << &d << endl;فى هذا المثال سترى ان كل مرجع يشير للمرجع الذى قبله فإذا حدث و أن كان المرجع له عنوان حينها المتغيران c و d لن يشيران لقيمة المتغير a و إنما لسلسلة المراجع التى قبلهم، و لكن هذا سيصبح خاطئ لأنك حينها ستحتاج للأنواع مرجع و مرجع و لمرجع و هكذا، أى اننا اصبح لدينا مسمسى جديد للمؤشرات و لكن بإستخدام المراجع.   لهذا السبب كان المرجع لا عنوان له و بهذا اصبح مجرد مسمى أخر للمتغير الذى له عنوان و يحتوى على قيمه، و لهذا فى المثال السابق المرجع b هو نفسه المتغير a و بالتالي عند إسناد قيمة b إلى c فأنت فعليا تسند قيمة a إلى c و نفس الأمر مع d حيث أصبح هو a.   لتتأكد من ان المرجع لا عنوان له أنظر المثال  التالي: int a = 1;int b = 2;int& c = a;int& d = c;d = 10; // value of a became 10c = b; // c refer to bd = 13;cout << a << endl << b << endl;فى هذا المثال c يشير لـ a و d يشير لـ c، بعدها تم تغيير قيمة d لتصبح 10 و من تسلسل المرجع فهذا يعنى ان قيمة a أصبحت 10، بعدها تم جعل c يشير لـ b و من ثم تم تغيير قيمة d، الأن إذا كان المرجع له عنوان فإن d يشير لـ c و بالتبعيه فإن d يشير لـ b و بهذا عند تغيير قيمة d إلى 13 فإننا نغير قيمة b إلى 13.   عند تشغيل البرنامج ستجد أن قيمة a هى تغيرت دائما و هذا يعنى ان المرجع لا عنوان له.   لأن المرجع لا عنوان له لابد دائما ان يشير لشئ ما، و لهذا عند تعريفه لابد من وضع قيمه له.   هل تذكر المثال الذى استخدمنا فيه مؤشر لمؤشر، أنظر إليه الأن: int* a = new int[10];char*& p = (char*&)a;نوع المتغير p يقرأ من اليمين لليسار ليصبح مرجع لمؤشر من نوع char، لاحظ أيضا ان قيمة المتغير a لابد من ان يتم تحويلها لهذا النوع حتى تستطيع إسناده إلى p.   لنعود للمصفوفات.   عندما نقوم بتعريف مرجع فإننا نكتب النوع يليه علامة & و هذا يعطينا نوع جديد بالإسم مرجع لنوع و هذا يعنى ان المترجم عندما يرى هذه الصيغه - مرجع لنوع - فإنه يعلم انه سيقوم بربط إسم لمتغير موجود، المشكله تظهر عندما تقوم يكتابة الكود التالي: int& p[10];لنقرأ الإسم معا، p هو مصفوفة من 10 عناصر بنوع مرجع لـ int، و لكن أنتظر عناصر المصفوفه لكل منها عنوان بالذاكره فكيف يمكن إنشاء مصفوفه بعناصر كل منها مرجع و لا يوجد لها عنوان و هنا يتوقف المترجم و يظهر رسالة خطأ تشبه التاليه: arrays of references are illegalو لكن p هو متغير من نوع مصفوفه و شانه شان كافة المتغيرات و أريد ان اقوم بتعريف مرجع له فكيف أفعلها؟   لتعرف كيف تقوم بهذا الأمر إسمح لى أن أعطيك مراجعه سريعه فى تعريف المتغيرات، أنظر المثال التالي: int a, b ,c;int &ar = a, &br = b, &cr = c;int *ap, *bp, *cp;int x[10];int (*sum)(int a, int b);أما السطر الأول فيقوم بتعريف ثلاثة متغيرات من نوع int، و السطر الثاني يقوم بتعريف ثلاثة مراجع للمتغيرات التى تم تعريفها بالسطر الأول، السطر الثالث يقوم بتعريف ثلاثة مؤشرات لـ int، السطر الرابع يعرف مصفوفه بالإسم x من عشرة عناصر بالنوع int، السطر الأخير يعرف مؤشر دالة إسمه sum و يأخذ معاملين كلاهما نوعه int.   ما يهمنى هنا تذكريك بالسطر الثاني و الثالث و الأخير حيث الأوليين تم ربط علامة مالرجع و المؤشر بإسم المتغير و ليس بإسم النوع و بالمثل عندما تم تعريف إسم مؤشر الدالة فإن علامة المؤشر لإسم الدالة.   قبل أن تقفذ للإستنتاجات، الكود السابق يمكن كتابته بالشكل التالي: int (a), (b), (c);int (&ar) = a, (&br) = b, (&cr) = c;int (*ap), (*bp), (*cp);int (x)[10];int (x2[10]);int (*sum)(int a, int b);هل بدءت فى شد شعرك بعد!!   بشكل عام كل شئ بعد إسم النوع و إلى نهاية إسم المتغير يطلق عليه declarators - و هو الفصل الثامن فى توثيق اللغه - و حيث انه توجد العديد من أشكال تعريف المتغيرات فإن المترجم أحيانا يختلط عليه الأمر و لا يعرف كيف يربط بين المعاملات المستخدمه مع الإسم او لا يعرف ماذا تقصد بإستخدام لمعامل معين مع إسم معين لذا يتم إستخدام الأقواس لجعل الصيغه التى تستخدمها لا تحتمل أكثر من معني.   هل تذكر لماذا استخدمنا الأقواس مع تعريف مؤشرات الدوال؟ السبب يعود لأن إن لم تستخدم الأقواس لتغليف معامل المؤشر مع الإسم سيتم ربط علامة المؤشر مع النوع و ستعطي مسمى مختلف حيث بدلا من تعريف مؤشر دالة ستقوم بالتصريح عن دالة تعيد مؤشر.   الأن هل عرفت الهدف الذى يستخدم من أجله الأقواس فى تعريف المتغيرات (لا اعتقد انه يوجد كتاب - قراته على الاقل - يتكلم عن هذه النقطه أو بعض مما سبق).   لنعود للمصفوفات مره أخرى: هل تذكر المشكله بهذا الكود: int& p[10];أعتقد أنك تعرف الحل الان: int (&p)[10];لاحظ انك لو ضممت عدد عناصر المصفوفه داخل الأقواس كالتالي: int (&p[10]);فإن هذا التعريف يطابق التعريف الذى يصدر الخطأ لأنه فى هذه الحالة - كما التى تصدر الخطأ - يتم ربط إسم المصفوفه بعدد العناصر قبل الربط على المرجع (يمكنك تخيل العملية أنها تبدأ من إسم المتغير ثم اليمين بالكامل فاليسار و هكذا حتى يتم الإنتهاء من التعريف) و فى حاتنا هذه فيتم قراءة إسم المصفوفه يليها عدد العناصر يليها المرجع و هنا يتم ربطه على العناصر و ليس إسم المصفوفه ثم العنوان، و يقرأ p هو مصفوفه من 10 عناصر مرجعيه بنوع int.   أما التى فيها عدد العناصر خارح الأقواس فيتم قراءة الإسم و اليمين فارغ و اليسار يحتوى على علامة المرجع و بهذا يعلم المترجم ان الإسم p هو مرجع ويخرج من الأوقاس و يقرأ العناصر العشره فيعلم ان الإسم p هو مرجع لمصفوفة من عشر عناصر ثم يقرأ النوع int فيعلم ان p هو مرجع لمصفوفه من عشر عناصر بنوع int   الأن قمنا بربط كافة الأساسيات التى نحتاجها معا و بقي لنا التطبيق فى الإجابه على السؤال الأصلي:   السؤال يحدد أن المصفوفه arr و arr2 يحتلا نفس المساحه من الذاكره، لذا الأمر الإفتراضي الذى لابد ان يتطرق إلى الأذهان هو ان كلا المصفوفتين موجودين داخل union و لكن السؤال يحدد أن المصفوفه arr2 لها عدد عناصر أصغر و تبدأ من العنصر الثاني داخل المصفوفه arr و هذا يعنى اننا سنقوم بعمل إزاحة للمصفوفه arr و من ثم الحصول على مرجع بدءا من هذا العنصر و بعدد العناصر التى نحتاجها.   دعنى افصلها لك خطوه خطوه:   1- سنقوم بعمل إزاحة للمصفوفه arr للموقع المحدد، الإزاحه ليست كما تتوقع و لكن هى فقط الحصول على العنصر الذى نريد أن نجعله أول عنصر فى المصفوفه الجديده: int& item = arr[2];لاحظ ان المرجع item مربوط على العنصر ذات الترتيب الثاني فى المصفوفه arr.   2- سنقوم بتعريف مرجع للمصفوفه arr2: int (&arr2)[5];هذا التعريف غير كامل و لابد من وضع قيمه له حتى يصبح فعال.   3- سنقوم بربط المصفوفه arr2 على العنصر item بعد تحويله لنوع المصفوفه arr2: int (&arr2)[5] = ( int(&)[5] )item;صيغة النوع الذى سيتم التحويل إليه قد تكون غريبه إليك و لكن إن فكرت بها قليلا ستجدها منطقيه حيث انك تقوم بتحويل إلى مرجع لمصفوفه من 5 عناصر بنوع int و هذا ما تعنيه صيغة التحويل.   المثال بالكامل: #include <iostream>using namespace std;int main(){ int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int (&arr2)[5] = (int(&)[5])(arr[2]); cout << "arr[0]=" << arr[0]; for(int i=1; i<10; i++) cout << ", arr[" << i << "]=" << arr[i]; cout << endl; const int arr2_len = sizeof(arr2)/sizeof(int); for(int i=0; i<arr2_len; ++i) arr2[i] += 5; cout << "arr[0]=" << arr[0]; for(int i=1; i<10; i++) cout << ", arr[" << i << "]=" << arr[i]; cout << endl; cout << "arr2[0]=" << arr2[0]; for(int i=1; i<arr2_len; i++) cout << ", arr2[" << i << "]=" << arr2[i]; cout << endl;}الفكره التى طبقناها هنا تسمى بـ array view و التى تسمح لك بالتعامل مع جزء من المصفوفه كانها مصفوفه منفصله، هذه الفكره لها تطبيقات عديده مثل التعامل مع جزء من النص كأنه نص منفصل.       و الله ولي التوفيق     [1] المسمى الصحيح هنا ليس البايت و إنما الوحدة حيث ان مساحة النوع char تساوى 1، و هذا الواحد مهما كان عدد البتات به فيطلق عليه إسم الوحده و مساحة كافة أنواع اللغه تقاس بالنسبه له، فالنوع signed short يستطيع ترميز قيم ضعف التى يستطيع ترميزها النوع signed char و بالتالي فحجم النوع signed short ضعف حجم النوع signed char و حيث ان الأنواع char و signed char و unsigned char كل منهم مساحته 1 وحدة بالتالي مساحة النوع signed short و unsigned short هو 2 وحدة و هى النتيجه التى من المفترض ان يعيدها مترجمك عند إستخدام اى النوعين مع المعامل sizeof.
  11. إستخدام مصفوفة كجزء من مصفوفة

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

    يمكنك تخيل وجود مصفوفتان بنفس موقع الذاكرة و المصفوفة A تتكون من 10 عناصر و المصفوفة B تتكون من 5 عناصر، و المصفوفة B أول عنصر بها موقعه فى الذاكره مموقع العنصر الثاني فى المصفوفة A و بالتالي قيمة العنصر الأول بالمصفوفة B هى قيمة العنصر الثاني بالمصفوفة A و بالتالي تغيير تلك القيمه من اى من المصفوفتين سيؤثر على الأخرى لأنه فى النهاية القيمة موجوده بمكان واحد فى الذاكرة و لكن يتم تعديلها من خلا مصفوفتين.     و الله ولي التوفيق
  13. عنوان الموضوع بالإنجليزية سيعطى المعنى بشكل أفضل : Array view into array.   يمكنك تخيل الأمر كالتالي أنت تقف فى غرفه و هى تحتوى على العديد من الأشياء و فى يديك كاميرا تنظر من خلالها لذا فى أى لحظه ما تراه من خلال الكاميرا هو جزء من الواقع و إذا حدث ان قمت و انت تمسك الكاميرا بتغيير اى شئ فستراه من خلال الكاميرا و ايضا سيتغير داخل الغرفه و بالمثل إن تم تغيير شئ داخل الغرفه فستراه عبر الكاميرا أيضا.   فى الكود التالي: int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};نوع المصفوفة arr هو [int[10 و المطلوب هو وجود المصفوفة arr2 بحيث يكون نوعها [int[5 و أول عنصر بها هو العنصر رقم 3 بالمصفوفة arr - و قيمته 2 - بحيث عند تنفيذ الكود التالي: const int arr2_len = sizeof(arr2)/sizeof(int);for(int i=0; i<arr2_len; ++i) arr2[i] += 5;و طباعة عناصر المصفوفة arr قبل و بعد تنفيذ الكود السابق بإستخدام الكود التالي: cout << "arr[0]=" << arr[0]for(int i=1; i<10; ++i) cout << ", arr[" << 1 << "]=" << arr[i];cout << endl;تكون النتيجة: arr[0]=0, arr[1]=1, arr[2]=2, arr[3]=3, arr[4]=4, arr[5]=5, arr[6]=6, arr[7]=7, arr[8]=8, arr[9]=9arr[0]=0, arr[1]=1, arr[2]=7, arr[3]=8, arr[4]=9, arr[5]=10, arr[6]=11, arr[7]=7, arr[8]=8, arr[9]=9أيضا عند إستخدام الكود التالي: cout << "arr2[0]=" << arr2[0];for(int i=1; i<arr2_len; i++) cout << ", arr2[" << i << "]=" << arr2[i];cout << endl;يتم طباعة: arr2[0]=7, arr2[1]=8, arr2[2]=9, arr2[3]=10, arr2[4]=11يحتاج السؤال إلى معرفة أساسيات اللغه جيدا (المؤشرات و المراجع و المصفوفات) فإن لم تستطع إجابة هذا السؤال على الأقل لنفسك فعلم ان مستواك ضعيف فى أساسيات اللغه أو أنك لم تركز عليها بالقدر الذى كانت تحتاجه.       و الله ولي التوفيق
  14. السلام عليكم و رحمة الله   الموضوع هو طلب شرح Segmented Sieve of Eratosthenes، قرأت مواضيع عديده و أكواد كثيرة لها و لكن حتى الأن لا أستطيع فهمها؟!!   إن استطاع أحد أن يضع شرح لها هنــا - مع مثال بسيط إن كان بالإمكان - فجزاه الله خيرا.     و الله ولي التوفيق
  15. 1- أغلب الشركات تستخدم MSI Barcode مع منتجاتها، إقرأ المقال جيدا و سيوضح لك العديد من الأمور. 2- بالنسبة لتوليد الأرقام فبإختصار لا توجد وسيلة محدده و يمكنك إستخدام مولد أرقام عشوائية.   إقرأ المقال المشار إليه و ستعلم العديد من التفاصيل.     و الله ولي التوفيق