מקבל שגיאת ריצה בהדפסת איבר ברשימה מקושרת - עמוד 3 - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

מקבל שגיאת ריצה בהדפסת איבר ברשימה מקושרת


bdoron

Recommended Posts

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

ומה שאני יודע שהם מוקצים במקטע הheap

גם אותם שדות מוקצה להם שם זיכרון? ואם מדובר בפרמיטיבים? שדות כמו int

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

  • תגובות 43
  • נוצר
  • תגובה אחרונה

מופעים של מחלקות תמיד נמצאים ב-heap. אם אתה מגדיר מחלקה (class) ויש לה שדה מטיפוס int, אז השדה הזה נמצא, יחד עם שאר המחלקה, ב-heap.

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

א. המשתנה\פרמטר הוא פרימיטיבי, ואז הערך שלו יושב במחסנית.

ב. המשתנה\פרמטר הוא reference type, שזה אומר שהמשתנה יושב במחסנית, אבל האובייקט שהוא מצביע עליו (בהנחה שיש כזה) יושב ב-heap. כל מחלקה (כולל string) היא reference type.

(אני בכוונה לא נכנס פה ל-struct שרק מסבך את העסק)

אם למדת ++C אז אתה מכיר מצביעים, נכון? אז כל משתנה מטיפוס reference type הוא בעצם מצביע - תמיד.

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

אתה רואה אני התכוונתי לזה , אז קודם כל תודה כי עשית לי סדר :) טוב לדעת שהמונח המקצועי של משתנים ששולחים לפונקציה או מתודה נקרא פרמטרים

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

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

בכל אופן לעניינינו...

בו נתחיל מההתחלה, אני עשיתי כמו שראית פונקציה print שבפנים יש לי לולאה שרצה כל עוד temp שונה מnull..

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

- - - תגובה אוחדה: - - -

למדתי שפת סי

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

לאובייקט יש שני שדות - Data מטיפוס Person, ו-next מטיפוס Node. כיוון ששניהם reference type, שניהם מאותחלים ל-null.

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

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

מה שאתה אומר לי יואב זה בעצם שלמרות שהצבתי בתוך אז אם אתחלתי פעם ראשונה את הhead אני צריך בעצם לפני הכל להגיד שhead.next == לnull בשביל לסדר את הבעיה

לא?

:)

כי ההיגיון שלי אומר שאם אני רץ בלולאה ועושה head=head.next אז שאני אגיע לאיבר האחרון שהוא בעצם הnext אני צריך שהוא יהיה null על מנת לצאת מהלולאה

- - - תגובה אוחדה: - - -

סדרתי את זה , דאגתי לאתחל בבנאי את head ב null

יואב יש לי עוד שאלונת, אם בתוך head יש לי עוד צומת, כמו שאתה רואה זה הnext אז שאני מאתחל את head בnull כל האובייקט עצמו ==null? או שאני צריך לאתחל גם את next בnull

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

אם כל האובייקט הוא null, אז אתה לא יכול בכלל לגשת לשדות שלו (כי הם לא קיימים), אז בטח שאין לך מה לאתחל אותם.

רק הערה קטנה (למניעת בלבול): האובייקט הוא לא null, אלא המשתנה הוא null. כשהמשתנה הוא null אז אין לך אובייקט בכלל.

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

מממ את האמת לא אשקר קצת בילבלתם אותי , יואב אם אני מציב לאובייקט null

לדוגמא: head=null

אז האובייקט עצמו או null לא?

או שברגע שאני רושם null לאובייקט זה כאילו הצבתי לכל השדות שלו null

ואם זה מציב לכל השדות null אז אני יכול להשיג את אותו אפקט על ידי הצבת null לכל המשתנים הפנימיים שלו במקום לעשות head=null?

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

בוא ננסה לעשות סדר.

C למדת, אז אתה מכיר מצביעים.

מבחינת סמנטיקה בOOP, מצביע (pointer) וreference הם אותו דבר.

אז, כמו ששניצל אמר, כשיש לך משתנה מסוג reference type, הוא למעשה לא האובייקט עצמו, אלא רק מצביע לאובייקט.

לכן כשאתה כותב head = null, שום אובייקט לא משתנה. המצביע שלך הופך להיות לnull (כלומר אינו מצביע לשום אובייקט תקני).

מה קרה לאובייקט שהצבעת אליו קודם? שום דבר.

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

אם אין יותר מצביעים לאובייקט הזה, הרי שמדובר באובייקט "מת". בסביבה לא מנוהלת זה אומר שהזכרון של האובייקט זלג. בסביבה מנוהלת, כמו #C, זה אומר שהgarbage collector מתישהו יזהה את העבודה שהאובייקט כבר לא נגיש וישחרר את הזכרון שלו.

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

המתודה Print של Person מדפיסה את המשתנים הפנימיים של האוביקט

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

תוכל לעשות דבר כזה

public void Print()
{
Node<T> temp = head;
while(temp!=null) {
Console.WriteLine(temp.Data.toString());
temp = temp.next;
}
}

הבנת?

זה פותר נקודתית את המקרה של ההדפסה, אבל זו לא הדרך הנכונה.

מה שצריך לעשות במקרה הזה זה להגדיר interface ולהשתמש בwhere בהגדרת המחלקה הגנרית.

בנוסף, כדי לעמוד בסטנדרטים שנהוגים בC# הרשימה צריכה לממש IEnumerable ולאפשר גישה lazy לאיברים במערך (על מנת לאפשר שירשור של אופרטורים בLinq למשל).

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

בכל מקרה, הקוד צריך להיות משהו כזה:



// The desired behavior
public interface IPrintable
{
void Print();
}


// Entity that implement this behavior
public class Person : IPrintable
{
public string FirstName { get; set; }
public string LastName { get; set; }


public void Print()
{
Console.WriteLine(FirstName + " " + LastName);
}
}


class Node<T>
{
public T Item;
public Node<T> Next;
public Node<T> Previous;
public CustomLinkedList<T> List;


public Node(T item, CustomLinkedList<T> list)
{
Item = item;
List = list;
}


}


// This implementation only handles the addition of items to the list and the enumeration
public class CustomLinkedList<T> : IEnumerable<T>
{
Node<T> Head { get; set; }


public void AddNode(T obj)
{
var newNode = new Node<T>(obj, this);


if (Head == null)
ListIsEmpty(newNode);
else
AddNodeToTheEnd(Head, newNode);
}


private void ListIsEmpty(Node<T> newNode)
{
newNode.Next = newNode;
newNode.Previous = newNode;
Head = newNode;

}


private void AddNodeToTheEnd(Node<T> node, Node<T> newNode)
{
newNode.Next = node;
newNod
e.Previous = node.Previous;
node.Previous.Next = newNode;
node.Previous = newNode;
}

public IEnumerator<T> GetEnumerator()
{
//Please implement this part, this one does the magic.
// use yield to enable lazy enumeration of the list
}


IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}


// this list enable printing of printable objects
public class PrintableList<T> : CustomLinkedList<T> where T : IPrintable
{
public void Print()
{
foreach (var item in this)
{
item.Print();
}
}



}


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

ארכיון

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


×
  • צור חדש...