Menu
Coddy logo textTech

Динамический построитель строк

Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 59 из 61.

challenge icon

Задание

Легко

Давайте создадим StringBuilder — динамический контейнер для строк, который автоматически увеличивается при добавлении текста. Это практическая утилита, сочетающая динамическое управление памятью с паттернами ООП, которые вы освоили в этом курсе.

Вы организуете свой код в трех файлах:

  • stringbuilder.h: Объявите структуру StringBuilder с тремя членами: буфером char*, size_t для текущей длины и size_t для общей емкости. Объявите прототипы функций для создания StringBuilder, добавления текста в него, получения итоговой строки и освобождения памяти. Использование include guards обязательно.
  • stringbuilder.c: Реализуйте вашу систему StringBuilder:
    • create_stringbuilder — выделяет StringBuilder в куче, инициализирует буфер с начальной емкостью 16 байт, устанавливает длину в 0 и гарантирует, что буфер начинается как пустая строка (с нулевым завершителем)
    • 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 после каждой операции добавления. При проверке необходимости перераспределения памяти учитывайте нулевой завершитель — буферу требуется место для 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