העברת מטריצה לפונקציה ב-C++ - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

העברת מטריצה לפונקציה ב-C++


PhoenixBoy

Recommended Posts

שלום,

אני מנסה לכתוב פונקציה שתקבל שתי מטריצות בגדלים זהים ותחזיר מטריצה של סכומם.

הצלחתי לעשות את הפונקציה כאשר היא מקבלת תמיד מטריצות של 2 טורים אבל אני לא מצליח לעשות פונקציה שתקבל מטריצות בגדלים שונים.

זה הקוד שכתבתי ועובד:

void Add(int mat1[][2], int mat2[][2], int w, int h, int res[][2])
{
//int res[w][h];
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
res[i][j] = mat1[i][j] + mat2[i][j];
}

וכאשר ניסית להעביר את זה למטריצה בגודל דינאמי זה לא עבד. הנה הקוד:

void Add(int mat1[][], int mat2[][], int w, int h, int res[][])
{
//int res[w][h];
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
res[i][j] = mat1[i][j] + mat2[i][j];
}

איך אני יכול להעביר את המטריצות בצורה דינאמית?

קישור לתוכן
שתף באתרים אחרים

כשאתה מעביר מערך רב-מימדי לפונקציה, אתה חייב לקבוע מראש את כל המימדים של המערך, פרט למימד הראשון.

הפתרון הוא להעביר מצביעים במקום מערכים, אבל אז צריך מאוד להיזהר מבחינת אינדוקסים.

קישור לתוכן
שתף באתרים אחרים

אז למה כשאני עושה ככה הוא נותן לי שגיאה?

הפונקציה:


void Add(int** mat1, int** mat2, int w, int h, int** res)
{
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
res[i][j] = mat1[i][j] + mat2[i][j];
}

שורת הקריאה:

  Add(mat1,mat2,2,2,res);

השגיאה שהוא נותן לי:

12 C:\Documents and Settings\Hebrew\My Documents\C++\MatAdd2.cpp cannot convert `int (*)[2]' to `int**' for argument `1' to `void Add(int**, int**, int, int, int**)' 

קישור לתוכן
שתף באתרים אחרים

מערך רב מימדי הוא לא באמת מצביע למצביע. הוא בעצם רק מצביע אחד, ולכן ההמרה הזו לא יכולה להתבצע.

טוב, התשובה קצת מסורבלת, אני אקווה שאתה מצליח לעקוב:

תזכורת קצרה (או אם לא ידעת):

כשאתה מגדיר מערך, לדוגמה:

int arr[N];

אז הקומפיילר מקצה בלוק של N אינטים בזכרון. arr הוא בעצם מצביע לתחילת המערך. הביטוי הזה:

arr[i]

שקול לביטוי הזה:

*(arr+i)

שזה אומר להוסיף i פעמים את הגודל של arr* (== הגודל של int) ל-arr

arr הוא בעצם מצביע לתחילת המערך.

כשאתה מגדיר מערך דו מימדי, ככה:

int arr[N][K];

אז הקומפיילר מקצה בלוק של N*K אינטים בזכרון. arr הוא טיפוס עם התנהגות מוזרה - הוא מצביע ל-int (ולא מצביע למצביע ל-int), אבל אם תעשה לו dereferencing אז הוא יישאר מצביע עם טיפוס [int[K, אבל עם אותו הערך (כלומר arr == arr*, אתה יכול לבדוק את זה אפילו בעצמך עם printf).

אם תמיר את arr ל-*int, אז הוא יתנהג כמו מערך חד-מימדי בגודל N*K.

הבעיה היא שכל הבלגן הזה דורש שהקומפיילר יידע מראש את גודל המערך. אם אתה רוצה לעבוד עם מערכים דינמיים, אז זה פשוט בלתי אפשרי. בשביל זה יש כמה פתרונות:

1. להקצות מערך של מצביעים, כך שבעצם תוכל להעביר מצביע למצביע:

int* parr[N];
for (int i = 0 ; i < N ; ++i)
{
parr[i] = mat[i];
}

כל מצביע במערך הזה מצביע לשורה במטריצה, ולכן אתה יכול להעביר את parr לפונקציה בבטחה.

2. "לשטח" את המטריצה שלך - להתייחס אליה כמערך חד-מימדי, ולבצע את חישובי האינדקסים בעצמך במקום לתת אותם לקומפיילר:

void Add(int* mat1, int* mat2, int w, int h, int* res)
{
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
res[i*h+j] = mat1[i*h+j] + mat2[i*h+j];
}

שים לב שזה דורש התעסקות עם מצביעים, ולכן דורש המרה של הקלט ל-*int:

Add((int*)mat1,(int*)mat2,2,2,(int*)res);

3. לעקוף לחלוטין את הבעיה, ולא להשתמש במערכים - כיוון שאתה עובד ב-++C, מומלץ להימנע משימוש במערכים ומצביעים איפה שאפשר - אם אתה יכול להשתמש ב-Vector, אז עדיף. במקרה שלך, אתה יכול להגדיר מטריצה ע"י וקטור של וקטורים:

vector< vector<int> >

ולעקוף לחלוטין את הבעיה.

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...