Menu
Coddy logo textTech

Dynamiczne tworzenie ciągów znaków

Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 59 z 61.

challenge icon

Wyzwanie

Łatwy

Zbudujmy StringBuilder: dynamiczny kontener na ciąg znaków, który automatycznie zwiększa swój rozmiar podczas dodawania tekstu. To praktyczne narzędzie łączy dynamiczne zarządzanie pamięcią ze wzorcami OOP, które opanowałeś w trakcie tego kursu.

Uporządkujesz kod w trzech plikach:

  • stringbuilder.h: Zadeklaruj strukturę StringBuilder z trzema polami: buforem char*, wartością size_t określającą bieżącą długość oraz wartością size_t określającą całkowitą pojemność. Zadeklaruj prototypy funkcji tworzącej obiekt StringBuilder, dodającej do niego tekst, pobierającej końcowy ciąg znaków i zwalniającej pamięć. Strażniki nagłówka są niezbędne.
  • stringbuilder.c: Zaimplementuj system StringBuilder:
    • create_stringbuilder: alokuje obiekt StringBuilder na stercie, inicjalizuje bufor początkową pojemnością 16 bajtów, ustawia długość na 0 i zapewnia, że bufor zaczyna się od pustego ciągu znaków (zakończonego znakiem null)
    • append: przyjmuje wskaźnik do obiektu StringBuilder i ciąg znaków do dodania. Oblicz nową wymaganą długość. Jeśli przekracza ona pojemność, podwajaj pojemność (wielokrotnie w razie potrzeby) i użyj realloc, aby powiększyć bufor. Następnie połącz nowy tekst za pomocą strcat
    • get_string: zwraca wskaźnik do wewnętrznego bufora (dostęp tylko do odczytu)
    • free_stringbuilder: najpierw zwalnia bufor, a następnie samą strukturę StringBuilder
  • main.c: Wczytaj liczbę całkowitą określającą, ile ciągów znaków należy dodać. Następnie wczytaj każdy ciąg za pomocą fgets i dodaj go do obiektu StringBuilder. Po dodaniu wszystkich ciągów wypisz kompletny złożony ciąg za pomocą get_string. Na koniec zwolnij obiekt StringBuilder.

Dwie kluczowe funkcje używane w tym wyzwaniu:

  • realloc(ptr, new_size): zmienia rozmiar wcześniej zaalokowanego bloku pamięci. Przyjmuje wskaźnik do istniejącego bloku i nowy żądany rozmiar w bajtach, a zwraca wskaźnik do bloku o zmienionym rozmiarze (który mógł zostać przeniesiony). Użyj jej w append, gdy bufor trzeba powiększyć:
    sb->buffer = (char*)realloc(sb->buffer, sb->capacity);
  • fgets(buffer, size, stream): wczytuje wiersz tekstu ze strumienia wejściowego do tablicy znaków, kończąc na znaku nowej linii lub po wczytaniu size - 1 znaków. Zachowuje znak nowej linii w buforze, więc trzeba go usunąć ręcznie. Użyj jej w main.c, aby wczytać każdy ciąg wejściowy:
    fgets(line, sizeof(line), stdin);
    Aby usunąć końcowy znak nowej linii: sprawdź, czy ostatnim znakiem jest '\n', i zastąp go znakiem '\0'.

Twój program otrzyma:

  1. Liczbę ciągów znaków do dodania
  2. Każdy ciąg w osobnym wierszu

Przykładowy wynik, gdy dane wejściowe to 3, a następnie Hello, , World:

Hello World

Przykładowy wynik, gdy dane wejściowe to 4, a następnie C, is, a, great language!:

C is a great language!

Przykładowy wynik, gdy dane wejściowe to 1, a następnie SingleString:

SingleString

Pamiętaj, aby aktualizować pole length po każdej operacji dodawania. Sprawdzając, czy potrzebna jest ponowna alokacja, uwzględnij znak null: bufor musi pomieścić length + new_text_length + 1 bajtów. Użyj strlen z <string.h>, aby zmierzyć długości ciągów znaków. Wywołaj również getchar() po scanf w main.c, aby usunąć pozostały znak nowej linii przed wczytywaniem ciągów za pomocą fgets.

Spróbuj swoich sił

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

int main() {
    int n;
    scanf("%d", &n);
    getchar(); // pobierz znak nowej linii po liczbie
    
    // TODO: Utwórz StringBuilder za pomocą create_stringbuilder()
    
    // TODO: Wczytaj n ciągów znaków i dołącz każdy z nich do StringBuilder
    // Wskazówka: Użyj fgets lub podobnej funkcji, aby wczytać każdą linię
    // Pamiętaj o obsłużeniu znaku nowej linii z fgets, jeśli jej używasz
    
    // TODO: Wypisz cały złożony ciąg znaków za pomocą get_string()
    
    // TODO: Zwolnij StringBuilder za pomocą free_stringbuilder()
    
    return 0;
}

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C online