10.27 Память на куче
Повторение:
Бывает по-разному, но обычно у запущенной программы в ОС:
- ↓ стек
- недоступная память
- ↑ куча
- статическая память
Почему так? Потому что!!! (+потому что виртуальная память, а так удобнее)
strlen, strlcpy и strlcat: ввести число n и строку, сформировать и вывести строку, повторенную n раз
Тип void * и двойные ссылки; malloc() и calloc()
Был ли void * на лекциях? Для чего нужен?
Написать функцию char *strmul(char *str, int mul), которая заказывает память для результата и возвращает строку str, повторенную mul раз
Тип int ** и ему подобные — для чего нужны?
Подсказка: все параметры передаются в функцию по значению
Преобразовать strmul() в функцию strmulinput(char **dst, int *size, int mul), которая вводит строку (не длиннее 100), формирует строку ввода, повторенную mul раз, и помещает указатель на строку и размер в dst и size. Вывести *dst и *size Попробовать добавить наш любимый -fsanitize=address
А вот! free
Кто маллочит — тот и фрит!
realloc: «увеличение» выделенного буфера
это не увеличение! выделяется новый (больший) буфер, в него копируется старый, старый уходит в free(), возвращается новый
Написать функцию char *getlines(int n), которая вводит n строк в одну (\n удалять не надо), возвращая указатель на эту многострочную строку. Проверить, всё ли в порядке с -fsanitize=address Подсказка: fgets() → realloc() → strcat() и так по кругу
Ввод строки произвольного размера
Работа getline
Ввод строки произвольного размера (для этого надо инициализировать приёмник NULL-ом)
(требуется free()):
char *s; size_t bufsize; ssize_t length; s = NULL; length = getline(&s, &bufsize, stidn); … free(s);
Если s != NULL, а вводимая строка больше bufsize, произойдёт realloc()
Переписать getlines() с использованием getline(). Проверить, всё ли в порядке с -fsanitize=address
Массив строк
Инициализированный массив строк
Ввести n, затем создать массив на n строк и ввести их; вывести только строки, в которых содержится первый символ последней строки (strchr) Не забыть free() для них для всех!
Д/З (предварительное)
Ввести две строки, вывести их наиболее длинную общую подстроку. Если таких несколько, вывести ту, что следует раньше в первой строке. TODO задать максимальный размер так, чтобы годился неэффективный алгоритм
01uj12qawsed23tgyhej34 uj-tgyhej-qawsed
→qawsed
Ввести последовательность «плюсфрагментов» — цепочек произвольных символов, разделённых символом '+'. Вывести только фрагменты, целиком состоящие из латинских гласных a, e, i, o, u. Внутри фрагмента могут встречаться пробелы и переводы строки. Совет: [[man3:getdelim]] и [[man3:strspn]]
- Ввести массив строк и отсортировать их по количеству запятых в них любым алгоритмом устойчивой сортировки. Вывести отсортированные строки, каждую на своей строке экрана.
- Алгоритм устойчивой сортировки сохраняет исходный порядок среди элементов, имеющих одинаковое значение критерия сортировки. Годится «пузырёк»
Поиск с заменой. Ввести три строки — s, a и b. Вывести строку, в которой все вхождения a будут заменены на b. Повторную замену (в случае, когда после замены образуются новые вхождения) делать не надо.
Поиск и замену вести в один проход среди найденных вхождений a в s в порядке от начала к концу. Например, при s="11111", a="11", b="2" результатом замены должно быть "221".
Нет повторной замены: "aba" → "ca" в строке "ababa". Вхождение aba в ababa одно (за первым aba следует только ba) ⇒ результат поиска с заменой — "caba".
