Skip to content

Практическая работа №7

Работа со структурами в C++

Section titled “Работа со структурами в C++”
ЭтапВремяЧто выполняется
Повторение и разбор примера10 минОбъявление структуры, поля, массив структур, функции
Исследовательская часть20 минТри небольших упражнения с готовыми данными
Индивидуальный вариант50 минОдин комплексный кейс с массивом структур
Проверка и сдача10 минДва теста, схема алгоритма, ответы на вопросы
Итого90 мин

Основные теоретические положения

Section titled “Основные теоретические положения”

1. Структура как пользовательский тип данных

Section titled “1. Структура как пользовательский тип данных”

Массив хранит элементы одного типа, а структура (struct) позволяет объединить разные, но логически связанные данные об одном объекте.

Например, данные о книге можно описать структурой:

#include <string>
using namespace std;
struct Book {
string title; // Название книги
string author; // Автор
int year; // Год издания
int copies; // Количество экземпляров
};

Слово Book — имя нового типа, title, author, year, copies — его поля. Объявление структуры завершается точкой с запятой ;.

Создание переменной и обращение к её полям:

Book book = {"Algorithms", "Knuth", 1997, 3};
cout << book.title << '\n'; // Algorithms
book.copies = 5; // Изменение поля

Для доступа к полям переменной структуры используют оператор точка (.).

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

Book books[] = {
{"Algorithms", "Knuth", 1997, 3},
{"CppPrimer", "Lippman", 2012, 2},
{"CleanCode", "Martin", 2008, 5}
};

Обращение к полю второй книги: books[1].year. Для перебора подходят обычный for и range-based for:

for (const Book& book : books) {
cout << book.title << ": " << book.copies << '\n';
}

В этом цикле каждая запись доступна через имя book и не копируется благодаря ссылке &.

3. Передача структур в функции

Section titled “3. Передача структур в функции”

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

void printBook(const Book& book) {
cout << book.title << ", " << book.year
<< ", экземпляров: " << book.copies << '\n';
}
void addCopies(Book& book, int amount) {
if (amount > 0) {
book.copies += amount;
}
}
  • const Book& — чтение без изменения исходной структуры.
  • Book& — изменение исходной структуры внутри функции.
  • Book без & — передача по значению: функция получает копию структуры.

4. Полный пример программы

Section titled “4. Полный пример программы”

В программе хранится список устройств. Функция printDevice() выводит запись, replenish() увеличивает количество устройств на складе.

#include <iostream>
#include <string>
using namespace std;
struct Device {
string name;
int stock;
};
void printDevice(const Device& device) {
cout << device.name << ": " << device.stock << '\n';
}
void replenish(Device& device, int amount) {
if (amount > 0) {
device.stock += amount;
}
}
int main() {
Device devices[] = {
{"Mouse", 4},
{"Keyboard", 2},
{"Monitor", 0}
};
for (const Device& device : devices) {
printDevice(device);
}
replenish(devices[2], 3);
cout << "После пополнения: ";
printDevice(devices[2]);
return 0;
}

Ожидаемый результат:

Mouse: 4
Keyboard: 2
Monitor: 0
После пополнения: Monitor: 3

Сохраните программу в файле practice7.cpp:

Terminal window
g++ -std=c++17 -Wall -Wextra -pedantic practice7.cpp -o practice7
./practice7

В Windows запускаемый файл обычно называется practice7.exe.


Задания для выполнения

Section titled “Задания для выполнения”

Часть 1. Исследование структур

Section titled “Часть 1. Исследование структур”

Задание 1.1. Объявление, инициализация, изменение полей

Создайте структуру Student с полями name (string), age (int) и averageGrade (double).

  1. Создайте переменную со значениями {"Ivanov", 17, 4.2}.
  2. Выведите все три поля.
  3. Измените averageGrade на 4.6 и выведите результат повторно.

