בעיות במטריצות

ShayHk

New member
בעיות במטריצות

איך אני יכול ההקצות דינמית מטריצה בגודל X , Y
 

ShayHk

New member
את זה אני יודע אבל איך??

לדוגמא : int **matrix; matrix = new int[5][5]????
 

DadleFish

New member
לא

ב-C אין דבר כזה "מטריצה". כשאתה מגדיר:
int **matrix;​
אתה מגדיר למעשה מצביע למצביע ל-int, לא מטריצה. האתחול הראשון אם כן יהיה:
matrix = new (int *)[5];​
כלומר הגדרת ש-matrix הוא מצביע למערך בן חמישה איברים, שבו כל איבר הוא מצביע ל-int. לאחר מכן עליך לאתחל כל איבר כזה, בצורה כזו:
for (int i=0; i < 5; i++) { matrix = new int[5]; }

בסיום עליך לשחרר את המערך הכפול באותה צורה:
// Deleting each "line" in the matrix for (int i = 0; i < 5; i++) { delete []matrix; } // Deleting the array of lines. delete []matrix;
 

the new L

New member
עדיף לעבוד עם vector

ולכתוב משהו כזה למשל:
vector< vector<int> > myMatrix(5,vector<int> (5));​
מה שיגדיר מטריצה של 5 על 5, ויחסוך מהמשתמש התעסקות עם הזיכרון בעצמו.
 

DadleFish

New member
כן, טוב,

אתה צודק. עדיף בכלל לממש מחלקה שיוצרת מטריצה ולהחביא את הכל מהמשתמש, אבל בחרתי ללכת לבסיס כי את זה הוא לא יודע, ולקפוץ למחלקות כשאתה לא יודע את הבסיס זה לא ממש מומלץ.
 

the new L

New member
נכון אבל

באופן כללי, כשעובדים עם C++ עדיף להשתמש בvector ולא במערכים של C, ועדיף מלכתחילה ללמוד על vector שעדיף בכל פרמטר אפשרי על מערך C.
 

Moridin

New member
לדעתי

כדאי לדעת גם ניהול זיכרון ב-C, כדי להבין מה קורה מאחורי הקלעים של C++... אבל אולי זה רק אני.
 

the new L

New member
אתה צודק

עדיף לדעת את שניהם, ובפועל לעבוד עם vector. רק אחרי שעובדים עם שניהם מבינים עד כמה vector עדיף :)
 
כן אבל לדעתי לא כפי שאתה הראית

וקטור יחזוך את ההתעסקות המיותרת (לרוב) עם הקצאה ושחרור זכרון, אבל עדיף תמיד לעבוד עם מערך חד מימדי ולעשות חישוב אינדקסים. זה פשוט יותר וזה טבעי יותר. הדוגמא הבאה תבהיר:
#include <vector> template <typename T> class Matrix : private std::vector<T> { public: // ctor (No need for destructor) // Matrix(int r, int c) : row(r), col(c), std::vector<T>(r * c) {} // Matrix dimensions // int max_row() const { return row; } int max_col() const { return col; } // Fortran like element access (for assignment) // T& operator()(int r, int c) { return (*this)[r * max_col() + c]; } const T& operator()(int r, int c) const { return (*this)[r * max_col() + c]; } private: int row; int col; };​
ירושה פרטית מלמדת שיורש את המימוש אבל לא את המימשק. היה אפשר לעשות זאת גם עם member vector וללא ירושה. שים לב שהשמה וקריאת ערכים ע"י אופרטורים יותר טבעיים (מבחינה מתימטית). הנה קוד לדוגמא שמשתמש במטריצה הזאת.
// test // #include <iostream> int main() { using namespace std; Matrix<int> matrix(3, 3); // Element assignment. // matrix(1, 1) = 15; // Fetch element // cout << matrix(1, 1) << endl; }​
 

gmorphus

New member
למה לך להתאמץ כל-כך?

תסתכל למשל בקוד הבא:
vector< vector<int> > myMatrix(5, vector<int>(5)); int main() { myMatrix[3][2] = 7; cout << myMatrix.size() << "X" << myMatrix[0].size() << endl; // will output 5X5 myMatrix[6][6] = 1; // will throw an exception cout << myMatrix[3][2] << endl; // will print 7 return 0; }​
כמובן שאפשר לשים איזה typedef או משהו, אבל העבודה עם המערך הזה דומה מאוד למה שאתה עשית ומגבילה את מספר האיברים כמו שצריך. אין במחלקה שכתבת שום רע אבל זה מאמץ...
 

the new L

New member
אזהרה!!

myMatrix[6]​
לא יזרוק exception אלא כנראה יעיף לך את התוכנית כי אתה ניגש לזיכרון שלא שייך לך! כל הרעיוון ב operator [] ב vector שהוא יהיה מהיר כמו שימוש במערכים, לכן לא מבוצעת שם שום בדיקה. אם אתה רוצה להיות בטוח שאתה לא חורג ושבמקרה ואתה חורג תיזרק exception יש להשתמש בפונקציה at במקום ב operator [].
 

gmorphus

New member
../images/Emo45.gif צודק

ואז אולי שווה לעטוף אותו באיזה class... או אולי מאקרו...
 

ShayHk

New member
זה עדיין לא פועל...תראה מה ניסיתי

int ** mat; mat=new (int *)[3]; // הקומפיילר אומר לי שצריך להיות ; לפני ה-] , למה for (int i=0; i < 3; i++) { mat = new int[3]; }
 
למעלה