Generic Stack
جزء من قسم البرمجة كائنية التوجه في رحلة C على Coddy. الدرس 60 من 61.
التحدي
سهلإن المكدس هو بنية بيانات أساسية تتبع مبدأ الوارد أخيرًا يصرف أولًا (LIFO): العنصر الأخير الذي تمت إضافته هو أول عنصر تتم إزالته. تخيّل كومة من الأطباق: تضيف من الأعلى وتزيل من الأعلى.
لننشئ مكدسًا عامًا: بنية بيانات متعددة الاستخدامات يمكنها تخزين أي نوع من البيانات باستخدام مؤشرات void*. سيتبع المكدس الذي تنشئه مبدأ الوارد أخيرًا يصرف أولًا، مع جميع العمليات الأساسية.
ستنظم التعليمات البرمجية عبر ثلاثة ملفات:
stack.h: عرّف البنيةStackبثلاثة أعضاء: مصفوفةvoid**للعناصر، وintلفهرس الموضع العلوي (الخانة التالية الفارغة)، وintللسعة. أعلن نماذج الدوال الخاصة بإنشاء مكدس (تأخذ سعة)، وإضافة عنصر، وإزالة عنصر، والاطلاع على العنصر العلوي، والتحقق مما إذا كان المكدس فارغًا، وتحرير المكدس.stack.c: نفّذ المكدس العام:create_stack: تخصص بنية Stack على heap، وتخصص مصفوفة العناصر بالسعة given، وتهيّئ top إلى 0، وتعيد المؤشرpush: تضيف عنصرًا إلى الموضع العلوي إذا كانت هناك مساحة (عندما يكون top أصغر من capacity)pop: تزيل العنصر العلوي وتعيده، أو تعيدNULLإذا كان المكدس فارغًاpeek: تعيد العنصر العلوي دون إزالته، أو تعيدNULLإذا كان فارغًاis_empty: تعيد 1 إذا لم يكن لدى المكدس أي عناصر، و0 otherwisefree_stack: تحرر مصفوفة العناصر أولًا، ثم بنية Stack نفسها
main.c: اقرأ عدد العمليات المطلوب تنفيذها. ثم لكل operation، اقرأ command:pushمتبوعة بقيمة integer، أوpop، أوpeek. أنشئ مكدسًا بسعة 10. بالنسبة إلىpush، خصص integer على heap وأضف مؤشره. بالنسبة إلىpop، استرجع العنصر، واطبع قيمته، وحرر integer. بالنسبة إلىpeek، اطبع القيمة دون إزالتها. إذا تم استدعاءpopأوpeekعلى مكدس فارغ، فاطبعempty. بعد جميع العمليات، حرر أي عناصر متبقية والمكدس.
سيستقبل برنامجك:
- عدد العمليات
- كل operation في سطر منفصل (
push Xأوpopأوpeek)
ناتج example عندما تكون المدخلات 5، ثم push 10، وpush 20، وpeek، وpop، وpop:
20
20
10ناتج example عندما تكون المدخلات 3، ثم pop، وpush 42، وpeek:
empty
42ناتج example عندما تكون المدخلات 4، ثم push 5، وpush 15، وpop، وpop:
15
5تذكّر أن المكدس يخزن مؤشرات void*: المتصل مسؤول عن تخصيص البيانات الفعلية وتحريرها. عند إزالة عنصر، حوّل void* المُعاد مرة أخرى إلى int* للوصول إلى القيمة. استخدم strcmp من <string.h> لمقارنة سلاسل command.
جرّب بنفسك
#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;
}
جميع دروس البرمجة كائنية التوجه
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكالتدرّب بنفسك: مترجم C عبر الإنترنت