Menu
Coddy logo textTech

Dinamik String Oluşturucu

Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 59 / 61.

challenge icon

Görev

Kolay

Metin ekledikçe otomatik olarak büyüyen dinamik bir dize kapsayıcısı olan bir StringBuilder oluşturalım. Bu, dinamik bellek yönetimini bu kurs boyunca ustalaştığınız OOP desenleriyle birleştiren pratik bir yardımcı programdır.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • stringbuilder.h: Üç üyeli StringBuilder yapısını (struct) bildirin: bir char* tamponu (buffer), mevcut uzunluk için bir size_t ve toplam kapasite için bir size_t. Bir StringBuilder oluşturmak, ona metin eklemek, nihai dizeyi almak ve belleği serbest bırakmak için fonksiyon prototiplerini bildirin. Include guard'lar (başlık korumaları) gereklidir.
  • stringbuilder.c: StringBuilder sisteminizi uygulayın:
    • create_stringbuilder — yığında (heap) bir StringBuilder tahsis eder, tamponu 16 baytlık bir başlangıç kapasitesiyle başlatır, uzunluğu 0 olarak ayarlar ve tamponun boş bir dize (null-terminated) olarak başlamasını sağlar.
    • append — bir StringBuilder işaretçisi ve eklenecek bir dize alır. Gerekli yeni uzunluğu hesaplayın. Kapasiteyi aşarsa, kapasiteyi iki katına çıkarın (gerektiği kadar tekrarlayarak) ve tamponu büyütmek için realloc kullanın. Ardından strcat kullanarak yeni metni birleştirin.
    • get_string — dahili tampona bir işaretçi döndürür (salt okunur erişim).
    • free_stringbuilder — önce tamponu, ardından StringBuilder yapısının kendisini serbest bırakır.
  • main.c: Kaç tane dize ekleneceğini belirten bir tam sayı okuyun. Ardından fgets kullanarak her bir dizeyi okuyun ve StringBuilder'ınıza ekleyin. Tüm dizeler eklendikten sonra, get_string kullanarak birleştirilmiş tam dizeyi yazdırın. Son olarak, StringBuilder'ı serbest bırakın.

Bu challenge'da kullanılan iki anahtar fonksiyon:

  • realloc(ptr, new_size) — önceden tahsis edilmiş bir bellek bloğunu yeniden boyutlandırır. Mevcut bloğa bir işaretçi ve bayt cinsinden istenen yeni boyutu alır ve (muhtemelen taşınmış) yeniden boyutlandırılmış bloğa bir işaretçi döndürür. Tamponun büyümesi gerektiğinde bunu append içinde kullanın:
    sb->buffer = (char*)realloc(sb->buffer, sb->capacity);
  • fgets(buffer, size, stream) — bir giriş akışından bir karakter dizisine bir satır metin okur, bir yeni satır karakterinde veya size - 1 karakter okunduğunda durur. Yeni satır karakterini tamponda tutar, bu yüzden onu manuel olarak temizlemeniz gerekecektir. Her giriş dizesini okumak için bunu main.c içinde kullanın:
    fgets(line, sizeof(line), stdin);
    Sondaki yeni satırı temizlemek için: son karakterin '\n' olup olmadığını kontrol edin ve onu '\0' ile değiştirin.

Programınız şunları alacaktır:

  1. Eklenecek dize sayısı
  2. Ayrı satırlarda her bir dize

Girdiler 3, ardından Hello, , World olduğunda örnek çıktı:

Hello World

Girdiler 4, ardından C, is, a, great language! olduğunda örnek çıktı:

C is a great language!

Girdiler 1, ardından SingleString olduğunda örnek çıktı:

SingleString

Her ekleme işleminden sonra length alanını güncellemeyi unutmayın. Yeniden tahsisat gerekip gerekmediğini kontrol ederken, null sonlandırıcıyı hesaba katın — tamponun length + new_text_length + 1 baytlık alana ihtiyacı vardır. Dize uzunluklarını ölçmek için <string.h> kütüphanesinden strlen kullanın. Ayrıca, fgets ile dizeleri okumadan önce kalan yeni satır karakterini tüketmek için main.c içinde scanf'ten sonra getchar() çağırın.

Kendin dene

#include <stdio.h>
#include <stdlib.h>
#include "stringbuilder.h"

int main() {
    int n;
    scanf("%d", &n);
    getchar(); // sayıdan sonraki yeni satır karakterini tüket
    
    // TODO: create_stringbuilder() kullanarak bir StringBuilder oluşturun
    
    // TODO: n adet dizeyi okuyun ve her birini StringBuilder'a ekleyin
    // İpucu: Her satırı okumak için fgets veya benzerini kullanın
    // Eğer kullanırsanız, fgets'ten gelen yeni satır karakterini işlemeyi unutmayın
    
    // TODO: get_string() kullanarak birleştirilmiş dizenin tamamını yazdırın
    
    // TODO: free_stringbuilder() kullanarak StringBuilder'ı serbest bırakın
    
    return 0;
}

Object Oriented Programming bölümündeki tüm dersler