§ 17. Массивы и структуры как параметры функций
Сайт: | Профильное обучение |
Курс: | Информатика. 10 класс (Повышенный уровень) |
Книга: | § 17. Массивы и структуры как параметры функций |
Напечатано:: | Гость |
Дата: | Четверг, 28 Ноябрь 2024, 08:44 |
17.1. Передача параметра по значению и по ссылке
По умолчанию аргументы функции в C++ передаются по значению. Когда аргумент передается по значению, то его значение копируется в параметр функции. Рассмотрим пример 17.1. В первом вызове функции func аргументом является число 5. При вызове функции создается переменная k, значение 5 копируется в нее. Выполняются команды функции, работающие с этим значением. Затем, когда func завершит свою работу, переменная k уничтожается. Во втором вызове функции аргументом является переменная x со значением 2. При вызове переменная k создается снова, и значение 2 копируется в k. По завершении работы функции переменная k уничтожается. В третьем вызове функции аргументом является выражение x + 3, которое сначала вычисляется (получаем 5), а затем это значение копируется в переменную k, которая уничтожается по завершении работы функции. Поскольку функция работает с копией переданного значения, то исходное значение не может быть изменено функцией (пример 17.2). Значения переменных x и y, которые удвоились внутри функции, после ее вызова остались не измененными. Обратите внимание на переменную k, которая является параметром функции func, а также описана внутри main. Для компилятора это совершенно разные переменные. Во время работы функции func значение переменной k, объявленной в main, не известно. Другим способом передачи значений параметров в функции может быть передача параметров по ссылке. Ссылка — тип переменной в C++, который работает как псевдоним другого объекта или значения. При объявлении ссылки используется знак амперсанд (&), который записывают между типом данных и именем ссылки. Функция в примере 17.3 отличается от функции в примере 17.2 тем, что параметр k объявлен как ссылка. При передаче параметра по ссылке не создается копия передаваемого объекта. Все действия происходят с тем объектом, на который указывает ссылка. Разные способы передачи параметров имеют свои плюсы и минусы. Если параметрами функции являются структуры или массивы, то их копирование может привести к значительному снижению производительности, особенно когда функция вызывается много раз. Также при таком копировании увеличивается необходимое количество памяти. Поэтому сложные типы данных передаются обычно по ссылке. При передаче параметров по значению единственный способ вернуть измененное значение обратно — использовать возвращаемое значение функции (в команде return). Но иногда необходимо, чтобы функция изменила значение переданного аргумента, а может быть, не одного, а нескольких. Передача по ссылке решает все эти проблемы. При передаче значения по ссылке возможен вызов функции, параметр которой еще не задан (пример 17.4). Значение параметра можно определить путем ввода с клавиатуры или из файла либо путем вычислений. Если формальный параметр объявлен как ссылка, то фактическим параметром может быть только переменная, описанная до вызова функции. |
Пример 17.1. Программа:
Тестирование. Пример 17.2. Программа:
Тестирование. Пример 17.3. Программа:
Тестирование. При вызове func(x) параметр k становится псевдонимом переменной x. Таким образом, все, что описано для переменной k, будет происходить с переменной x. После завершения работы функции значение переменной x будет изменено (увеличится в 2 раза). Следующий вызов func(y) сделает параметр k псевдонимом переменной y, которая также изменит свое значение после выполнения функции. Пример 17.4. Программа:
Тестирование. Значения переменных до вызова функции не известны. Они будут определены при вызове функции и размещены по соответствующим адресам в памяти. Если в описании такой функции убрать ссылку, то переменные будут определены произвольными значениями. |
17.2. Массивы как параметры функций
Пример 17.5. Даны натуральные n, m целые a0,..., an – 1, b0,..., am – 1, получить:
Этапы выполнения задания I. Исходные данные: переменные n и m — количество элементов в массивах а и b, a и b — линейныe массивы. II. Результат: значение переменной t. III. Алгоритм решения задачи. 1. Ввод исходных данных. Для ввода массива создадим функцию. Поскольку до вызова функции размер вектора неизвестен, то векторы a и b создаются без указания количества элементов в них. Для ввода значений можно использовать один из двух вариантов: 1.1. Ввести количество элементов, изменить размер вектора с помощью функции resize (см. Приложение к главе 1), затем ввести элементы. 2. Для нахождения минимального и максимального элементов массива оформим соответствующие функции. Функция будет принимать массив как параметр и возвращать значение минимального (максимального) элемента в массиве. |
Пример 17.5. V. Программа:
VI. Тестирование. |
17.3. Поиск заданного элемента в многомерном массиве
При организации линейного поиска в одномерном массиве для проверки сложных условий поиска создавали функции, которые проверяли отдельный элемент. При работе с двумерными массивами можно поступить аналогично. В этом случае функция будет принимать в качестве параметра линейный массив и обрабатывать его. Пример 17.6. Задан двумерный массив a из m строк и n столбцов. Получить линейный массив b, в котором b[i] — сумма элементов i-й строки массива a, кратных 3. Этапы выполнения задания I. Исходные данные: переменные n и m — количество строк и столбцов в массиве а, a — двумерный массив. II. Результат: линейный массив b. III. Алгоритм решения задачи. 1. Ввод исходных данных. Элементы массива сгенерированы случайным образом. IV. Описание переменных: n, m – int, a – vector<vector<int>>, b – vector<int>. Пример 17.7. Задан двумерный массив a из m строк и n столбцов. Вывести номера строк, элементы которых образуют возрастающую последовательность. Если таких строк в массиве нет, то ввести соответствующее сообщение. Этапы выполнения задания I. Исходные данные: переменные n и m — количество строк и столбцов в массиве а, a — двумерный массив. II. Результат: номера строк и сообщение, что строк нет. III. Алгоритм решения задачи. 1. Ввод исходных данных. Элементы массива сгенерированы случайным образом. 2.1. Элементы образуют возрастающую последовательность, если каждый следующий больше предыдущего. 3. В цикле вызовем функцию для каждой строки и проверим результат. |
Пример 17.6. V. Программа:
VI. Тестирование. Пример 17.7. V. Программа:
VI. Тестирование. |
17.4. Массивы структур. Поиск в массиве структур
Пример 17.8. В текстовом файле input.txt хранится информация о студентах. Для каждого студента указана его фамилия, город, из которого он приехал (название города — одно слово), и три числа — баллы за ЦТ, с которыми он поступил в ВУЗ. Посчитать количество студентов, у которых сумма баллов больше x (вводится с клавиатуры). Вывести в текстовый файл с именем otchet.txt фамилии и суммарный балл студентов из указанного города (вводится с клавиатуры). Этапы выполнения задания I. Исходные данные: структура student с полями fam, gorod, otm (массив из трех элементов). Данные считываются в массив структур. II. Результат: список студентов из указанного города в файле и количество студентов с суммарным баллом, большим x, на экране. Если поиск не дал результата, то вывод соответствующего сообщения. III. Алгоритм решения задачи. 1. Ввод исходных данных с помощью функции vvod. В структуру добавим поле summa, в которое будем записывать суммарный балл для каждого студента при считывании данных. 2.1. Функция для поиска по баллам find_ball возвращает в качестве результата число студентов. Если функция вернула значение 0, то таких студентов нет. 3. После вызова каждой функции проверим, был ли поиск успешным, и выведем соответствующее сообщение. IV. Описание переменных: n – int, a – vector<student>. Передача параметров по ссылке позволяет переслать большие структуры или массивы с минимальной затратой ресурсов. Однако здесь также могут возникнуть другие проблемы. Ссылки позволяют функции изменять значения аргументов напрямую. Однако это может быть нежелательно, если нужно, чтобы аргумент был доступен только для чтения. В таком случае можно использовать передачу параметра по константной ссылке. Константная ссылка — ссылка на переменную, значение которой невозможно изменить через эту же ссылку. Для того чтобы ссылка была константной, нужно добавить перед описанием ключевое слово const. Если использовать константную ссылку в качестве параметра функции, то функция не изменит аргумент. При попытке это сделать получим ошибку компиляции (пример 17.9). |
Пример 17.8. V. Программа:
VI. Тестирование Пример 17.9. Программа: |
Вопросы к главе
1. Что происходит в функции при передаче параметров по значению? 2. Как передать параметр функции по ссылке? 3. Для каких данных рекомендуется передача параметра по ссылке? 4. Зачем может быть использована передача параметра по константной ссылке? |
Упражнения
1. Для задачи из примера 17.5 выполните перечисленные задания.
1. Перечислите ситуации, которые относятся к «остальным случаям» в условии задачи.
2. Измените программу так, чтобы для «остальных случаев» выводились значения и
2. Даны натуральные n, m, k целые a0, ..., an-1, b0, ..., bm-1, c0, ..., ck-1, получить:
1.
2.
3.
3. Дано натуральное n и целые x0, ..., xn – 1, y0, ..., yn – 1. Получить:
1.
2.
Запись обозначает сумму всех xi при изменении i от 0 до n – 1: x0 + x1 + ... + xn – 1.
4. Задан двумерный массив a из m строк и n столбцов. Получить линейный массив b, в котором b[i] — это:
1. Количество положительных элементов i-й строки массива a.
2. Целая часть среднего арифметического i-й строки массива a.
3. Минимальный элемент i-й строки массива a.
4. Количество чисел, модуль которых равен модулю максимального элемента i-й строки массива a.
5. Количество чисел, которые при делении на 3 и на 5 дают одинаковые остатки.
6. Число, встречающееся в i-й строке массива a чаще других чисел. Если таких чисел несколько, то взять число с меньшим номером в строке.
7. Реализовать пункты 1–6 для столбцов. Для этого транспонировать матрицу (см. пример 15.13).
5. Задан двумерный массив a из m строк и n столбцов.
- Вывести номера строк, содержащих минимальный элемент двумерного массива.
- Вывести номера строк, в которых есть равные элементы. Если таких строк нет, то вывести соответствующее сообщение.
- Вывести номера строк, в которых все элементы различны. Если таких строк нет, то вывести соответствующее сообщение.
- Вывести номера строк, суммы элементов в которых равны. Вывод осуществить в виде таблицы.
Пример |
Пояснение |
0: 1: 2, 3 2: 3 3: 4: 5 5: |
Сумма элементов первой стоки равна сумме элементов 2-й и 3-й строк, сумма элементов 2-й строки равна сумме элементов 3-й строки. Сумма элементов 4-й строки равна сумме элементов 5-й строки. Для строк 0 и 3 нет строк с равными им суммами. Для каждой строки проверяются только строки с номерами, которые больше, чем номер текущей строки. |
5. реализовать пункты 1—4 для столбцов. Для этого транспонировать матрицу (см. пример 15.13).
6. Внесите изменения в программу примера 17.8 так, чтобы программа корректно обрабатывала названия городов, состоящие более чем из одного слова (например, Старые Дороги или Нижний Новгород).
7. Создать текстовый файл описанной ниже структуры. В первой строке в текстовом файле записать количество данных. Количество данных увеличить до 10, подобрав подходящую информацию. Вывести в текстовый файл с именем otchet.txt данные, удовлетворяющие перечисленным условиям.
1. В файле хранятся: название страны[1], столица, площадь (тыс. км2) и количество населения (млн чел):
Беларусь Минск 208 9.41
Россия Москва 17075 143.3
США Вашингтон 9373 310.2
Канада Оттава 9985 34.2
Франция Париж 547 65.4
И т.д.
Найти количество стран с населением <=50 млн чел. и названия тех стран, название столицы которых состоит из k (вводится с клавиатуры) букв.
2. В файле хранятся: название производителя стиральной машины, ее модель, мощность и максимальная загрузка белья (кг).
Samsung WW65K52E69S 2400 6.5
Bosch WLT24440OE 2300 7
Haier HW70-BP12758S 1900 7
LG F12M7NDS0 1700 6
И т.д.
Найти количество стиральных машин с мощностью >2000 и названия производителей, в модель которых входит буква «х» (значение «х» вводится с клавиатуры).
3. В файле хранятся: название озера[2], область, в которой оно расположено; его объем (млн м3), площадь (км2), максимальная глубина (м) и прозрачность(м).
Нарочь Минская 710 79.6 24.8 7.4
Снуды Витебская 107 22 16.5 6.6
Ричи Витебская 131.5 12.9 51.9 5.5
Свитязь Гродненская 7.76 25.2 15 5.2
И т.д.
Найти самое глубокое и самое прозрачное озеро (вывести название и месторасположение), а также названия тех озер, которые находятся в указанной области (ввести с клавиатуры).
[1] http://ostranah.ru/ – географический справочник «О странах» (дата доступа 20.06.2020).
[2] http://rad.org.by/articles/voda/10-samyh-... и https://ru.wikipedia.org/wiki/Озёра_Белоруссии (дата доступа 20.06.2020).