C++ — SOS!!! Задача на C++


Новые сложные задачи на C++. Герб Саттер

Данная книга представляет собой продолжение вышедшей ранее книги Решение сложных задач на C++.
В форме задач и их решений рассматриваются современные методы проектирования и программирования на C++. В книге сконцентрирован богатый многолетний опыт программирования на C++ не только самого автора, но и всего сообщества программистов на C++, так что некоторые рекомендации автора могут показаться неожиданными даже опытным программистам-профессионалам.
Автор рассматривает и конкретные методики, приемы и идиомы программирования, однако основная тема книги — это стиль программирования, причем в самом широком понимании этого слова.
Особое внимание во всех задачах книги уделено вопросу проектирования, которое должно обеспечить максимальную надежность, безопасность, производительность и сопровождаемость создаваемого программного обеспечения. Книга рассчитана в первую очередь на профессиональных программистов с глубокими знаниями языка, однако она будет полезна любому, кто захочет углубить свои знания в данной области.

Если вам понравилась эта книга поделитесь ею с друзьями, тем самым вы помогаете нам развиваться и добавлять всё больше интересных и нужным вам книг!

Ledrunning ╔═(███)═╗

Electronics and coding

Типовые задачи по С++ для новичков (часть 4.1, указатели)

Всем привет! Наконец-то я добрался до написания очередной статьи, и в этот раз мы добрались до указателей! Сущность указателя проста, но понять ее достаточно сложно, но можно.

Начнем с того, что все переменные нашей программы при выполнении хранятся в оперативной памяти персонального компьютера (встраиваемой системы, гаджета и тд). Оперативную память компьютера можно представить в виде последовательности пронумерованных однобайтовых ячеек, с которыми можно работать по отдельности или блоками(кстати статья по алгоритмам управления памятью в операционных системах). Каждая переменная при выполнении программы будет иметь свой адрес в оперативной памяти. Приближенная картина:

Адреса памяти классически указывают в шеснадцатиричном виде (HEX).

Практически все современные языки программирования являются безопасными, так как непосредственно напрямую работать с памятью ОЗУ персонального компьютера или гаджета они не позволяют, правда в некоторых языках, таких как C# такая возможность присутствует, если разработчик понимает всю ответственность за написанный код. Для того что бы работать непосредственно с памятью ОЗУ необходимо код поместить в блок unsafe <> и в настройках проекта установить галочку: «разрешить небезопасный код». Язык С++ это язык с богатой историей, наследник языка Си, в котором так же присутствовали указатели, они автоматически и перекочевали в плюсы оттуда. При прямой работе с памятью возрастает скорость работы приложения и ее КПД, но и процесс разработки таких программ очень сложный. В то время как в современных языках существует автоматический сборщик мусора, который автоматически следит за ненужными объектами в оперативной памяти и удаляет их по мере необходимости.

Указатель (англ. Pointer) — это такая же переменная, которую необходимо объявить, содержащая адрес ячейки памяти. Указатель не несет информации о содержимом объекта, а содержит сведения о том, где размещен объект, то есть его адрес. Указатель может ссылаться на переменную, зная ее физический адрес в памяти. Указатели широко используются в программировании на языке Си и С++. Особенно указатели помогают работать с массивами (передача указателя на массив в функцию) и динамическими массивами, когда по ходу программы мы не знаем размерность массива и можем изменять его.

Что бы объявить переменную указатель нам необходимо сделать так:

Как вы уже успели заметить, в объявлении присутствует оператор *; Так же обычно принято при именовании переменной указателя перед названием переменной писать приставку pt. Например: pt_var, pt_time, ptName и тд…
Существует еще один оператор для указателей, это & (амперсанд) или операция взятия адреса.

  • операция * (звездочка) — позволяет получить значение объекта по его адресу — определяет значение переменной, которое содержится по адресу, находящейся в указателе;
  • операция & (амперсанд) — позволяет определить адрес переменной.

При объявление можно использовать разный стиль, компилятор в любом случае поймет, что это указатель:

Попробуем применить оба оператора и напишем небольшую консольную программу в Visual Studio:

Если запустить нашу программу, то мы увидим следующее:

Число в шестнадцатиричном виде в консоли, являются адресом переменной int var. Размер указателя равен четырем байтам.

