سؤال

وعندما تعلن مجموعة اثنين الأبعاد

int random[height][width];

ومن ثم استخدامه في وظيفة

void populate(int random[height][width], int x, int y)

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

هل كانت مفيدة؟

المحلول

وانا ذاهب الى تصعيد في الوقت الحالي واقول لكم ان المصفوفات متعددة الأبعاد لا تساوي الجهد الدماغ في C أو C ++. كنت أفضل حالا باستخدام المصفوفات أحادية الأبعاد (أو الأفضل من ذلك، الحاويات القياسية) والكتابة وظيفة الفهرسة:

inline int index (int x, int y)
{
  return x + y * width;
}

والآن لمشكلتك. C ++ لا يدعم C99 صفائف متغيرة الطول. المترجم يجب أن يعرف، في وقت الترجمة، وحجم المصفوفة. وفيما يلي، على سبيل المثال، لن يعمل.

int dim = 4;
int ar[dim];

إذا كانت dim const، انها ستعمل لأن المترجم سيكون قادرا على ان اقول بالضبط كيف ينبغي أن تكون ar واسعة (لأن قيمة dim لن تتغير). وربما هذا هو المشكلة التي تواجهها.

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

template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);

وهذا هو قبيح.

لوقت التشغيل، سوف تحتاج إلى استخدام new لتخصيص البيانات، أو استخدام نوع الحاوية.

نصائح أخرى

لا يمكن تعريف المصفوفة ذات أبعاد غير ثابتة (العرض والارتفاع) خارج وظيفة، وهذا هو - وليس في إطار مكدس، لأن أبعاد ليست معروفة في الترجمة من الوقت. كنت قد الثوابت استخدام أو تحيله حيوي (إما في كومة أو في إطار مكدس).

وعندما يتم تمرير مجموعة مباشرة كمعلمة إلى وظيفة (تمرير من حيث القيمة) أنه يضمحل إلى مؤشر إلى العنصر الأول من الصفيف. حتى إذا كنت تستطيع قراءة بوضوح في التوقيع أبعاد المصفوفة، يتم تجاهل هذه الأبعاد من قبل المجمع. هذا السلوك هو متوافق مع C.

وعن طريق C ++ يمكنك تمرير مجموعة بالرجوع، وأنه لن يكون هناك مشكلة أي أكثر من ذلك.

int extract_value( int (&a)[10][10], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[10][10] = {};
   a[5][5] = 1;
   std::cout << extract_value( a, 5, 5 ) << std::endl;
   int b[5][5];
//   extract_value( b, 2, 2 ); // error: the function takes an array of 10x10
}

ويجب أن يطابق المعلمة وظيفة بالضبط، وهذا هو، إلا أنها تأخذ مجموعة من العناصر 10X10. يمكنك أن تأخذ التخلص من هذا القيد من قبل النموذجيه الدالة على أحجام صفيف. مرة كنت في ذلك أيضا نوع:

template <typename T, int Rows, int Cols>
T extract_value( T (&a)[Rows][Cols], int row, int col ) {
   return a[row][col];
}
int main() {
   int a[5][7] = {};
   extract_value( a, 3, 4 );
   int b[8][2] = {};
   extract_value( b, 7, 1 ); // correct, the compiler matches sizes
   double c[4][4] = {};
   extract_value( c, 2, 2 ); // different types are allowed
}

وهذا الحل لا تزال مرهقة في ذلك أحجام يجب تجميع ثوابت الوقت، ويجب المكدس تخصيص صفيف. الحل لهذا هو تعريف بعض الطبقة التي تأخذ ذاكرة ديناميكية في منطقة عازلة (خطي) ويحتوي على التحول من N-تنسيق النظام في مجموعة 1 الأبعاد للحصول على القيم، كما اقترح من قبل. يمكنك الحصول على بعض التلميحات حول كيفية القيام بذلك في هذه التعليمات عن الحمولة الزائدة المشغل الذي يوفر تنفيذ مصفوفة 2D. وبمجرد الانتهاء من أن تنفذ، يمكنك فقط استخدام هذا كمعلمة إلى وظائف / الأساليب.

وتوصيتي سيكون لمتابعة هذا المسار الأخير: تغليف مجموعة N-الأبعاد إلى الدرجة التي توفر التحويلات في ناقلات 1D (وC ++ التعليمات لايت يستخدم مؤشر الخام، لكنني أفضل حاويات STL)

وأنا يجب توضيح مع مثل:

و// غلوبالس

وconst int ARRAY_SIZE = 16 struct ArrayType_t arrayType[ARRAY_SIZE];

وعلى الرغم من أن أعلنت ARRAY_SIZE ك int ثابت انها لم يتم تهيئة قيمة في وقت الترجمة وبالتالي المترجم لا يعرف حجم المصفوفة ويعطي مثل هذا الخطأ. ولكن إذا كنت جعل هذا بمثابة التجزئة تعريف #define ARRAY_SIZE 16 struct ArrayType_t arrayType[ARRAY_SIZE] ===> يعمل هذا لأنه يتم تعريف ARRAY_SIZE في وقت الترجمة والمترجم يستطيع أن يعرف حجم مجموعة في وقت الترجمة.

ويمكنك استخدام شيء من هذا القبيل:

void populate(int height, int width, int **random)
{
    //here you can work from random[0][0] to random[height][width]
}

وبعد ذلك يمكنك استخدام مثل هذا:

int main()
{
    int height=10;
    int width=20;
    int **myarray = new int*[height];
    for( int i=0; i< height; i++ ) myarray[i] = new int[width];
    populate( height, width, myarray);
}

ولكن، بطبيعة الحال، سيكون لديك لمشاهدة لعازلة الفيضانات

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top