// ============================================================ // Управление динамическим массивом строк // ============================================================ #включить "руси.з" #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека #включить // стандартная библиотека // ============================================================ // Управление динамическим массивом строк // ============================================================ пусто массив_строк_добавить(МассивСтрок *массив, символ *строка) { если (!массив) возврат; // Инициализация массива при первом использовании если (!массив->data) { массив->data = (символ **)calloc(8, размер(символ *)); если (!массив->data) { // Ошибка выделения памяти - выходим возврат; } массив->capacity = 8; массив->len = 0; } // Расширение массива при необходимости если (массив->capacity == массив->len) { size_t новая_ёмкость = массив->capacity * 2; символ **новые_данные = (символ **)realloc(массив->data, размер(символ *) * новая_ёмкость); если (!новые_данные) { // Ошибка перевыделения памяти возврат; } массив->data = новые_данные; массив->capacity = новая_ёмкость; // Инициализация новых элементов нулями для (size_t ш = массив->len; ш < массив->capacity; ш++) { массив->data[ш] = NULL; } } // Добавление строки массив->data[массив->len++] = строка; } // ============================================================ // Форматирование строки в стиле printf // ============================================================ символ *формат(символ *строка_формата, ...) { если (!строка_формата) возврат NULL; символ *буфер = NULL; size_t разм_буфера = 0; // Открываем поток в память FILE *поток = open_memstream(&буфер, &разм_буфера); если (!поток) { возврат NULL; } // Форматируем вывод va_list арг; va_start(арг, строка_формата); цел рез = vfprintf(поток, строка_формата, арг); va_end(арг); // Закрываем поток (это освобождает внутренние ресурсы) fclose(поток); // Проверяем успешность записи если (рез < 0) { free(буфер); возврат NULL; } возврат буфер; } // ============================================================ // Дополнительные полезные функции для работы со строками // ============================================================ // Создает копию строки с выделением памяти символ *строка_дублировать(конст символ *исходная) { если (!исходная) возврат NULL; size_t длина = strlen(исходная) + 1; символ *копия = (символ *)malloc(длина); если (!копия) возврат NULL; memcpy(копия, исходная, длина); возврат копия; } // Объединяет две строки в новую символ *строка_склеить(конст символ *первая, конст символ *вторая) { если (!первая) возврат строка_дублировать(вторая); если (!вторая) возврат строка_дублировать(первая); size_t дл1 = strlen(первая); size_t дл2 = strlen(вторая); символ *рез = (символ *)malloc(дл1 + дл2 + 1); если (!рез) возврат NULL; memcpy(рез, первая, дл1); memcpy(рез + дл1, вторая, дл2 + 1); возврат рез; } // Объединяет три строки в новую символ *строка_склеить3(конст символ *первая, конст символ *вторая, конст символ *третья) { если (!первая && !вторая && !третья) возврат NULL; если (!первая) возврат строка_склеить(вторая, третья); если (!вторая) возврат строка_склеить(первая, третья); если (!третья) возврат строка_склеить(первая, вторая); size_t дл1 = strlen(первая); size_t дл2 = strlen(вторая); size_t дл3 = strlen(третья); символ *рез = (символ *)malloc(дл1 + дл2 + дл3 + 1); если (!рез) возврат NULL; memcpy(рез, первая, дл1); memcpy(рез + дл1, вторая, дл2); memcpy(рез + дл1 + дл2, третья, дл3 + 1); возврат рез; } // Освобождает массив строк пусто массив_строк_освободить(МассивСтрок *массив) { если (!массив) возврат; если (массив->data) { // Освобождаем каждую строку для (size_t ш = 0; ш < массив->len; ш++) { если (массив->data[ш]) { free(массив->data[ш]); массив->data[ш] = NULL; } } // Освобождаем массив указателей free(массив->data); массив->data = NULL; } массив->len = 0; массив->capacity = 0; } // Очищает массив строк без освобождения памяти под него пусто массив_строк_очистить(МассивСтрок *массив) { если (!массив || !массив->data) возврат; // Освобождаем только строки, но не массив указателей для (size_t ш = 0; ш < массив->len; ш++) { если (массив->data[ш]) { free(массив->data[ш]); массив->data[ш] = NULL; } } массив->len = 0; } // Получает строку по индексу с проверкой границ символ *массив_строк_получить(конст МассивСтрок *массив, size_t инд) { если (!массив || !массив->data || инд >= массив->len) { возврат NULL; } возврат массив->data[инд]; } // Устанавливает строку по индексу с проверкой границ бул массив_строк_установить(МассивСтрок *массив, size_t инд, символ *строка) { если (!массив || !массив->data || инд >= массив->len) { возврат ложь; } // Освобождаем старую строку если (массив->data[инд]) { free(массив->data[инд]); } массив->data[инд] = строка; возврат истина; } // Вставляет строку в указанную позицию бул массив_строк_вставить(МассивСтрок *массив, size_t поз, символ *строка) { если (!массив || !строка) возврат ложь; если (поз > массив->len) возврат ложь; // Добавляем в конец если (поз == массив->len) { массив_строк_добавить(массив, строка); возврат истина; } // Вставляем в середину - сначала добавляем элемент в конец массив_строк_добавить(массив, NULL); если (!массив->data) возврат ложь; // Сдвигаем элементы вправо для (size_t ш = массив->len - 1; ш > поз; ш--) { массив->data[ш] = массив->data[ш - 1]; } массив->data[поз] = строка; возврат истина; } // Удаляет строку по индексу бул массив_строк_удалить(МассивСтрок *массив, size_t инд) { если (!массив || !массив->data || инд >= массив->len) { возврат ложь; } // Освобождаем удаляемую строку если (массив->data[инд]) { free(массив->data[инд]); } // Сдвигаем элементы влево для (size_t ш = инд; ш < массив->len - 1; ш++) { массив->data[ш] = массив->data[ш + 1]; } массив->len--; массив->data[массив->len] = NULL; возврат истина; } // Ищет строку в массиве ssize_t массив_строк_найти(конст МассивСтрок *массив, конст символ *строка) { если (!массив || !массив->data || !строка) возврат -1; для (size_t ш = 0; ш < массив->len; ш++) { если (массив->data[ш] && strcmp(массив->data[ш], строка) == 0) { возврат (ssize_t)ш; } } возврат -1; } // Проверяет, содержит ли массив строку бул массив_строк_содержит(конст МассивСтрок *массив, конст символ *строка) { возврат массив_строк_найти(массив, строка) >= 0; }