Menu
Coddy logo textTech

בונה מחרוזות דינמי

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 59 מתוך 61.

challenge icon

אתגר

קל

בואו נבנה StringBuilder: מכל להחזקת מחרוזת דינמי שגדל אוטומטית כשמוסיפים לו טקסט. זהו כלי שימושי ומעשי שמשלב ניהול זיכרון דינמי עם דפוסי ה-OOP שהתמקצעת בהם לאורך הקורס הזה.

תארגן את הקוד שלך בשלושה קבצים:

  • stringbuilder.h: הכרז על המבנה StringBuilder ובו שלושה איברים: מאגר char*, ערך מסוג size_t עבור האורך הנוכחי, וערך מסוג size_t עבור הקיבולת הכוללת. הכרז על אבות טיפוס של פונקציות ליצירת StringBuilder, להוספת טקסט אליו, לקבלת המחרוזת הסופית ולשחרור הזיכרון. הגנות הכללה הן חיוניות.
  • stringbuilder.c: ממש את מערכת ה-StringBuilder שלך:
    • create_stringbuilder: מקצה StringBuilder בערימה, מאתחלת את המאגר בקיבולת התחלתית של 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: המאגר צריך להכיל מקום עבור 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;
}

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C אונליין