בעייה ברשימה מקושרת....

rantri

New member
בעייה ברשימה מקושרת....

יש לי קוד שיוצר רשימה מקושרת ב- ++c , התוכנית לא עובדת , לא הבנתי למה הפונקציה ()insert לא יוצרת איברים חדשים ברשימה. אני יודה למי שימצא איפה טעיתי....
#include <iostream.h> class LNode { public: int data; LNode *next; LNode(int d=0,LNode *n=0); // uses default arguments }; LNode::LNode(int d, LNode *n) { data = d; next = n; } class List { LNode *head; public: List(); ~List(); void insert(int record); int retrieve(int record); // return is error code int remove(int record); void clear(); bool empty(); }; List::List() { head = NULL; } bool List::empty() { if(head = NULL) return true; return false; } void List::clear( ) { LNode *rest; // meaning rest of the list // check for empty list already if (head==0) return; // loop and delete while (head) // NULL would return false and indicate empty rest = head->next; delete head; head = rest; } List::~List() { clear(); } void List::insert(int record) { LNode *p; p = new LNode(record); // using default arguments here p->next = head; head = p; } int main() { List *TheList = 0; TheList = new List; TheList->insert(15); TheList->empty(); return 0; }​
 

אלדד28

New member
טיפים...

1. שים לב שפונקציית ה-empty שלך שמה NULL בתוך HEAD. השתמשת ב- "=" במקום ב- "==". כדי שטעויות כאלו לא יקרו לך, תעשה לעצמך מנהג לכתוב את המשתנה מימין ולא משמאל. כלומר, במקום לעשות:
if (head == NULL)​
כתוב:
if (NULL == head)​
בצורה כזו, אם טעית וכתבת = במקום ==, הקומפיילר יצעק לך על הטעות. 2. בפונקציה clear מומלץ שתבדוק אם הרשימה ריקה על ידי קריאה ל-empty. מה שעשית בפועל היה שכפול קוד. אם מחר הרשימה תסומן כריקה על ידי סימון אחר (ויש לזה סיבות טובות), תצטרך לשנות בשני מקומות שונים. 3. לפעמים אתה משתמש ב-NULL, לפעמים אתה משתמש ב-0. למה? תשתמש רק ב-NULL כשאתה רוצה לאפס מצביע. 4. ב-constructor של Node, במקום לאתחל את המשתנים כמו שעשית, אתה יכול לאתחל אותם באמצעות initialization list, ככה:
class LNode { public: int data; LNode *next; LNode(int d=0,LNode *n=0) : data(d), next(n) {} };​
הסיבה לכך היא פשוטה - כשאתה לא עושה את זה ככה, ה-member-ים של ה-class מאותחלים בעזרת ה-default constructor שלהם, ואח"כ אתה עושה לתוכם השמה. כשמדובר ב-int וב-pointer זה לא נורא, אבל אם היה לך בתוך ה-class אובייקט - כלומר, class אחר, זה היה בזבוז משווע של זמן. היית קורא ל-constructor שלו, היית קורא לאופרטור = כדי לבצע את ההשמה, והיית יוצר אובייקט זמני בזכרון. קל מאוד לבזבז זמן ב-++C וצריך להישמר מזה. 5. אין שימוש ב-inline. יש כמה פונקציות שפשוט מתחננות לזה אצלך בקוד, כמו למשל empty. 6. ב-main שלך, אתה קורא ל-empty, בלי להסתכל על הערך המוחזר שלה. זו פונקציה שלא עושה שום דבר חוץ מלהחזיר לך bool. מה הטעם לקרוא לה סתם ככה? 7. ב-clear יש לך בעיה רצינית מאוד. כתבת:
.... while (head) // NULL would return false and indicate empty rest = head->next; delete head; head = rest; ....​
עכשיו, הקוד הזה היה יכול להיות בסדר, אבל ה-while שלך פשוט לא טוב ויגרום ללולאה אינסופית. הכוונה שלך הייתה טובה - רצית ששלוש השורות שאחרי ה-while יבוצעו בכל "סיבוב" (איטרציה) ב-while, אבל בפועל זה לא מה שעשית. רק השורה הראשונה, ששמה את next של head בתוך rest, תתבצע שוב ושוב. למעשה head לעולם לא יהיה null ככה, ולכן הלולאה לא תסתיים. מה שהיית צריך לעשות זה:
while (head) // NULL would return false and indicate empty { rest = head->next; delete head; head = rest; }​
בכל אופן, אחרי כל התיקונים האלו, התוכנית שלך עובדת מצוין. דווקא ב-insert אין שום בעיה והיא פועלת יפה. ממליץ לך לחזור על החומר ולהשתפשף קצת יותר.
 

rantri

New member
לאלדד../images/Emo51.gif

לאלדד מצתטער שזה קצת באיחור, אבל רציתי להגיד לך תודה רבה על ההשקעה ועל העזרה שנתת לי. זה עזר לי מאוד ובאמת שהייתי צריך לחזור יותר על הנושה של רשימות מקושרות, ולנסות לימצוא את הטעויות לבד. רן.
 
למעלה