Теперь давайте немного изменим нашу программу:

Применив оператор * на 16 строчке на выходе мы получим уже не адрес переменной var, а ее конкретное значение, в данном случае 515. Такая операция называется разыменование указателя.

Давайте теперь попробуем произвести операцию сложения нашего pt_var указателя с обычной переменной значимого типа:

Как мы видим, значение pt_var изменилось на два пункта, так как мы и запланировали. А вот переменная var не изменилась:

Итак мы рассмотрели основные принципы указателя, ничего страшного не правда-ли? В конце первой части я снова вернусь к оперативной памяти компьютера.

ОЗУ, с которой работает программа, подразделяется на три вида: статическую, автоматическую и динамическую.

Статическая память — это область памяти, выделяемая при запуске программы до вызова функции main из свободной оперативной памяти для размещения глобальных и статических объектов, а также объектов, определённых в пространствах имён.

Автоматическая память (стек англ. Stack) — это специальный отдел памяти, который резервируется до вызова функции main из свободной оперативной памяти и используемый в дальнейшем для размещения локальных объектов: объектов, определяемых в теле функций и получаемых функциями через параметры в момент вызова (переменные, поля структур и тд.). И в этой области хранятся переменные значимого типа (примитивные типы: int, char, float, double и тд.)

Динамическая память (куча — англ. Heap) — это совокупность блоков памяти, выделяемых из доступной свободной оперативной памяти непосредственно во время выполнения программы под размещение конкретных объектов. В ней хранятся ссылочные типы и объекты классов. Для того, что бы выделить память в куче, в языке C++ (и не только) присутствует оператор new.

И вот тут проявляются определенные проблемы. Так как место в памяти мы выделили, объект там хранится на протяжении выполнении программы и постепенно эта самая память может переполнится, такой эффект называется утечкой памяти, так же существует еще одна проблема — фрагментация памяти. Примеры таких проблем вы можете посмотреть в первой статье цикла по С++. В языках Си и С++ программист сам должен следить за объектами для которых он выделяет память, и в случае необходимости удалять из памяти. Для этой цели в С++ служит оператор delete. Когда нам не нужен будет *pt_var, необходимо сделать операцию delete pt_var (Важно! Без оператора *) .


При первом запуске мы видим, что у нас какой-то мусор, после инициализации и выделения памяти, мы уже видим адрес в куче и значение:

Цукерберг рекомендует:  Unity - Софт для 2D анимации в играх

Ну а после удаления в строке 16, мы снова получаем мусор в отладчике. А это значит что мы освободили память в куче для других объектов.

Ну как вам первое знакомство с указателями? Интересно? Тогда продолжение следует…

Решения задач по программированию на C++

На этой странице отображены ссылки на статьи с решениями различных популярных задач по программированию на языке программирования C++. Раздел пополняется ссылками на новые статьи, оставайтесь в курсе, подписавшись на RSS.

Если вы не знакомы с программированием на C++,то почитайте статью о том, что нужно для начала программирования на C++.

Решения задач по программированию на языке C++

Программа для решения факториала на C++ — в статье описана реализация алгоритмов рекурсивного нахождения значения факториала и через циклы на языке программирования C++.

Программа для решения квадратных уравнений на C++ — в статье описывается как написать программу для решения квадратных уравнений на C++, нахождение дискриминанта, проверка на существование решения, нахождение двух корней.

Алгоритм пузырьковой сортировки одномерного массива на C++ — в статье описывается сам алгоритм пузырьковой сортировки, показывается как отсортировать массив методом пузырьковой сортировки на C++.

Считывание строк из файла и запись в массив на C++ — в статье описывается как работать с файлами, как считывать данные из файла в массив.

QFile и файлы. Чтение и запись строк в файл. — а здесь описано как работать с записью и считыванием из файла с помощью фреймворка Qt.

Найти максимальный и минимальный элемент массива на C++ — в статье подробно разобрано решение задачи по нахождению минимального и максимального элемента в массиве.

Рекурсивное нахождение чисел Фибоначчи на C++ — в статье описано решение задачи по нахождению чисел Фибоначчи рекурсивным способом.

