Типичная ошибка программирования 8 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Типичная ошибка программирования 8



Предположение, что элементы локального массива класса static в функции получают нулевые начальные значения при каждом вызове функции.

Рис.13 – Сравнение присваивания начальных значений массиву типа static и автоматическому массиву (часть 1 из 2)

Рис.13 – Сравнение присваивания начальных значений массиву типа static и автоматическому массиву (часть 2 из 2)

 

Передача массивов в функции

Чтобы передать массив в качестве аргумента в функцию, укажите имя массива без каких-либо квадратных скобок. Например, если массив hourlyTemperatures объявлен как

int hourlyTemperatures [2 4 ];

то оператор вызова функции

modifyArray (hourlyTemperatures, 24);

передает массив hourlyTemperatures и его размер функции modifyArray. При передаче массива в функцию его размер часто передается, чтобы функция могла обрабатывать заданное число элементов в массиве. В главе 8, когда мы познакомимся с классом Array, мы будем встраивать размер массива внутрь типа, определяемого пользователем — каждый объект Array, который мы создадим, будет «знать» свой собственный размер. Таким образом, при передаче объекта Array функции нет необходимости передавать ей в качестве аргумента размер массива.

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

Хотя массивы как целое передаются моделируемым вызовом по ссылке, отдельные элементы массива передаются вызовом по значению подобно простым переменным. Такие отдельные простые элементы данных называются скалярами или скалярными параметрами. Чтобы передать в функцию элемент массива, используйте индексированное имя элемента массива как аргумент в вызове функции. В главе 5 мы покажем, как можно моделировать вызов по ссылке для скаляров (т.е. отдельных переменных и элементов массива).

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

void modifyArray(int b[], int arraySize)

указывая, что modifyArray ожидает принятия массива целых чисел в параметре b, и количество элементов массива в параметре arraySize. Размер массива в квадратных скобках указывать не нужно. Если он включен, компилятор его проигнорирует. Поскольку массивы передаются моделируемым вызовом по ссылке, то вызываемая функция, используя имя массива b, в действительности будет работать с истинным массивом в источнике вызова (массив hourlyTemperatures в предыдущем вызове).

Отметим необычный вид прототипа функции для modifyArray

void modifyArray (int [], int); Этот прототип мог бы быть записан в виде void modifyArray (int anyArrayName[], int anyVariableName)

но, компиляторы C++ игнорируют имена переменных в прототипах.

Напомним, что прототип сообщает компилятору количество аргументов и типы каждого аргумента (в порядке их ожидаемого появления).

Программа на рис. 14 демонстрирует различие между передачей всего массива и его отдельных элементов. Программа сначала печатает пять элементов массива целых чисел а. Далее массив а и его размеры передаются функции modifyArray, где каждый элемент массива а умножается на 2. Затем а повторно печатается в main. Как показывают выходные данные, элементы а действительно модифицируются функцией modifyArray. Затем программа печатает значение а[3] и передает его функции modifyElement. Функция modifyElement умножает свой аргумент на 2 и печатает его новое значение. Заметим, что при повторной печати элемента а[3] в main он не модифицировался, потому что отдельные элементы массива передаются вызовом по значению.

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

Программа на рис.15 демонстрирует спецификацию const. Функция tryToModifyArray определяется с параметром const int b[ ], который указывает, что массив b — постоянный и не может быть модифицирован. В выходных данных показаны сообщения об ошибках, вырабатываемые компилятором Borland C++. Каждая из трех попыток функции модифицировать элементы массива приводит к ошибке компилятора «Постоянный объект не может быть модифицирован».

Рис.14 – Передача функциям массивов и отдельных элементов массива (часть 1 из 3)

Рис.14 – Передача функциям массивов и отдельных элементов массива (часть 2 из 3)

Рис.14 – Передача функциям массивов и отдельных элементов массива (часть 3 из 3)

Рис.15 – Демонстрация спецификации типа const

 

Сортировка массивов

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