Задание 1.2. Обработка массива структур

Используйте структуру Book из теории и готовый массив:

Book books[] = {
{"Algorithms", "Knuth", 1997, 3},
{"CppPrimer", "Lippman", 2012, 2},
{"CleanCode", "Martin", 2008, 5}
};
  1. Выведите названия и годы издания всех книг в цикле.
  2. Найдите общее число экземпляров в массиве.
  3. Найдите самую новую книгу по году издания.

Для самопроверки: 10 экземпляров, самая новая книга — CppPrimer (2012).

Задание 1.3. Функции и ссылки

Используйте функции printBook(const Book& book) и addCopies(Book& book, int amount) из теории.

  1. Вызовите printBook() для каждой книги из задания 1.2.
  2. Увеличьте число экземпляров CppPrimer на 4 с помощью addCopies().
  3. Повторно выведите изменённую запись и общую сумму экземпляров.

Для самопроверки: у CppPrimer стало 6 экземпляров, общая сумма — 14.


Часть 2. Индивидуальное задание

Section titled “Часть 2. Индивидуальное задание”

Общие требования для всех вариантов:

  1. Объявите указанную структуру и обычный массив из четырёх записей. Первоначально значения берите из приведённого в варианте кода.
  2. Реализуйте функцию print... (const T& item) для вывода всех полей одной записи. Вызовите её для каждого элемента массива.
  3. Выполните два действия анализа данных из условия своего варианта, используя циклы и условия.
  4. Реализуйте функцию update... (T& item, ...), изменяющую одно указанное поле. С клавиатуры вводятся ключ записи и новое значение (или величина изменения). Найдите запись перебором массива, вызовите функцию и выведите обновлённые данные. Если запись не найдена, выведите сообщение.
  5. Для числовых полей не допускайте явно некорректных значений (например, отрицательной цены, количества или возраста). Не используйте классы, динамические массивы, вложенные структуры и указатели.
  6. Для поиска используйте точное совпадение строк (==); названия в исходных данных записаны латиницей без пробелов, чтобы их можно было вводить оператором cin >>.

Схема алгоритма: составьте одну небольшую блок-схему поиска записи и изменения её поля: ввод ключа → перебор элементов → совпадение? → обновление → вывод результата / сообщение об отсутствии записи. Не нужно рисовать отдельную блок-схему для каждого пункта.

Вариант 1. Книжный фонд библиотеки

Section titled “Вариант 1. Книжный фонд библиотеки”

Исходные данные:

struct Book {
string title;
string author;
int year;
int copies;
};
Book items[] = {
{"Algorithms", "Knuth", 1997, 3},
{"CleanCode", "Martin", 2008, 5},
{"CppPrimer", "Lippman", 2012, 2},
{"EffectiveCpp", "Meyers", 2005, 0}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Book& и вывести все элементы массива.
  2. Найдите общее количество экземпляров всех книг.
  3. Выведите книги, изданные после введённого года (год ввести с клавиатуры).
  4. По названию книги измените число экземпляров на новое неотрицательное значение через функцию с Book&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Всего 10 экземпляров. После 2006 года: CleanCode, CppPrimer.


Вариант 2. Остатки товаров на складе

Section titled “Вариант 2. Остатки товаров на складе”

Исходные данные:

struct Product {
string name;
int price;
int quantity;
};
Product items[] = {
{"Keyboard", 1200, 4},
{"Mouse", 650, 8},
{"Monitor", 9500, 2},
{"Webcam", 2900, 0}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Product& и вывести все элементы массива.
  2. Вычислите общую стоимость остатков: сумму price * quantity для всех товаров.
  3. Выведите названия товаров, количество которых равно 0.
  4. По названию товара задайте новое неотрицательное количество через функцию с Product&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Общая стоимость: 29 000 руб. Без остатка — Webcam.


Вариант 3. Учёт автомобилей

Section titled “Вариант 3. Учёт автомобилей”

Исходные данные:

struct Car {
string brand;
int year;
int mileage;
};
Car items[] = {
{"Lada", 2018, 85000},
{"Kia", 2021, 60000},
{"Ford", 2015, 110000},
{"Skoda", 2020, 70000}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Car& и вывести все элементы массива.
  2. Найдите автомобиль с наибольшим пробегом.
  3. Выведите автомобили, выпущенные после введённого года.
  4. По марке измените пробег на новое неотрицательное значение через функцию с Car&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Наибольший пробег — Ford (110000). После 2019 года: Kia, Skoda.


Вариант 4. Население городов

Section titled “Вариант 4. Население городов”

Исходные данные:

struct City {
string name;
int population;
string region;
};
City items[] = {
{"Pskov", 187000, "Pskov"},
{"Novgorod", 223000, "Novgorod"},
{"Tver", 414000, "Tver"},
{"Vologda", 313000, "Vologda"}
};

Необходимо:

  1. Написать функцию вывода одной записи через const City& и вывести все элементы массива.
  2. Найдите город с наибольшим населением.
  3. Выведите города, население которых превышает введённое число.
  4. По названию города измените население на новое неотрицательное значение через функцию с City&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Наибольшее население — Tver (414000). При пороге 300000: Tver, Vologda.


Вариант 5. Каталог фильмов

Section titled “Вариант 5. Каталог фильмов”

Исходные данные:

struct Movie {
string title;
string genre;
double rating;
};
Movie items[] = {
{"Arrival", "SciFi", 8.0},
{"Dune", "SciFi", 8.1},
{"Coco", "Animation", 8.4},
{"Her", "Drama", 8.0}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Movie& и вывести все элементы массива.
  2. Найдите фильм с самым высоким рейтингом.
  3. Выведите фильмы заданного жанра (жанр ввести с клавиатуры).
  4. По названию фильма измените рейтинг через функцию с Movie& (значение от 0 до 10). Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Максимальный рейтинг — Coco (8.4). Жанр SciFi: Arrival, Dune.


Вариант 6. Результаты спортсменов

Section titled “Вариант 6. Результаты спортсменов”

Исходные данные:

struct Athlete {
string name;
string sport;
int points;
};
Athlete items[] = {
{"Anna", "Run", 38},
{"Boris", "Swim", 42},
{"Vera", "Run", 45},
{"Oleg", "Swim", 40}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Athlete& и вывести все элементы массива.
  2. Найдите спортсмена с наибольшим числом очков.
  3. Выведите спортсменов введённого вида спорта.
  4. По имени измените число очков на новое неотрицательное значение через функцию с Athlete&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Лидер — Vera (45). Для Run: Anna, Vera.


Вариант 7. Книга рецептов

Section titled “Вариант 7. Книга рецептов”

Исходные данные:

struct Recipe {
string title;
int minutes;
int portions;
};
Recipe items[] = {
{"Soup", 35, 4},
{"Salad", 15, 2},
{"Pasta", 25, 3},
{"Pie", 50, 6}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Recipe& и вывести все элементы массива.
  2. Найдите рецепт с минимальным временем приготовления.
  3. Выведите рецепты, время приготовления которых не превышает введённое количество минут.
  4. По названию рецепта измените время приготовления на положительное число минут через функцию с Recipe&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Самый быстрый рецепт — Salad (15 мин.). При пороге 25 мин.: Salad, Pasta.


Вариант 8. Музыкальный плейлист

Section titled “Вариант 8. Музыкальный плейлист”

Исходные данные:

struct Song {
string title;
string artist;
int seconds;
};
Song items[] = {
{"Sky", "Nova", 210},
{"Road", "Luna", 185},
{"Rain", "Nova", 240},
{"Light", "Alex", 205}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Song& и вывести все элементы массива.
  2. Найдите общую длительность всех песен в секундах.
  3. Выведите песни введённого исполнителя.
  4. По названию песни измените длительность на положительное число секунд через функцию с Song&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Общая длительность — 840 с. Исполнитель Nova: Sky, Rain.


Вариант 9. Справочник стран

Section titled “Вариант 9. Справочник стран”

Исходные данные:

struct Country {
string name;
string capital;
int areaThousandKm2;
};
Country items[] = {
{"Norway", "Oslo", 385},
{"Sweden", "Stockholm", 450},
{"Finland", "Helsinki", 338},
{"Denmark", "Copenhagen", 43}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Country& и вывести все элементы массива.
  2. Найдите страну с наибольшей площадью.
  3. Выведите страны, площадь которых превышает введённый порог (единица измерения: тысячи км²).
  4. По названию страны измените площадь на положительное значение через функцию с Country&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Наибольшая площадь — Sweden (450 тыс. км²). При пороге 350: Norway, Sweden.


Вариант 10. Расписание авиарейсов

Section titled “Вариант 10. Расписание авиарейсов”

Исходные данные:

struct Flight {
string code;
string destination;
int freeSeats;
};
Flight items[] = {
{"SU101", "Moscow", 12},
{"SU202", "Kazan", 0},
{"SU303", "Moscow", 5},
{"SU404", "Sochi", 9}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Flight& и вывести все элементы массива.
  2. Определите общее количество свободных мест на всех рейсах.
  3. Выведите рейсы, прибывающие в заданный город.
  4. По номеру рейса измените количество свободных мест на неотрицательное число через функцию с Flight&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Всего 26 свободных мест. Город Moscow: рейсы SU101, SU303.


Вариант 11. Дневник погоды

Section titled “Вариант 11. Дневник погоды”

Исходные данные:

struct WeatherDay {
string day;
int minTemp;
int maxTemp;
};
WeatherDay items[] = {
{"Mon", 12, 19},
{"Tue", 10, 22},
{"Wed", 14, 17},
{"Thu", 8, 20}
};

Необходимо:

  1. Написать функцию вывода одной записи через const WeatherDay& и вывести все элементы массива.
  2. Найдите день с наибольшей разницей между максимальной и минимальной температурой (при равенстве — первый).
  3. Выведите дни, когда максимальная температура была выше введённого порога.
  4. По названию дня измените максимальную температуру через функцию с WeatherDay&. Новое значение не должно быть ниже минимальной температуры этого дня. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Наибольшая разница — 12 °C, первый такой день — Tue. При пороге 20 °C: Tue.


Вариант 12. Учёт животных

Section titled “Вариант 12. Учёт животных”

Исходные данные:

struct Animal {
string species;
string nickname;
int age;
};
Animal items[] = {
{"Cat", "Barsik", 3},
{"Dog", "Rex", 6},
{"Cat", "Murka", 5},
{"Parrot", "Kesha", 2}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Animal& и вывести все элементы массива.
  2. Найдите самое старшее животное.
  3. Выведите животных заданного вида.
  4. По кличке измените возраст на неотрицательное значение через функцию с Animal&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Самое старшее — Rex (6 лет). Вид Cat: Barsik, Murka.


Вариант 13. Турнирная таблица

Section titled “Вариант 13. Турнирная таблица”

Исходные данные:

struct Player {
string nickname;
string team;
int points;
};
Player items[] = {
{"Alex", "Red", 12},
{"Nina", "Blue", 18},
{"Oleg", "Red", 7},
{"Sara", "Blue", 16}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Player& и вывести все элементы массива.
  2. Найдите игрока с наибольшим числом очков.
  3. Вычислите сумму очков игроков заданной команды.
  4. По нику игрока прибавьте к его очкам введённое неотрицательное число через функцию с Player&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Лидер — Nina (18 очков). Команда Red набрала 19 очков.


Вариант 14. Зарплатная ведомость

Section titled “Вариант 14. Зарплатная ведомость”

Исходные данные:

struct Employee {
string name;
string department;
int salary;
};
Employee items[] = {
{"Ivanov", "IT", 65000},
{"Petrova", "HR", 54000},
{"Sidorov", "IT", 72000},
{"Orlova", "Sales", 60000}
};

Необходимо:

  1. Написать функцию вывода одной записи через const Employee& и вывести все элементы массива.
  2. Вычислите среднюю заработную плату по всем сотрудникам.
  3. Выведите сотрудников указанного отдела.
  4. По фамилии измените зарплату на неотрицательное число через функцию с Employee&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Средняя зарплата — 62 750 руб. Отдел IT: Ivanov, Sidorov.


Вариант 15. Книжный магазин

Section titled “Вариант 15. Книжный магазин”

Исходные данные:

struct BookOffer {
string title;
string author;
int year;
int price;
};
BookOffer items[] = {
{"CppBasics", "Ivanov", 2019, 1100},
{"Networks", "Petrov", 2008, 900},
{"Algorithms", "Smirnov", 2022, 1800},
{"Databases", "Orlov", 2014, 1500}
};

Необходимо:

  1. Написать функцию вывода одной записи через const BookOffer& и вывести все элементы массива.
  2. Найдите самую дорогую книгу, изданную после 2010 года.
  3. Определите количество книг, выпущенных после введённого года.
  4. По названию книги измените цену на новое неотрицательное значение через функцию с BookOffer&. Если ключ не найден, выдать сообщение.

Для самопроверки до изменения данных: Самая дорогая книга после 2010 года — Algorithms (1800 руб.). После 2010 года — 3 книги.


Проверка правильности решения

Section titled “Проверка правильности решения”

Для индивидуального варианта выполните два теста:

  1. Основной: используйте готовый массив, проверьте результаты по строке «Для самопроверки», затем измените одну существующую запись и убедитесь, что значение действительно обновилось.
  2. Граничный: попробуйте найти отсутствующий ключ. Программа должна вывести понятное сообщение и не изменять остальные записи. Также проверьте отказ от недопустимого нового значения, если для поля установлено ограничение.

Предоставьте:

  1. Файл practice7.cpp с одной работающей программой по индивидуальному варианту и с функциями вывода и изменения записи.
  2. Небольшую блок-схему поиска записи и её изменения (на бумаге или в редакторе схем).
  3. Результаты двух тестов: успешное обновление и поиск отсутствующей записи. Достаточно продемонстрировать их преподавателю при сдаче.

Обратите внимание: исследовательские задания выполняются для изучения приёмов работы со структурами; основным оцениваемым результатом является индивидуальный вариант. Контрольные вопросы предназначены для устной проверки понимания — не нужно письменно отвечать на все вопросы в пределах 90 минут.

  1. Чем структура struct отличается от обычного массива?
  2. Как объявить структуру и создать переменную этого типа?
  3. Для чего нужен оператор .?
  4. Как получить доступ к полю элемента массива структур?
  5. Как перебрать массив структур обычным циклом for?
  6. Для чего при передаче структуры в функцию используют const T&?
  7. Чем отличается передача в функцию по значению (T) от передачи по ссылке (T&)?
  8. Как определить, что запись с заданным ключом отсутствует в массиве?
  9. Почему важно проверять корректность нового значения перед изменением поля?
  10. Какие преимущества даёт разбиение программы на функции вывода, поиска и изменения данных?

Рекомендуемая литература

Section titled “Рекомендуемая литература”
  1. LearnCpp — Introduction to structs, members, and member selection — введение в структуры.
  2. cppreference — Aggregate initialization — инициализация структур.
  3. cppreference — References — ссылки и передача данных.
  4. Прата С. Язык программирования C++. Лекции и упражнения. 6-е изд.
  5. Страуструп Б. Язык программирования C++. 4-е изд.