Проверить, является ли строка палиндромом на C++ — в статье рассказывается что такое палиндром, как реализовать функцию для проверки строки на палиндромность. И приведен код программы, использующей эту функцию.

Этот список со временем будет пополняться новыми решениями.

Задачи по программированию на C++

Задача 1. Телешоу. Решение на C++

В новом интеллектуальном телешоу участнику, проходящему в суперфинал, предлагается следующая игра: на каждом из n секторов большого барабана записывается буква латинского алфавита li. После минуты на размышления игрок указывает одну из позиций на барабане i. Его выигрыш вычисляется по такому правилу: для каждой позиции j меньшее из расстояний по и против часовой стрелке от i до j, измеренное в секторах, умножается на абсолютною величину разности номеров в алфавите букв li и lj , после чего все такие величины суммируются.

А Вы можете написать программу, находящую способ получения наибольшего выигрыша?

Первая строка входного файла INPUT.TXT содержит натуральное число n (1 ≤ n ≤ 100000) — размер барабана. Во второй строке задаются разделенные пробелами строчные латинские буквы, записанные на барабане.

В первой строке выходного файла OUTPUT.TXT выведите наибольший выигрыш, который можно получить при заданном расположении букв на барабане. Во второй строке выведите номер какого-нибудь из секторов, на который игрок должен для этого указать.

Задача 2. Треугольники — 4. Решение на C++

У Сени есть шоколадка, составленная из нескольких прилегающих друг к другу плиточек в форме правильных треугольников. Его брат Женя нашел эту шоколадку и решил сделать ее треугольной, съев все лишнее (ведь треугольные шоколадки намного вкуснее). Сколькими способами он может это сделать?

Например, из такой шоколадки:

можно сделать треугольную шоколадку со стороной 1 шестью способами или шоколадку со стороной 2 двумя способами. Итого восемь способов.

Входные данные

Форма шоколадки задается ее границей в порядке обхода по часовой стрелке. Первая строка входного файла INPUT.TXT содержит число n — количество отрезков на границе (1 ≤ n ≤ 5000). Далее n чисел от 1 до 6, задающих направление движения по границе (см. рисунок).


Выходные данные

В выходной файл OUTPUT.TXT выведите одно число — количество способов.

Задача 3. Узор. Решение на C++

В комнате решили сделать паркетный пол. Причем есть задумка выложить на полу некоторый узор. Плитки паркета, которыми выкладывается пол комнаты, состоят из квадратиков 1×1, каждый из которых может быть либо белым, либо черным. В свою очередь, комната имеет размеры NxM. На плане комнаты указано, какой квадрат комнаты какого цвета должен быть. Существует несколько форм паркетных плиток:

Квадратики одной паркетной плитки могут быть окрашены по-разному. Может существовать несколько типов плиток одинаковой формы, но окрашенных по-разному. Плитки разных типов могут иметь разную стоимость. Количество плиток каждого типа не ограничено. Плитки разрешается как угодно поворачивать (на углы, кратные 90 градусам). Не разрешается разламывать плитки, а также класть их лицевой стороной вниз.

Изначально, какая-то часть пола может уже быть выложена плиткой. Требуется определить минимальную стоимость плитки, необходимой для того, чтобы замостить оставшуюся часть комнаты.

Входные данные

В первой строке входного файла INPUT.TXT записаны три числа: N, M (размеры комнаты) и K (количество доступных видов плитки). 1

— это число от 1 до 4, описывающее форму плитки (см. рисунок выше)

— это натуральное число, не превосходящее 10000, задающее стоимость одной плитки такого типа

— это от одного до трех чисел 0 или 1. Количество чисел совпадает с количеством квадратиков, из которых состоит плитка. Числа задают цвета квадратиков плитки в том порядке, в каком квадратики пронумерованы на рисунке.

Примеры решений задач на C/C++

Задача 1. Односвязный список. Реализуйте список строк. Напишите функции для подсчета количества слов в списке:
а. начинающихся и оканчивающихся одной и той же буквой
б. начинающихся с той же буквы, что и следующее слово
в. совпадающих с последним словом.

Задача 2. Двумерный массив. Характеристикой столбца целочисленной матрицы назовем сумму модулей его отрицательных нечетных элементов. Переставляя столбцы заданной матрицы, расположить их в соответствии с ростом характеристик.

