Dynamiczne tworzenie ciągów znaków
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 59 z 61.
Wyzwanie
ŁatwyZbudujmy 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ęStringBuilderz trzema polami: buforemchar*, wartościąsize_tokreślającą bieżącą długość oraz wartościąsize_tokreś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żyjrealloc, aby powiększyć bufor. Następnie połącz nowy tekst za pomocąstrcatget_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ąfgetsi 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 wappend, 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 wczytaniusize - 1znaków. Zachowuje znak nowej linii w buforze, więc trzeba go usunąć ręcznie. Użyj jej wmain.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:
- Liczbę ciągów znaków do dodania
- Każdy ciąg w osobnym wierszu
Przykładowy wynik, gdy dane wejściowe to 3, a następnie Hello, , World:
Hello WorldPrzykł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:
SingleStringPamię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
1Podstawy programowania modularnego
Pliki nagłówkoweZabezpieczenia przed wielokrotnym dołączeniemPliki źródłoweFunkcje statycznePodsumowanie: kalkulator modularny4Enkapsulacja
Koncepcja niejawnych wskaźnikówDefiniowanie niejawnych strukturGettery i setteryWalidacja w setterachPowtórka: tajemnicze pudełko2Obiekty i metody
Struktury jako obiektyWskaźnik „self”Poprawność constWskaźnik czy wartośćMetody pomocniczePodsumowanie: menedżer punktów5Projekt: Proste konto bankowe
Konfiguracja projektuImplementacja konta8Polimorfizm
Wskaźniki do funkcji w strukturachSymulowanie metodKoncepcja interfejsuImplementowanie interfejsówIteracja polimorficznaPodsumowanie: Greeter11Wzorce projektowe w C
Wzorzec SingletonWzorzec fabrykiWzorzec iteratoraPodsumowanie: fabryka loggera3Cykl życia obiektu
Wzorzec konstruktoraWzorzec destruktoraInicjalizacja na stosieKopia głębokaPodsumowanie: klasa opakowująca ciąg znaków6Dziedziczenie przez kompozycję
Osadzanie strukturZasada pierwszego elementuDostęp do elementów klasy nadrzędnejKonwersja w górę hierarchiiPodsumowanie: hierarchia kształtów9Projekt: Rysownik kształtów
Przegląd projektuImplementacja kołaImplementacja prostokątaZastosowanie polimorfizmuKontener kształtówPoćwicz samodzielnie: Kompilator C online