Повторение: обобщенный массив
Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 53 из 61.
Задание
ЛегкоДавайте создадим контейнер GenericArray — гибкую структуру данных, которая может хранить смесь целых чисел и строк в одной коллекции, используя указатели void*.
Вы организуете свой код в трех файлах:
generic_array.h: Определите структуруGenericArrayс тремя членами: массивvoid**для хранения указателей,intдля текущего количества элементов (count) иintдля емкости (capacity). Объявите прототипы функций для создания массива, добавления элементов, получения элементов по индексу и освобождения массива.generic_array.c: Реализуйте функциональность вашего контейнера:create_array— выделяет память для GenericArray с заданной начальной емкостью и инициализирует count значением 0add_element— сохраняет указательvoid*в следующую доступную ячейку и увеличивает count (предположим, что емкости достаточно)get_element— возвращаетvoid*по указанному индексуfree_array— освобождает массив элементов и саму структуру GenericArray
main.c: Продемонстрируйте работу вашего универсального массива, сохраняя в нем как целые числа, так и строки. Считайте количество элементов для добавления, затем для каждого элемента считайте индикатор типа (iдля целого числа,sдля строки), а затем само значение. После добавления всех элементов переберите массив и выведите каждое значение. Для целых чисел выводите число напрямую. Для строк выводите текст напрямую.
Ваша программа получит:
- Количество добавляемых элементов
- Для каждого элемента: индикатор типа (
iилиs), за которым следует значение
При добавлении целых чисел выделите память для int и сохраните указатель. При добавлении строк выделите память и скопируйте строку. При извлечении выполните приведение обратно к соответствующему типу для вывода на экран.
Важно: Чтобы отслеживать типы для вывода, вы можете использовать простой параллельный массив индикаторов типов в main или сохранять символ индикатора типа вместе с каждым элементом.
Пример вывода, когда входные данные: 3, затем i 42, s Hello, i 100:
42
Hello
100Пример вывода, когда входные данные: 4, затем s World, s Generic, i -5, s Arrays:
World
Generic
-5
ArraysНе забудьте использовать include guards в заголовочном файле. Самому контейнеру не нужно знать, какие типы он хранит — он просто содержит указатели void*. Ответственность за знание типа ложится на код, который добавляет и извлекает элементы.
Попробуйте сами
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "generic_array.h"
int main() {
int n;
scanf("%d", &n);
// TODO: Создайте GenericArray с емкостью n
// TODO: Создайте параллельный массив для отслеживания типов (массив char размера n)
// TODO: Для каждого элемента:
// - Считайте индикатор типа (i или s)
// - Считайте значение
// - Если целое число: выделите память для int, сохраните значение, добавьте в массив
// - Если строка: выделите память для строки, скопируйте значение, добавьте в массив
// - Сохраните индикатор типа в вашем параллельном массиве
// TODO: Пройдитесь по массиву и выведите каждый элемент
// - Проверьте тип из вашего параллельного массива
// - Приведите void* обратно к соответствующему типу и выведите
// TODO: Освободите всю выделенную память (целые числа, строки и сам массив)
return 0;
}
Все уроки раздела Object Oriented Programming
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик7Указатели на функции
Объявление указателей на функцииВызов указателей на функцииTypedef для указателей на функцииПередача функций в качестве аргументовИтоги: Диспетчеризация калькулятора10Обобщенные контейнеры
Повторение: указатели voidОбобщенная оберткаОбобщенный обмен (Swap)Обобщенное сравнениеПовторение: обобщенный массив2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация круга