Задача 3. Калькулятор. Реализовать на С++ калькулятор с возможностью выполнения четырех арифметических действий. У пользователя запрашивать аргументы и знак операции (символ). Программу «зациклить» — после вывода результата предлагать пользователю произвести вычисления еще раз. Выход из программы производить по нажатию клавиши q. Осуществить проверки: 1) деления на ноль (в этом случае выводить предупреждающее сообщение и запрашивать делитель еще раз); 2) корректности ввода знака операции (в этом случае просить ввести корректный знак операции).

Задача 4. Работа со строками. На входе массив строк и его длина. Каждая строка имеет вид: «Фамилия Имя Отчество» (разделяются одним пробелом). Функция должна возвращать новый массив, состоящий из строк вида «И.О. Фамилия».

Где найти интересные задачи по с++ разного уровня?

Не знаю что такое «озов» похоже на город какой-то, но тогда неясно отчего с маленькой буквы. Говорят в древности на Руси алфавит ( ну или буквица ) начинался с буквы Аз, откуда вероятно и пошли азы.

По сути вопроса — любая программа длиннее тысячи строк будет представлять собой вполне себе задачу среднего уровня. Поставьте себе задачу и реализуйте ее на си++. Например напишите свой http/ftp сервер или клиент. Создайте простую игру, или удобное приложение.

Можно конечно искать задачи где нужно «с помощью указателей» сделать что-либо, или «написать иерархию классов с виртуальными функциями» но имхо это полная ерунда. Она может помочь разве что закрепить синтаксис языка, но не дает понимания того зачем конкретная фича языка нужна.
А вот создание собственной объемной программы — такое понимание дает в полной мере. Когда вы напишите 20й класс похожий на остальные, то зададитесь вопросом как это можно сделать проще, перечитаете учебник языка и поймете зачем нужны например шаблоны или виртуальные функции.
Если до написания программы ( а лучше во время ) вы будете штудировать учебник языка — будет совсем хорошо.

Цукерберг рекомендует:  Основы SMM и SMM-стратегия. Создание SMM-стратегии

Герб Саттер: Решение сложных задач на C++. 87 головоломных задач с решениями

Exceptional C++. 87 New Engineering Puzzles, Programming Problems, and Solutions

Мы пришлем письмо о полученном бонусе, как только кто-то воспользуется вашей подборкой. Проверить баланс всегда можно в «Личном пространстве»

Мы пришлем письмо о полученном бонусе, как только кто-то воспользуется вашей ссылкой. Проверить баланс всегда можно в «Личном пространстве»

Аннотация к книге «Решение сложных задач на C++. 87 головоломных задач с решениями»

В книге «Решение сложных задач на С++» объединены две широко известные профессионалам в области программирования на C++ книги Герба Саттера Exceptional C++ и More Exceptional C++ , входящие в серию книг C++ In-Depth, редактором которой является Бьерн Страуструп, создатель языка C++. Материал книги «Решение сложных задач на С++» составляют переработанные задачи серии Guru of the Week, рассчитанные на читателя с достаточно глубоким знанием C++, однако книга будет полезна каждому, кто хочет углубить свои знания в этой области.

C++ — SOS!!! Задача на C++

БлогNot. Задачи на строки и файлы, C vs C++

Задачи на строки и файлы, C vs C++


Решать такие задачи можно как с помощью классических «сишных» библиотек cstdio и cstring, так и «новыми» c++-ными fstream и string. Что удобнее? Это зависит от задачи. В общем случае, если объёмы данных невелики, а быстродействие критично, char * может оказаться предпочтительнее, чем класс string . Если же данных много и мы не хотим возиться с «ручной» обработкой строк, string делается намного удобнее.

С файлами дело обстоит примерно так же — форматное чтение файлов или просто обработку данных небольшого объёма нередко выгоднее реализовать через FILE * , а в новых средах с управляемым кодом или при необходимости заставить «длинные» файловые операции выполняться в отдельном потоке приложения, fstream , конечно же, предпочтительнее.

Приведём несколько примеров, часть из них программируя классическим способом, а часть — «новым».

Пример 1. Текстовый файл содержит произвольные слова на английском языке, по 1 слову в строке, не более 40 слов в файле, длина слова ограничена 80 символами. Переписать слова в другой файл, отсортировав их в алфавитном порядке.

