منشئ نصوص ديناميكي
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 59 من 61.
التحدي
سهللنقم ببناء StringBuilder — وهو حاوية نصوص ديناميكية تنمو تلقائياً كلما أضفت نصاً إليها. هذه أداة عملية تجمع بين إدارة الذاكرة الديناميكية وأنماط البرمجة كائنية التوجه (OOP) التي أتقنتها خلال هذه الدورة.
ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:
stringbuilder.h: قم بالتصريح عن هيكلStringBuilderبثلاثة أعضاء: مخزن مؤقت من نوعchar*، ومتغير من نوعsize_tللطول الحالي، ومتغير من نوعsize_tللسعة الإجمالية. صرّح عن النماذج الأولية للوظائف (function prototypes) لإنشاء StringBuilder، وإضافة نص إليه، واسترجاع السلسلة النهائية، وتحرير الذاكرة. استخدام حواجز التضمين (Include guards) أمر ضروري.stringbuilder.c: قم بتنفيذ نظام StringBuilder الخاص بك:create_stringbuilder— يخصص StringBuilder على الذاكرة الحيوية (heap)، ويهيئ المخزن المؤقت بسعة أولية تبلغ 16 بايت، ويضبط الطول على 0، ويضمن أن يبدأ المخزن المؤقت كسلسلة فارغة (منتهية بـ null).append— يأخذ مؤشراً لـ StringBuilder وسلسلة نصية لإضافتها. احسب الطول الجديد المطلوب. إذا تجاوز السعة، ضاعف السعة (بشكل متكرر إذا لزم الأمر) واستخدمreallocلزيادة حجم المخزن المؤقت. ثم قم بدمج النص الجديد باستخدامstrcat.get_string— يعيد مؤشراً إلى المخزن المؤقت الداخلي (وصول للقراءة فقط).free_stringbuilder— يحرر المخزن المؤقت أولاً، ثم يحرر هيكل StringBuilder نفسه.
main.c: اقرأ عدداً صحيحاً يشير إلى عدد السلاسل النصية المراد إضافتها. ثم اقرأ كل سلسلة باستخدامfgetsوأضفها إلى StringBuilder الخاص بك. بعد إضافة جميع السلاسل، اطبع السلسلة المجمعة الكاملة باستخدامget_string. وأخيراً، قم بتحرير StringBuilder.
دالتان رئيسيتان مستخدمتان في هذا التحدي:
realloc(ptr, new_size)— يغير حجم كتلة ذاكرة تم تخصيصها مسبقاً. يأخذ مؤشراً للكتلة الموجودة والحجم الجديد المطلوب بالبايت، ويعيد مؤشراً للكتلة التي تم تغيير حجمها (والتي قد يتم نقلها لمكان آخر). استخدمه فيappendعندما يحتاج المخزن المؤقت للنمو:sb->buffer = (char*)realloc(sb->buffer, sb->capacity);fgets(buffer, size, stream)— يقرأ سطراً من النص من تدفق الإدخال إلى مصفوفة أحرف، ويتوقف عند سطر جديد أو عند قراءةsize - 1من الأحرف. يحتفظ بحرف السطر الجديد في المخزن المؤقت، لذا ستحتاج إلى إزالته يدوياً. استخدمه فيmain.cلقراءة كل سلسلة إدخال:fgets(line, sizeof(line), stdin);
لإزالة السطر الجديد في النهاية: تحقق مما إذا كان الحرف الأخير هو'\n'واستبدله بـ'\0'.
سيتلقى برنامجك:
- عدد السلاسل النصية المراد إضافتها
- كل سلسلة نصية في سطر منفصل
مثال للمخرجات عندما تكون المدخلات 3، ثم Hello، و ، و World:
Hello Worldمثال للمخرجات عندما تكون المدخلات 4، ثم C، و is، و a، و great language!:
C is a great language!مثال للمخرجات عندما تكون المدخلات 1، ثم SingleString:
SingleStringتذكر تحديث حقل length بعد كل عملية إضافة. عند التحقق مما إذا كانت هناك حاجة لإعادة التخصيص، ضع في اعتبارك حرف النهاية (null terminator) — يحتاج المخزن المؤقت لمساحة تبلغ length + new_text_length + 1 بايت. استخدم strlen من <string.h> لقياس أطوال السلاسل. استدعِ أيضاً getchar() بعد scanf في main.c لاستهلاك السطر الجديد المتبقي قبل قراءة السلاسل باستخدام fgets.
جرّب بنفسك
#include <stdio.h>
#include <stdlib.h>
#include "stringbuilder.h"
int main() {
int n;
scanf("%d", &n);
getchar(); // استهلاك سطر جديد بعد الرقم
// TODO: قم بإنشاء StringBuilder باستخدام create_stringbuilder()
// TODO: اقرأ n من السلاسل النصية وأضف كل منها إلى StringBuilder
// تلميح: استخدم fgets أو ما شابه لقراءة كل سطر
// تذكر معالجة محرف السطر الجديد من fgets إذا قمت باستخدامه
// TODO: اطبع السلسلة النصية الكاملة المجمعة باستخدام get_string()
// TODO: قم بتحرير StringBuilder باستخدام free_stringbuilder()
return 0;
}
جميع دروس Object Oriented Programming
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مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة