למבינים בC++

mirig

New member
../images/Emo53.gifלמבינים בC++

היי לכולם, משהו יודע למה הפונקציה הזאת עובדת מצויין בפעם הראשונה, ובפעם השניה המערכים שמוחזרים ממנה מאופסים? bool AddName(char* NewName, int Size, char** Names) { // Variables definition char** tmp; int curr_index; // Code Section // Allocate new dinamic array tmp = new char* [Size+1]; // Check if the allocation succeded if (tmp == NULL) { // Return false return false; } else { // If the allocation succeded copy old matrix to the temporary one for(curr_index = 0; curr_index<Size; curr_index++) { // Allocate new memory to copy the name tmp[curr_index]=Names[curr_index]; Names[curr_index] = NULL; } // Insert the new name last tmp[Size] = new char[strlen(NewName)+1]; // Check if the allocation succeded if (tmp[Size] == NULL) { return false; } // copy the new name to it´s location in the matrix strcpy(tmp[Size], NewName); } // Release old pointers delete[] Names; // Allocate the names array again Names = new char*[Size+1]; // Check the allocation if (Names == NULL) { return false; } for(curr_index = 0; curr_index<=Size; curr_index++) { // Allocate new memory to copy the name Names[curr_index]=new char[strlen(tmp[curr_index])+1]; strcpy(Names[curr_index], tmp[curr_index]); } // Delete the temporary array delete[] tmp; // The action succeded return true; } תודה!!
 
משהו פה חשוד מאד ../images/Emo11.gif

בשורה האומרת:
Names = new char*[Size+1];​
יש משהו חשוד. המערך Names נכנס לפונקציה בשיטת "by value" ולכן אין שום דרך שהקצאה כזאת תשפיע עליו בתכנית הראשית. יש כאן שתי אפשרויות, או להתחיל לעבוד עם משהו מכוער כמו מצביע-למצביע-למצביע (char ***Names) או לעבור לשיטת ה-reference - הרבה יותר אלגנטי.
 
פתרון בשליפה

להוסיף בהכרזת הפונקציה את הסימן ampersand (משום מה אני לא מצליח להקיש אותו בחלון הזה) אחרי ה-** char. עדיין, יש פה איפשהו דליפות זיכרון פראיות. שאין לי זמן לחפש אותן כרגע.
 

galh

New member
אתה עובד עם מחרוזות, לא?

בעיון מהיר נראה שאתה מקצה משתנה לא נכון. אם אתה עובד עם מחרוזות אז אתה אמור לרשום [new char[Size ולא *char כמו שאתה עושה.
 
העיון היה מהיר מדי כנראה

יש כאן הקצאה של מערכים של מחרוזות ולא רק מחרוזות פשוטות.
 

mirig

New member
צודק....

נראה לי שאני מפספסת משהו בהבנת הנושא....
 

mirig

New member
למה זה עובד מצויין בפעם הראשונה../images/Emo35.gif

עד כמה שידוע לי ברגע שמדובר במצביעים - מדובר במעבר By Reference ולא By value כי המעבר הוא רק של הכתובת של התא הראשון (או שאני מפספסת משהו....) וחוץ מזה - למה זה עובד רק בפעם הראשונה? אם זה באמת היה By value אז הערך הראשוני שהוא היה שומר לא היה נמחק. אולי למשהו יודע איזה שיטות יש להגדלת גודל של מערך דינמי בC++ מבלי להשתמש במערך עזר? אני כבר ממש מיואשת מהמצביעים האלה...
 

Pembelton

New member
ניתוח

א. כמו שכתבו פה כבר, אם אתה עושה ;[Names = new char*[Size+1 בתוך הפונקציה, זה לא משפיע על Names שמחוץ לפונקציה. אתה יכול להעביר ***char או יותר פשוט לשנות את ה return value של הפונקציה כך שהיא תחזיר את names החדש או NULL במקרה של כשלון. ב. כל הקוד שמתחת ל- //Allocate the names array again מיותר. אתה לא צריך להקצות את Names מחדש ולהעתיק את המחרוזות אחת אחת אלא מספיק להציב את tmp לתוך Names: ; Names = tmp ג. בכל מקרה, עזוב אותך מסעיפים א´ ו-ב´. אתה עובד ב C++ אז תשתמש בה עד הסוף. יש לך std::vector ו- std::string שיכולים לעשות לך את העבודה. במקרה של הפונקציה הנ"ל כל הקוד מצטמטצם לדבר הבא: ( void AddName(std::string& NewName, std::vector<std::string> Names } ;(Names.push_back(NewName { לא לשכות לעשות include# לקבצעים: vector ו- string
 

mirig

New member
וזה יעבוד ביוניקס??

אני לומדת מדמ"ח שנה א´, ואנחנו לא ברמה כ"כ מתקדמת... אתה יכול להסביר בבקשה יותר את השורה שכתבת. (או להמליץ על מקור ללמוד ממנו) תודה מירי
 

Pembelton

New member
יעבוד מצויין ביוניקס.

אני כמובן ממליץ על סעיף ג´. זה עובד גם ביוניקס, זה חלק מהסטנדרט של C++ וזה גם לא כל כך מסובך (זה אולי טיפה מפחיד את מי שלא רגיל). הבעיה היחידה היא שאולי בקורס שבו את לומדת לא מאשרים להשתמש ב standard library , שזו לפי דעתי טעות. בכל אופן אם אכן יש את המגבלה הזו את עדיין יכולה ללכת על מה שהצעתי בסעיפים א´ ו-ב´. איפה לומדים על ה standard library? אפשר פה: http://www.sgi.com/tech/stl/stl_introduction.html
 

mirig

New member
זה גם עובד רק בפעם הראשונה

נראה לי שבאמת קצת הטעו אותנו, ומערכים לא מועברים לפונקציה בצורה אוטומטית by referece אלה by value. אנחנו לא למדנו עדיין את הסטנדרט הזה (וכך שהם אוהבים להוריד נקודות על מה שהם לא לימדו אני לא אקח סיכון) הבעיה תפטר ברגע שהמעבר של המערכים הדינמיים לפונקציות יהיה by reference אבל אני לי ממש יודעת איך עושים את זה... מירי
 

Pembelton

New member
טעיתי, שכחתי & אחד

הכותרת של הפונקציה צריכה להיות ( void AddName(std::string& NewName, std::vector<std::string>& Names (ה- & שלפני ה Names מאד חשוב). חוץ מזה, לא הבנתי איזו מההצעות ניסית. רצוי גם שתראי את הקוד שקורא לפונקציה (רק את החלקים הרלבנטיים).
 
למעלה