Программа на рис.16 сортирует значения массива а из 10 элементов в возрастающем порядке. Используемая при этом техника получила название пузырьковая сортировка или сортировка погружением, потому что наименьшее значение постепенно «всплывает», продвигаясь к вершине (началу) массива, подобно пузырьку воздуха в воде, тогда как наибольшее значение погружается на дно (конец) массива. Этот прием требует нескольких проходов по массиву. При каждом проходе сравнивается пара следующих друг за другом элементов. Если пара расположена в возрастающем порядке или элементы одинаковы, то мы оставляем значения как есть. Если же пара расположена в убывающем порядке, значения меняются местам в массиве.

Сначала программа сравнивает а[0] и а[1], затем а[1] и а[2], потом а[2] и а[3] и т.д. до тех пор, пока проход не закончится сравнением а[8] и а[9]. Хотя элементов 10, производится только девять сравнений. При выбранном способе последовательных сравнений большое значение может перемещаться в массиве вниз на много позиций за один проход, но малое значение может быть передвинуто вверх только на одну позицию. При первом проходе наибольшее значение гарантированно опустится на место нижнего элемента массива а[9]. При втором проходе второе наибольшее значение гарантированно опустится на место а[8]. При девятом проходе девятое наибольшее значение опустится на место а[1]. Это оставляет наименьшему значению место а[0], так что для сортировки массива из 10 элементов нужно только девять проходов.

Сортировка выполняется с помощью вложенного цикла for. Если необходима перестановка, она выполняется тремя присваиваниями

hold = a [i];

а [ i ] = а [ i + 1 ];

a[i + 1] = hold;

где дополнительная переменная hold временно хранит одно из двух переставляемых значений. Перестановку нельзя выполнить двумя присваиваниями

a[i] = а [i + 1];

а [ i + 1] = а [ i ];

Если, например, a[i] равно 7, a a[i + 1] равно 5, то после первого присваивания оба значения будут 5, а значение 7 будет потеряно. Следовательно, необходима дополнительная переменная hold.

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

Рис.16 – Пузырьковая сортировка массива (часть 1 из 2)

Рис.16 – Пузырьковая сортировка массива (часть 1 из 2)

 

Учебный пример: вычисление среднего значения, медианы и моды с использованием массивов

Часто компьютеры используются для обработки и анализа результатов обследований и голосований. Программа на рис.17 использует массив response, которому в качестве начальных значений присвоено 99 (размер представлен именованной константой responseSize) значений ответов при обследовании. Каждый ответ является числом от 1 до 9. Программа вычисляет среднее значение, медиану и моду 99 значений.

Среднее — это среднее арифметическое 99 значений. Функция mean вычисляет среднее путем суммирования 99 элементов и деления результата на 99.

Медиана — это «середина». Функция median определяет медиану, вызывая функцию bubbleSort, чтобы отсортировать массив ответов в порядке их возрастания, и выбирая средний элемент answer[responseSize / 2] отсор-- тированного массива. Заметим, что если массив содержит четное число элементов, медиана должна вычисляться как среднее значение двух элементов в середине массива. Функция median этой возможности не обеспечивает. Функция print Array вызывается для вывода на экран массива response.

Мода — это наиболее часто встречающееся значение среди 99 ответов. Функция mode определяет моду, подсчитывая количество ответов каждого типа и выделяя затем наиболее часто встречающийся ответ. Этот вариант функции mode не обрабатывает случай равного числа нескольких ответов (см. упражнение 14). Функция mode строит также гистограмму, чтобы помочь определить моду графически. Рис.18 содержит выходную информацию прогона программы. Этот пример включает наиболее общие операции, необходимые обычно при работе с массивами, включая передачу массивов функциям.

Рис.17 – Программа анализа данных обследования (часть 1 из 3)

Рис.17 – Программа анализа данных обследования (часть 2 из 3)

Рис.17 – Программа анализа данных обследования (часть 2 из 3)

 



Поделиться:


Последнее изменение этой страницы: 2021-04-14; просмотров: 70; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.14.253.221 (0.011 с.)