تمرير المصفوفات متعددة الأبعاد كوسيطات دالة في لغة C

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

  •  08-06-2019
  •  | 
  •  

سؤال

في لغة C، هل يمكنني تمرير مصفوفة متعددة الأبعاد إلى دالة كوسيطة واحدة عندما لا أعرف ما هي أبعاد المصفوفة؟

بالإضافة إلى ذلك، قد تحتوي مصفوفتي متعددة الأبعاد على أنواع أخرى غير السلاسل.

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

المحلول

يمكنك القيام بذلك مع أي نوع بيانات.ما عليك سوى جعله مؤشرًا إلى مؤشر:

typedef struct {
  int myint;
  char* mystring;
} data;

data** array;

لكن لا تنس أنه لا يزال يتعين عليك ضبط المتغير، وهو أمر معقد بعض الشيء:

//initialize
int x,y,w,h;
w = 10; //width of array
h = 20; //height of array

//malloc the 'y' dimension
array = malloc(sizeof(data*) * h);

//iterate over 'y' dimension
for(y=0;y<h;y++){
  //malloc the 'x' dimension
  array[y] = malloc(sizeof(data) * w);

  //iterate over the 'x' dimension
  for(x=0;x<w;x++){
    //malloc the string in the data structure
    array[y][x].mystring = malloc(50); //50 chars

    //initialize
    array[y][x].myint = 6;
    strcpy(array[y][x].mystring, "w00t");
  }
}

يبدو رمز إلغاء تخصيص البنية مشابهًا - لا تنس الاتصال مجانًا () على كل ما قمت بتخصيصه!(أيضًا، في التطبيقات القوية، يجب عليك تحقق من عودة malloc ().)

لنفترض الآن أنك تريد تمرير هذا إلى دالة.لا يزال بإمكانك استخدام المؤشر المزدوج، لأنك ربما تريد إجراء عمليات معالجة على بنية البيانات، وليس المؤشر إلى مؤشرات هياكل البيانات:

int whatsMyInt(data** arrayPtr, int x, int y){
  return arrayPtr[y][x].myint;
}

استدعاء هذه الوظيفة مع:

printf("My int is %d.\n", whatsMyInt(array, 2, 4));

انتاج:

My int is 6.

نصائح أخرى

قم بتمرير مؤشر صريح إلى العنصر الأول بأبعاد المصفوفة كمعلمات منفصلة.على سبيل المثال، للتعامل مع المصفوفات ثنائية الأبعاد ذات الحجم العشوائي من int:

void func_2d(int *p, size_t M, size_t N)
{
  size_t i, j;
  ...
  p[i*N+j] = ...;
}

والذي سوف يسمى كما

...
int arr1[10][20];
int arr2[5][80];
...
func_2d(&arr1[0][0], 10, 20);
func_2d(&arr2[0][0], 5, 80);

ينطبق نفس المبدأ على المصفوفات ذات الأبعاد الأعلى:

func_3d(int *p, size_t X, size_t Y, size_t Z)
{
  size_t i, j, k;
  ...
  p[i*Y*Z+j*Z+k] = ...;
  ...
}
...
arr2[10][20][30];
...
func_3d(&arr[0][0][0], 10, 20, 30);

يمكنك إعلان وظيفتك على النحو التالي:

f(int size, int data[][size]) {...}

سيقوم المترجم بعد ذلك بإجراء جميع العمليات الحسابية للمؤشر نيابةً عنك.

لاحظ أنه يجب أن تظهر أحجام الأبعاد قبل المصفوفة نفسها.

يسمح GNU C بإعادة توجيه إعلان الوسيطة (في حالة احتياجك حقًا إلى تمرير الأبعاد بعد المصفوفة):

f(int size; int data[][size], int size) {...}

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

int matmax(int **p, int dim) // p- matrix , dim- dimension of the matrix 
{
    return p[0][0];  
}

int main()
{
   int *u[5]; // will be a 5x5 matrix

   for(int i = 0; i < 5; i++)
       u[i] = new int[5];

   u[0][0] = 1; // initialize u[0][0] - not mandatory

   // put data in u[][]

   printf("%d", matmax(u, 0)); //call to function
   getche(); // just to see the result
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top