السلام عليكم
اريد عمل برنامج يقوم بعمليات الضرب والقسمة الخاصة بالمصفوفات
وعندما اقوم بتعرييف مصفوفة هكذا :
int m,n
int array[m][n]={0}لايقبلها المترجم
فمالحل ؟؟ هل هناك طريقة اخرى ؟
السلام عليكم
اريد عمل برنامج يقوم بعمليات الضرب والقسمة الخاصة بالمصفوفات
وعندما اقوم بتعرييف مصفوفة هكذا :
int m,n
int array[m][n]={0}لايقبلها المترجم
فمالحل ؟؟ هل هناك طريقة اخرى ؟
لا يمكنك تعريف هذه المصفوفة في ++C حيث أن m , n متحولات ...
إما أن تعرف m , n على شكل ثوابت
const int m = 100; const int n = 100;
أو أن تعرف مصفوفة ديناميكية حيث تعرف مؤشر على مصفوفة ... و بعد ذلك تحجز ديناميكيا أي أثناء الـ runtime و ليس أثناء الـ compile time كما في المصفوفات الساكنة ... و لكن أعتقد أن الأمر قد يكون صعبا عليك إذا كنت مبتدئ خصوصا إذا كانت المصفوفة ثنائية البعد و لكن سأضع لك مثالا بسطيا
بفرض أن n عدد الأسطر و m عدد الأعمدة
int m , n; cin >> n >> m; int* a = new[n*m]; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) a[j+i*n] = 0
لاحظ أننا وصلنا إلى العنصر [j] بالطريقة [j+i*n]
و هي تتعامل مع المصوفة تماما كما تخزن فالمصفوفة أكيد أنها لا تخزن في الذاكرة على شكل مربع و إنما على شكل تتالي من العناصر ... قانون الوصول إلى أي عنصر فيه هو (رقم العمود + عدد الأسطر*رقم السطر)
الشرح ليس جيدا بما فيه الكفاية ... ليس لدي الخبرة للشرح .. و لكن أرجو أن أكون قد ساعدتك ..
تم تعديل هذه المشاركة بواسطة aubada في 29 يوليو 2006 في 23:30
MAAAAAAAAAAAAAAAAAAAAAAAC
THE TORNADO
جزاك الله كل خير اخي على توضيح طريقة المصفوفة الديناميكية ، الشرح واضح جداً
اشكرك مره اخرى اخي :)
الأخ Tornado لم يقصر و لكن هناك ملاحظتين فقط ..
int *a = new int[n*m];
طبعا لا تنسى تعمل delete للدايناميك array
delete [] a
ثانيا يمكن أن تستخدم هذه الطريقه لتصفير المصفوفه ذات اتجاهين
int a[n][m]= {{0}}لكن لازم تعرف حجم المصفوفات قبلا ..
اقتباسطبعا لا تنسى تعمل delete للدايناميك arraydelete [] a
بهي معك حق ... راحت عن بالي ;)
MAAAAAAAAAAAAAAAAAAAAAAAC
مالفائدة من عملية حذف المصفوفة ؟
يا صديقي ... عند الإنشاء الديناميكي فإنك تقوم بحجز جزء من الذاكرة ... و إذا لم تقم بتحريره سيبقى محجوزا دون فائدة ... و إلا لماذا المصفوفات الديناميكية ..
ثانيا : و لست متأكدا ... من الممكن أن يبقى الجزء المحجوز في الـ RAM حتى بعد انتهاء تنفيذ برنامجك ........
MAAAAAAAAAAAAAAAAAAAAAAAC
تقوم عملية الحذف عزيزي على توفير عملية الذاكرة
يعني تخيل انك قمت بكتابة نفس كودك السابق لبرنامج عرضته لمستخدم وقام المستخدم بادخال مصفوفة ثنائية الابعاد ولكن حجمها كبير جدا مثلا 100 * 100
ثم انتهى دور المصفوفة واتيت لفقرة جديده .. انت لن تحتاج إلى هذا الكم الهائل من الحجز للذاكرة لذلك يفضل ان تقوم بمسحه باستخدام عملية []delete وعندها تزيد سرعة البرنامج
لكن تذكر ان تستخدمها بمجرد ان يكون البرنامج قد انتهى من المصفوفة
ملاحظة مهمه :
لاتعتقد انه يجب وضع عملية الحذف !!
اي انه عند تنفيذ البرنامج لاتعتقد ان المصفوفة تبقى ان لم تحذفها
بمجرد انتهاء المجال الخاص في main الداله الرأيسية ستنتهي المصفوفة نهائيا
}
المصفوفة
{
عندها انتهت المصفوفة حتى لو لم تحذفها
___________________________________________________________
مااعتقد في شرح اكثر من كذا :D
بالتوفيق

اشهد ان لا إله إلا الله وان محمدا ً رسول الله
بالتأكيد time1 ... فأي متحول يموت (يهدم) بعد الخروج من الـ scope التي تم تعريفه فيها
و لكني سمعت كلاما من البعض انه من الممكن أن يبقى الحجم المحجوز للمصفوفة الديناميكية في الـ RAM لأن المكان الذي تحجز فيها للمتحولات الديناميكية (المؤشرات) غير المكان الذي يحجز فيه للمتحولات .... ممكن توضيع إذا كنت واثق من كيفية تخزين متحولات البرنامج في stack و heap
و شكرا
MAAAAAAAAAAAAAAAAAAAAAAAC
استاذي الفاضل
The Tornado
عندما نقوم بكتابة الكود لأي برنامج ونقوم بتنفيذه فإن البرنامج يحجز مكانه في الذاكرة RAM
وطبعا هو يحجز قسمين احدهم للشفرة والاخر يسمى بمقطع البيانات وفيه تكون المتحولات
لكن مقطع البيانات كما تعرف محدود الذاكرة ولا تكفي ربما لحجز عدد كبير من البيانات لذلك نستطيع ان نستخدم ماتبقى من الذاكرة RAM وهو حجم كبير طبعا
ويسمى كما تفضلت heap من خلال الأمر new ونقوم بإعادة عناوينها باستخدام المؤشرات
كما تعلم انه احيانا يحدث عملية تسريب للذاكرة وبقاء حجم مصفوفة ديناميكية ذات حجم كبير في ذاكرة heap امر غير مقبول ,,لذلك نستخدم امر delete ولو لم نستخدمه لكان البرنامج صحيحا طبعا
ولكن لمنع تسريب الذاكرة
التوضيح :
انظر معي لهذا الكود
main()
{
int *point=new int;
*point=50;
لاحظ هنا انه تم حجز مكان في heap
من نوع صحيح واعطائة قيمة 50
نستطيع ان نجري عليها ما نشاء من عمليات مثلا: نطبعها
ثم لاحظ معي لو قمنا بالتالي
point=new int;
*point = 100;
هنا لو اردنا طباعة *point
ستطبع 100
لكن لو اردنا العودة إلى القيمة 50 كيف سنعود ؟!
القيمة 50 موجوده بالذاكرة ومحفوظة ولكن لا نعلم عنوانها
عندها يوجد تسريب بالذاكرة .. فيوجد بيانات غير مهمه لاننا لا نعلم مكانها .. اذا يوجد حجز غير مهم
لذلك نجتاج لاستخدام الامر delete point
ربما يظهر انه من غير المهم حذف هذا الحجز ولكن لو تم حجز مصفوفه 100*100 وسيتم حجز مصفوفه اخرى عندها سيكون 10000 عنصر موجودين بالذاكرة ولا يمكن الوصول إليهم .. عندها يكون تسريب بالذاكرة
لاحظ معي ان الحجز للمؤشر *pointيكون في قسم مقطع البيانات
اما الحجز بالامر new يكون في heap
اما بخصوص عدم كتابة الامر delete فان البيانات تحذف من الذاكرة مباشرة بعد انتهاء البرنامج
هذا والله اعلم

اشهد ان لا إله إلا الله وان محمدا ً رسول الله
شكرا جزيلا على التوضيح سيد time1 ... كنت أعلم بعض المعلومات و كلن البعض الآخر توضح بشكل أفضل الآن
MAAAAAAAAAAAAAAAAAAAAAAAC
العفو استاذي الفاضل
لكن حبيت اضيف شيء معين بما ان الصورة وضحت عندك
الامر delete هو عبارة عن استدعاء تابع التدمير للغرض
فكما تعلم لغة السي ++ تنظر لكل شئ على انه غرض
وبنهاية مجال الرؤية يتم استدعاء التابع المدمر للغرض حتى ولو كان الحجز ديناميكي في heap
فان التحرير الديناميكي يستخدم افتراضي مع الغرض .. لكن delete يقوم استدعاء التابع المدمر ليدمر الغرض من الحجز وذلك لتوفير مساحة لفقرات اخرى بالبرنامج لزيادة كفائته وتوفير الذاكرة
هذا والله اعلم
اتمنى التوفيق

اشهد ان لا إله إلا الله وان محمدا ً رسول الله
bashmohandes كتب:بمجرد انتهاء الProcess التي فيها البرنامج يقوم نظام التغيل بازالة كل متعلقاتها تماماً
داه هو الكلام ;)
هذا الموضوع مغلق.