أفضل طريقة لتمثيل مصفوفة ثنائية الأبعاد في لغة C++‎ مع تحديد الحجم في وقت التشغيل

StackOverflow https://stackoverflow.com/questions/256297

سؤال

في C++ أود أن أفعل شيئًا مثل:

int n = get_int_from_user();

char* matrix = new char[n][n];

matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';

delete [][] matrix;

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

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

المحلول

الطريقة الديناميكية اليدوية:

لنفترض أنك تريد مصفوفة ذات عرض*ارتفاع، الطريقة الأكثر فعالية هي استخدام مصفوفة ذات بعد واحد فقط:

char *matrix = new char[width*height];

لحذفه:

delete[] matrix;

للوصول إليه:

char getArrayValue(char *matrix, int row, int col)
{
  return matrix[row + col*width];
}

لتعديله:

void setArrayValue(char *matrix, int row, int col, char val)
{
  matrix[row + col*width] = val;
}

مصفوفة التعزيز:

فكر في استخدام Boost::matrix إذا كان بإمكانك الحصول على التبعية.

يمكنك بعد ذلك ربطها بـ تعزيز الجبر الخطي المكتبات.

هنا بعض نموذج كود التعزيز::matrix:

#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
    for (unsigned j = 0; j < m.size2 (); ++ j)
        m (i, j) = 3 * i + j;

على المكدس لبعض المترجمين:

تسمح لك بعض المترجمات فعليًا بإنشاء صفائف على المكدس بأحجام محددة في وقت التشغيل.g++ مثال على هذا المترجم.لا يمكنك القيام بذلك بشكل افتراضي VC++ بالرغم من ذلك.

لذلك في g++ هذا رمز صالح:

int width = 10;
int height = 10; 
int matrix[width][height];

ذكر Drew Hall أن ميزة C99 هذه تسمى المصفوفات ذات الطول المتغير (VLAs) ومن المحتمل أن يتم تشغيلها في أي مترجم حديث.

نصائح أخرى

وأنا عادة ما تفعل شيئا من هذا القبيل:

char *matrix = new char [width * height];

matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';

delete [] matrix;

وماذا عن std::vector< std::vector<int> > array2d;؟

يبدو أنك تفتقد المغزى الأساسي من لغة C++ (C مع الفئات) :-).هذا هو نوع الاستخدام الذي يستدعي الفصل لتنفيذه.

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

  • المُنشئ الذي، بالنظر إلى n، سينشئ فقط مصفوفة n*n جديدة من char (على سبيل المثال، charray)..
  • وظائف الأعضاء التي تحصل على القيم وتعيينها بناءً على x.y والتي تشير ببساطة إلى charray[x*n+y];
  • المدمر الذي يحذف [] هو المصفوفة.

لاثنين مجموعة الحقيقية الأبعاد:

int n = get_int_from_user();

char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
    matrix[i] = new char[n];
}

// Operations on matrix.

for (int i = 0; i < n; i++) {
    delete [] matrix[i];
}
delete matrix;

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

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

class Matrix
{
    int width;
    int height;
    char* data;
public:
    Matrix();
    Matrix(int width, int height);
    ~Matrix();

    char getArrayValue(int row, int col);
    void setArrayValue(int row, int col, char val);
}

وتنفيذ تمرين للقارئ. ؛)

وأعتقد أن هذا سيكون فكرة جيدة.

int n = get_int_from_user();

char **matrix=new (char*)[n];

for(int i=0;i<n;i++)
    matrix[i]=new char[n];

matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';

for(int i=0;i<n;i++)
    delete []matrix;
delete []matrix;
std::vector<int> m;

وثم استدعاء m.resize () في وقت التشغيل.

int* matrix = new int[w*h];

وإذا كنت تريد أن تفعل شيئا مثل القضاء جاوس يجب أن تكون المصفوفة الخاصة بك

int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
    matrix[i] = new int[w];

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

scroll top