Menu
Coddy logo textTech

Контейнер фигур

Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 48 из 61.

challenge icon

Задание

Легко

Давайте доведём проект Shape Drawer до грандиозного финала! Вы создадите контейнер фигур, содержащий смешанную коллекцию Circle и Rectangle, а затем переберёте их, чтобы вычислить общую площадь, продемонстрировав истинную силу полиморфизма.

Основываясь на всём, что вы уже создали, ваш полный проект будет включать:

  • shape.h и shape.c: ваш базовый интерфейс Shape и функция process_shape.
  • circle.h и circle.c: ваша реализация Circle с её конструктором и вычислением площади.
  • rectangle.h и rectangle.c: ваша реализация Rectangle с её конструктором и вычислением площади.
  • main.c: именно здесь происходит волшебство. Вы создадите массив указателей Shape*, способный содержать фигуры любого типа. Заполните его смесью Circle и Rectangle, а затем пройдите по массиву, чтобы вычислить и вывести общую площадь всех фигур.

Ваша программа получит следующие входные данные:

  1. Количество создаваемых фигур
  2. Для каждой фигуры: индикатор типа (c для круга, r для прямоугольника), за которым следуют её размеры

Для каждой фигуры в вашем контейнере самостоятельно вызовите draw и area через указатель Shape* (shapes[i]->draw(shapes[i]), shapes[i]->area(shapes[i])) и добавьте площадь к текущей общей сумме. Здесь не используйте process_shape из shape.c: она выводит дополнительную строку Area: для каждой фигуры, которой нет в ожидаемом выводе. После обработки всех фигур выведите общую площадь с 2 знаками после запятой в формате Total Area: X.XX.

Пример с входными данными 3, затем c 5.0, r 4.0 3.0, c 2.0:

Drawing Circle with radius: 5.00
Drawing Rectangle with width: 4.00 and height: 3.00
Drawing Circle with radius: 2.00
Total Area: 103.11

Пример с входными данными 2, затем r 6.0 4.0, r 3.0 2.0:

Drawing Rectangle with width: 6.00 and height: 4.00
Drawing Rectangle with width: 3.00 and height: 2.00
Total Area: 30.00

Ключевая идея заключается в том, что ваш массив хранит указатели Shape*. Ему не важно, является ли каждый элемент Circle или Rectangle. Когда вы перебираете массив и вызываете draw и area через каждый указатель, автоматически выполняется правильная реализация — в зависимости от того, как была создана каждая фигура. Это полиморфизм в действии: один цикл, один интерфейс, несколько вариантов поведения.

Помните, что вам нужно хранить в массиве указатели на встроенные члены Shape ваших конкретных фигур. Используйте 3.14159 для π при вычислении площади круга.

Важно: чтение символа типа фигуры: после чтения количества фигур с помощью scanf("%d", &n) каждый последующий вызов для чтения символа типа должен пропускать оставшийся символ новой строки во входном буфере. Для этого используйте ведущий пробел в строке формата:

scanf(" %c", &type);  // note the space before %c

Без ведущего пробела scanf прочитает символ новой строки, оставшийся от предыдущего ввода, вместо ожидаемого c или r, из-за чего проверка типа фигуры незаметно завершится неудачей и не выведет ничего.

Попробуйте сами

#include <stdio.h>
#include <stdlib.h>
#include "shape.h"
#include "circle.h"
#include "rectangle.h"

int main() {
    // TODO: Прочитать количество фигур
    // TODO: Выделить массивы для circles, rectangles и указателей Shape*
    // TODO: Пройти циклом по каждой фигуре, прочитать её тип и размеры,
    //       создать фигуру и сохранить указатель на её базу в массив shapes
    // TODO: Пройти циклом по массиву shapes, вызвать shapes[i]->draw(...) и
    //       shapes[i]->area(...) напрямую и накопить общую площадь
    //       (не вызывайте process_shape: он печатает лишнюю строку Area)
    // TODO: Вывести общую площадь в формате: Total Area: X.XX
    // TODO: Освободить выделенную память
    return 0;
}

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C