עבור לתוכן

שאלה קטנה ב-++C

Featured Replies

פורסם

יש לי מבנה נתונים כלשהו, נקרא לו ST.

הצהרתי על מצביע למבנה כזה, כלומר כתבתי את זה:

ST *head

כאשר head הוא שם המצביע.

אני רוצה לשנות את ערך המצביע בפונקציה, איך אני עושה דבר כזה?

בינתיים כתבתי את זה:

void func(ST *ptr)

{

ST *ptr2;

change ptr2 value

ptr = ptr2;

}

וקראתי לפונקציה עם זה:

func(&*head)

האם זה אמור לעבוד?

פורסם

ST *head

void func(ST **ptr)

{

ST *ptr2;

change ptr2 value

*ptr = ptr2;

}

func(&head)

נגיד אתה עובד עם int

אתה עושה

int i;

viod fun(int *a) {

int b;

*a=b;

}

fun(&i);

אותו דבר בדיוק

פורסם
  • מחבר

תודה, ושאלה נוספת:

איך אני ניגש למבנה ש-ptr מצביע עליו?

נניח שיש לי שדה ב-ST שנקרא field. ממה שהבנתי, כדי לגשת לשדה הזה דרך ptr אני צריך לכתוב את זה:

**ptr -> field

אבל אני מקבל שגיאת קומפליציה -

"pointer to sturcture required on left side of -> or ->*"

איפה הטעות שלי?

פורסם

אם הגדרת

ST *head

ואתה רוצה לגשת לשדה field אתה צריך לעשות

head->field or (*head).field

שים לב שלאופרטור חץ יש עדיפות על כוכבית.

אם הגדרת

ST **head

ואתה רוצה לגשת לשדה field אתה צריך לעשות

(*head)->field or (**head).field

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

פורסם
  • מחבר

תודה, ושאלה אחרונה:

בזמן הרצת התוכנית אני מקבל הודעת שגיאה כזו -

Thread stopped at *

Fault: access violation at

0x4010b1: read of address

0x0

כאשר * הוא שם הכונן והקובץ

זו התוכנית:

struct Tree {

int Key;

Tree *p;

Tree *Left;

Tree *Right;

};

void TreeInsert(Tree **root,Tree **z)

{

Tree *x,*y;

y = NULL;

x = *root;

while (x != NULL)

{

y = x;

if ((*z) -> Key < x -> Key)

x = x -> Left;

else

x = x -> Right;

}

(*z) -> p = y;

if (y == NULL)

root = z;

else

if ((*z) -> Key < x -> Key)

y -> Left = *z;

else

y -> Right = *z;

}

void main()

{

Tree *r,*z;

r = new Tree;

z = new Tree;

r -> Key = 5;

r -> p = NULL;

r -> Left = NULL;

r -> Right = NULL;

z -> Key = 10;

z -> p = NULL;

z -> Left = NULL;

z -> Right = NULL;

TreeInsert(&r,&z);

}

את הודעת השגיאה אני מקבל על השורה הזו:

if ((*z) -> Key < x -> Key)

מה אני עושה לא בסדר?

פורסם

מה בדיוק נסית לעשות?

עריכה - הבנתי כבר לבדר

פורסם

קודם כל הסתבכת קשות עם מבציעים

הטעות שלך נמצאת פה

if (y == NULL)

root = z;

else

if ((*z) -> Key < x -> Key)

y -> Left = *z;

else

y -> Right = *z;

הרי אם הגעת לכאן אז מהלולאה הקודמת x=NULL אז אתה לא יכול לגשת לשדה הזה, לדעתי זה צריך להיות y->key.

חוץ מזה root = z פשוט לא יעשה כלום. הרי root הוא משתנה מקומי, אם כבר אז

*root = *z

הרבה יותר פשוט היה לעשות ככה

struct Tree {

int Key;

Tree *p;

Tree *Left;

Tree *Right;

};

void TreeInsert(Tree *root,Tree *z)

{

Tree *x,*y;

y = NULL;

x = root;

while (x != NULL)

{

y = x;

if (z->Key < x->Key)

x = x->Left;

else

x = x->Right;

}

z->p = y;

if (y == NULL)

root = z;

else

if (z->key < y->Key)

y -> Left = z;

else

y -> Right = z;

}

void main()

{

Tree *r,*z;

r = new Tree;

z = new Tree;

r -> Key = 5;

r -> p = NULL;

r -> Left = NULL;

r -> Right = NULL;

z -> Key = 10;

z -> p = NULL;

z -> Left = NULL;

z -> Right = NULL;

TreeInsert(r,z);

}

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

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

int init(tree **x) {

tree *a;

a = new tree;

*x = a;

return 0;

}

מקווה שעכשיו הכל ברור

פורסם

אם אתה לא מניח תקינות קלט אתה צריך לטפל במקרים ש-root==NULL או z==NULL

דרך אגב יותר ברור ויפה לעשות ככה

void TreeInsert(Tree *x,Tree *z)

{

Tree *y;

if(x==NULL) ??? /* big problem... maybe return Failure or just return */

if(z==NULL) return;

y = NULL;

while (x != NULL)

{

y = x;

if (z->Key < x->Key) {

if(x->Left == NULL) {

z->p = x;

x->Left = z;

return;

}

x = x->Left;

}

else {

if(x->Right == NULL) {

z->p = x;

x->Right = z;

return;

}

x = x->Right;

}

}

פורסם
  • מחבר

Holy, תודה רבה על העזרה שלך :)

בסוף באמת בילבלתי בין שני משתנים, כשאחד היה אמור להיות NULL והשני לא

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

ארכיון

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

דיונים חדשים