Пример 2. Подсчитать количество строк и символов в произвольном файле, а также процент символов, являющихся пробельными (пробел, табуляция, возврат каретки и перевод строки). Строка завершается парой символов «возврат каретки и перевод строки». При подсчете количества символов пара символов «возврат каретки» и «перевод строки» не интерпретируется как один символ.

Последнее — намёк читать файл по байтам с помощью fread , а не через fgetc .

Пример 3. Задана строка s произвольного размера. Реализовать подпрограмму удаления символов из строки, начиная с символа номер n, n≥0 до символа номер k включительно, k≥n. Подпрограмма возвращает указатель на полученную строку или NULL , если удаление невозможно.

Пример 3.1. Реализация этой задачи с помощью класса string :

Пример 4. Прочитать из бинарного файла данных динамический массив, состоящий из целых чисел. Определить, сколько раз в нём встречается максимальное значение.

Исходя из того, что каждое число в бинарном файле займёт sizeof(int)==4 байта (в 32-разрядной системе), файл теста сделаем, например, таким:

Видно, что здесь всего 4 числа и каждое число повторяется дважды.

Пример 4.1. Реализация этой задачи с помощью поточной библиотеки fstream :

Пример 5. Посимвольно считаем абзацы (строки) из текстового файла и запишем в вектор.

В этой заметке мы заставляли ifstream выполнять работу, которую часто пытаются возложить на функции классического Си.

А можно ли без scanf(«%s») прочитать из потока символы только до нужного разделителя, например, того же пробела? Проверим на примере стандартного потока ввода cin .

Пример 6. Прочитать через cin символы до пробела. В конце кода также показано, как игнорировать весь ввод до нажатия Enter.

Во многих случаях задачи удобнее решать не просто применяя строки string и потоки fstream , но и готовые алгоритмы из библиотеки для выполнения типовой обработки данных (вместо «ручной» реализации обработки в цикле).

Приведу пару таких примеров на посимвольную обработку строковых данных.

Пример 7. Дана строка. Подсчитать количество содержащихся в ней цифр.

Пример 8. Дана строка. Вывести все цифры из неё.

Платой за лаконичность становится, конечно, меньшая «понятность» кода с точки зрения классического процедурного программирования. Все программы проверены в Visual Studio 2015.

15.12.2020, 17:03; рейтинг: 7556

Полезные приёмы и хитрости C++

Знать специфику языка, на котором пишешь, всегда полезно. Чем большим количеством особенностей языка владеет разработчик, тем осознанней его код при прочих равных условиях. В материале рассмотрены интересные приёмы и трюки для C++.

Прим. перев. Стоит отметить, что статья в первую очередь будет полезна для олимпиадного программирования. В продакшне некоторые из этих приёмов могут не оценить.

Общие хитрости для C++

1. Макрос watch — один из самых полезных приёмов.

При отладке кода watch(переменная) выведет имя переменной и её значение.


2. Другие полезные макросы:

3. Не бойтесь использовать typedef .

Порой что-нибудь вроде set

>>> можно заменить на set

4. В качестве наиболее точного значения числа π можно использовать const double pi = 2 * acos(0.0) . Желательно использовать именно такой вариант, если иное значение не указано в условии задания.

4 октября 2020 – 1 марта 2020, Москва и онлайн, беcплатно

5. Никогда не используйте INT_MAX в качестве бесконечности для целых чисел. В некоторых алгоритмах, например, Флойда–Уоршелла, используются значения вроде ∞+w, что приведёт к переполнению при использовании INT_MAX . Вместо этого лучше использовать int oo = 0x3f3f3f3f , поскольку:

  • Это число достаточно большое для задач, связанных с целыми числами;
  • 2 * oo не приведёт к переполнению;
  • Все байты равны, поэтому вы без проблем можете использовать memset(array, oo, sizeof(array)) ;
  • Его довольно легко запомнить.

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

6. Для double -бесконечности хорошей идеей будет использовать double inf = 1.0/0.0 , поскольку именно так представлено значение бесконечности. У вас не будет переполнения, если вы напишете что-нибудь вроде 2*inf , так как 2*inf равно inf .

