מחסנית גנרית
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 60 מתוך 61.
אתגר
קלמחסנית היא מבנה נתונים בסיסי הפועל לפי עקרון נכנס אחרון, יוצא ראשון (LIFO): האיבר האחרון שנוסף הוא הראשון שמוסר. חשבו על ערימת צלחות: מוסיפים לצידה העליון ומסירים מהחלק העליון.
בואו נבנה מחסנית גנרית: מבנה נתונים רב־תכליתי שיכול לאחסן כל סוג של נתונים באמצעות מצביעי void*. המחסנית שלכם תפעל לפי עקרון נכנס אחרון, יוצא ראשון, ותכלול את כל הפעולות החיוניות.
תארגנו את הקוד שלכם בשלושה קבצים:
stack.h: הגדירו את המבנהStackעם שלושה איברים: מערךvoid**לפריטים, ערךintלאינדקס העליון (המקום הפנוי הבא), וערךintלקיבולת. הכריזו על אבות־טיפוס של פונקציות ליצירת מחסנית (מקבלת קיבולת), לדחיפת פריט, לשליפת פריט, להצצה בפריט העליון, לבדיקה אם המחסנית ריקה ולשחרור המחסנית.stack.c: ממשו את המחסנית הגנרית שלכם:create_stack: מקצה מחסנית בערימה, מקצה את מערך הפריטים בקיבולת הנתונה, מאתחלת את top ל־0 ומחזירה את המצביעpush: מוסיפה פריט לראש המחסנית אם יש מקום (כאשר top קטן מהקיבולת)pop: מסירה ומחזירה את הפריט העליון, או מחזירהNULLאם המחסנית ריקהpeek: מחזירה את הפריט העליון בלי להסיר אותו, או מחזירהNULLאם המחסנית ריקהis_empty: מחזירה 1 אם אין פריטים במחסנית, ו־0 אחרתfree_stack: משחררת תחילה את מערך הפריטים, ולאחר מכן את מבנה Stack עצמו
main.c: קראו את מספר הפעולות לביצוע. לאחר מכן, עבור כל פעולה, קראו פקודה:pushואחריה ערך שלם,popאוpeek. צרו מחסנית בקיבולת 10. עבורpush, הקצו מספר שלם בערימה ודחפו את המצביע אליו. עבורpop, שלפו את הפריט, הדפיסו את ערכו ושחררו את המספר השלם. עבורpeek, הדפיסו את הערך בלי להסיר אותו. אם קוראים ל־popאו ל־peekכשהמחסנית ריקה, הדפיסוempty. לאחר כל הפעולות, שחררו את הפריטים שנותרו ואת המחסנית.
התוכנית שלכם תקבל:
- את מספר הפעולות
- כל פעולה בשורה נפרדת (
push X,popאוpeek)
פלט לדוגמה כאשר הקלט הוא 5, ואז push 10, push 20, peek, pop, pop:
20
20
10פלט לדוגמה כאשר הקלט הוא 3, ואז pop, push 42, peek:
empty
42פלט לדוגמה כאשר הקלט הוא 4, ואז push 5, push 15, pop, pop:
15
5זכרו שהמחסנית שלכם מאחסנת מצביעי void*: האחריות להקצאה ולשחרור של הנתונים עצמם מוטלת על הקוד שקורא לה. בעת שליפה, המירו את void* המוחזר בחזרה ל־int* כדי לגשת לערך. השתמשו ב־strcmp מתוך <string.h> כדי להשוות בין מחרוזות הפקודות.
נסו בעצמכם
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
int main() {
int n;
scanf("%d", &n);
// TODO: צור מחסנית בקיבולת 10
// TODO: עבד כל פעולה
for (int i = 0; i < n; i++) {
char command[10];
scanf("%s", command);
if (strcmp(command, "push") == 0) {
int value;
scanf("%d", &value);
// TODO: הקצה מספר שלם בערימה ודחוף מצביע אליו למחסנית
}
else if (strcmp(command, "pop") == 0) {
// TODO: שלוף את הפריט מהמחסנית
// - אם אינו NULL, הדפס את הערך ושחרר את המספר השלם
// - אם הוא NULL (מחסנית ריקה), הדפס "empty"
}
else if (strcmp(command, "peek") == 0) {
// TODO: הצץ בפריט העליון במחסנית
// - אם אינו NULL, הדפס את הערך (אל תסיר או תשחרר אותו)
// - אם הוא NULL (מחסנית ריקה), הדפס "empty"
}
}
// TODO: שחרר את כל הפריטים שנותרו במחסנית
// TODO: שחרר את המחסנית עצמה
return 0;
}
כל השיעורים ביחידה תכנות מונחה עצמים
4כימוס
המושג של מצביעים אטומיםהגדרת מבנים אטומיםפונקציות Get ו-Setאימות ב-Settersסיכום: הקופסה הסודית2אובייקטים ומתודות
מבנים כאובייקטיםמצביע 'Self'נכונות constמצביע לעומת ערךמתודות עזרחזרה: מנהל נקודות5פרויקט: חשבון בנק פשוט
הגדרת הפרויקטמימוש החשבוןתרגלו בעצמכם: קומפיילר C אונליין