rusi/strings.c

253 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================
// Управление динамическим массивом строк
// ============================================================
#включить "руси.з"
#включить <stdio.h> // стандартная библиотека
#включить <stdlib.h> // стандартная библиотека
#включить <stdarg.h> // стандартная библиотека
#включить <string.h> // стандартная библиотека
// ============================================================
// Управление динамическим массивом строк
// ============================================================
пусто массив_строк_добавить(МассивСтрок *массив, символ *строка) {
если (!массив) возврат;
// Инициализация массива при первом использовании
если (!массив->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;
}