7. Существует встроенная функция для нахождения наибольшего общего делителя двух чисел. Это функция __gcd , доступная в заголовочном файле algorithm . Подробней можно почитать здесь.

8. Почти всё о манипуляциях с битами — как установить бит, обнулить бит, быстро умножить/разделить на 2 и т.д. — можно найти здесь и здесь.

9. Не используйте 1 , если x может быть больше 31, так как это неопределённое поведение может привести совсем не к тому результату, который вы ожидаете. Сначала приведите 1 к long long : 1ll .

10. Вместо if(условие) x++ вы можете написать x += условие . Спецификация C не гарантирует, что true равно 1, но в соревновательном программировании можно предположить, что это сработает.

11. Всегда компилируйте код с флагом -O2 . Ваш алгоритм может тратить слишком много времени на работу, однако компилятор сделает свою оптимизационную магию, и вы уложитесь в нужное время.

Прим. перев. В олимпиадном программировании оценивается время работы программы на тестирующем сервере, флаги компиляции на котором задаются огранизаторами олимпиады и обычно уже включают флаг -O2 .

Цукерберг рекомендует:  Cc++ - [Решено]Помочь разобраться с заданием

12. Стандартные объекты ввода и вывода C++ cin и cout по умолчанию работают быстро. Но их работу замедляет синхронизация с буферами C. Поэтому, если в начале кода написать ios::sync_with_stdio(false) , то cin и cout будут работать так же быстро, как и printf и scanf , которые вы, однако, больше не сможете использовать.

13. Не стесняйтесь использовать глобальные переменные. Максимальный размер массива, объявленного в функции main , может быть порядка 10 6 , в то время как размер глобального массива может быть порядка 10 7 .

Прим.перев. Ограничение на размер массива, объявленного внутри функции, возникает из-за того, что память, выделяемая операционной системой под стек, ограничена.

Хитрости для GCC

1. Если вы используете GCC, вы можете написать #include для импортирования всех стандартных библиотек.

2. GCC имеет встроенные функции для проведения определённых манипуляций с битами за постоянное время. Например, __builtin_popcount вычисляет общее количество установленных битов заданного целого числа (для long long используйте __builtin_popcountll ).

Есть множество других встроенных функций, прочитать про которые можно здесь.

Хитрости для C++11

C++11 привнёс некоторые обновления и пару классных вещей. Почти все компиляторы установили эту версию по умолчанию, но если в вашем случае это не так, то используйте флаг -std=c++11 для компиляции.

Прим. перев. В новых версиях GCC по умолчанию включён более новый стандарт C++14, который включает в себя все возможности C++11.

1. В заголовочном файле numeric есть полезная функция std::iota . Она заполняет std::vector (или какой-нибудь контейнер) увеличивающимися значениями, начиная с x . Например, iota(v.begin(), v.end(), x) .


2. Вам больше не нужно использовать _pair . Вместо этого вы можете написать ii p = <1, 2>или, например, iii p = <1, <2, 3>> .

Примечание Иногда работает не так, как вы ожидаете . Например, этот код выведет то, что должен:

Этот код, с другой стороны, не скомпилируется. Дело в том, что в результате инициализации списка просто инициализируются объекты. Вы не можете использовать их без контекста. Больше подробностей здесь.

3. Ключевое слово auto позволяет не указывать явно тип переменной, если вы объявляете и инициализируете её в одном месте. Например, вместо int i = 10 вы можете написать auto i = 10 , поскольку компилятор знает, что у i тот же тип, что и у 10 . Само собой, без инициализации переменной это не сработает.

