Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

منشئ نصوص ديناميكي

جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 59 من 61.

challenge icon

التحدي

سهل

لنقم ببناء 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'.

سيتلقى برنامجك:

  1. عدد السلاسل النصية المراد إضافتها
  2. كل سلسلة نصية في سطر منفصل

مثال للمخرجات عندما تكون المدخلات 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