4. В С++11 появилась такая классная штука, как цикл for , основанный на диапазоне. Например, вам не придётся писать for (int i = 0; i , потому что теперь есть for (auto &e : v) . За подробностями сюда.

Он очень полезен при обходе std::set или std::map :

Если вы хотите изменять значения, то используйте спецификатор & , чтобы получить ссылку на содержимое контейнера.

5. Вы можете написать функцию, которая будет возвращать два и более значений, с помощью std::tuple и std::tie .

Уже знали все эти хитрости и думаете, что вы эксперт в С++? Тогда пройдите наш тест и подтвердите это.

Классы в C++ Задача 1

Уважаемые читатели, переходим к очень важной теме: реализация классов на языке C++, на этот раз код будет достаточно большим, поэтому напомню, что в конце статьи, впрочем как и всегда, вас ждет готовый исходник, написанный под Windows.

Переходим к заданию:

Составить описание класса прямоугольников со сторонами, параллельными осям координат. Предусмотреть возможность перемещения прямоугольников на плоскости, изменения размеров, построения наименьшего прямоугольника, содержащего два заданных прямоугольника, и прямоугольника, являющегося общей частью (пересечением) двух прямоугольников.
Написать программу, демонстрирующую работу с этим классом. Программа должна содержать меню, позволяющее осуществить проверку всех методов класса.

О том, что такое классы в C++, достаточно хорошо написано здесь. А наша задача заключается в том, чтобы понять как эти классы реализуются, а также, что можно с ними делать, конечно, на нашем примере. Что ж начнем:

Ну, для начала подключим стандартные библиотеки и пространство имен. Далее уже идет само объявление класса rectangle (от англ. прямоугольник). В объявлении класса необходимо написать конструктор по умолчанию — это означает, что когда в main мы создадим какой либо объект класса, то по умолчанию он заполнится стандартными значениями, которые мы указали.

Конструктор с параметрами — соответственно, когда мы будем создавать объект в том же main, мы можем сразу же указать какие значения мы хотим для координат нашего прямоугольника. Далее идет деструктор, который по своей сути ничего не делает (в данной задаче), но в классах C++ он необходим.

После этого мы объявили несколько функций, подобно тому как мы это делали чуть ранее, когда говорили про функции в C++ на примере динамических массивов. И, отмечу, что функции, которые объявляются в классе, принято называть методами класса, и в будущем мы будем говорить именно о методах класса.

Также не забудем про объявление переменных в разделе private. Так как это раздел private, то обращаться к этим переменным могут только методы этого класса, в других местах программы это невозможно.

И еще кое что: так как в прямоугольнике 4 точки, то соответственно требуется 8 координат (по 2 на точку) — 8 переменных, в нашей же программе используется всего 4 переменные: 2 координаты по Х (левые и правые точки) и 2 координаты по Y (нижние и верхние точки). Так можно сделать, учитывая, что в задании сказано, что стороны прямоугольника параллельны осям координат.

Далее начинаем описывать наши методы. Начнем сразу с 2 простых: ввод и вывод. Думаю, что если вы изучаете классы в C++, то эта часть кода для вас очень проста.

Помните в начале я говорил, что код будет большим, так вот, поздравляю вас, мы пересекли экватор. Ну что, еще 2 метода в этой части кода: перемещение прямоугольника и изменение его размеров. Оба метода реализуются просто: мы спрашиваем у пользователя на сколько или во сколько раз нужно переместить или увеличить наш прямоугольник. А затем выдаем ему уже новые координаты прямоугольника.

А вот это уже что то слишком здоровое! Я не стал разбивать на блоки этот ОДИН метод, чтобы у вас была цельная картина.

Принцип метода: для начала просим пользователя задать координаты второго прямоугольника, так как для этого метода их нужно 2. Затем все это выводим на экран, далее, записываем координаты по X и Y соответственно в массивы. Зачем нам тут массивы — сейчас увидите, для начала, на картинке:

Так вот, чтобы найти координаты прямоугольника, содержащего оба заданных прямоугольника, нужно взять минимальные и максимальные координаты по X и по Y. Именно это мы и находим, перебирая наши массивы в цикле. Затем уже выводим полученные координаты общего прямоугольника.

Последний метод:

Логика этого метода, аналогична предыдущему методу. Только вместо минимальных и максимальных координат, мы используем серединные координаты, для того чтобы определить координаты прямоугольника на пересечении. И, конечно, если вы зададите прямоугольники, которые не пересекаются, то у вас возникнет ошибка, значения вы получите, но они не будут верными.

И наконец перейдем к main:

Напомню, что нам нужно было реализовать меню. В моей программе оно реализовано через switch, но главное, чтобы это было похоже на меню, и при нажатии клавиши выполнялся соответствующий метод. Именно это и реализовано.

На этом сегодня все, кто дочитал от начала до конца, тот просто молодец! И, конечно, не забудьте скачать исходники.

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих