Сколько часов отработал сотрудник номер 2?: 42
Сколько часов отработал сотрудник номер 3?: 29
Сколько часов отработал сотрудник номер 4?: 35
65
Сколько часов отработал сотрудник номер 5?: 38
Сколько часов отработал сотрудник номер 6?: 37
На рис. 2. показано состояние целочисленного массива после ввода этих данных.
Рис. 2.. Состояние массива после присвоения значений его элементам.
Полезно разобраться, что произошло бы, если бы в программе 1.1 внутри цикла
"for" в операторе "cin..." отсутствовало бы вычитание 1 из переменной "count".
Компилятор Си++ (в отличие, например, от Паскаля) не обнаруживает ошибки выхо-
Да за пределы массива, поэтому участок памяти компьютера с массивом и сразу за
Ним оказался бы в состоянии, показанном на рис. 3.
Рис. 3.. Ошибка выхода за пределы массива.
Другими словами, значение "37" было бы размещено в ячейке памяти, доста-
точной для хранения целого числа, которая расположена сразу после массива "hours".
Это чрезвычайно нежелательная ситуация, потому что компилятор может зарезерви-
|
|
Ровать эту ячейку памяти для другой переменной (например, для переменной
"count").
Массивы могут быть любого типа, не обязательно типа "int". Ниже приведена
программа 1.2, в которой символьный ("char") массив применяется для печати собст-
Венного исходного файла на экране в обратном порядке.
#include <iostream.h>
#include <fstream.h>
const int MAX_LEN = 1000;
typedef char File_array[MAX_LEN];
Int main()
{
char character;
File_array file;
int count;
ifstream in_stream;
in_stream.open("prg6_1_2.cpp");
in_stream.get(character);
for (count = 0;!in_stream.eof() && count < MAX_LEN; count++)
{
file[count] = character;
66
in_stream.get(character);
}
in_stream.close();
while (count > 0)
cout << file[--count];
return 0;
}
Программа 1.2.
В заголовке цикла "for" обратите внимание на условие "... && count < MAX;
...", специально предусмотренное для предотвращения выхода за пределы массива.
Передача массивов в качестве параметров функций
Чтобы у программ была понятная человеку структура, допускающая модифи-
Кацию и повторное использование исходного текста, отдельные алгоритмы следует
Реализовывать в виде самостоятельных функций. Т.к. для хранения данных часто
Применяются массивы, то бывают необходимы и функции для их обработки. Этим
Функциям массивы можно передавать в качестве параметров. В показанном ниже
Фрагменте программы 2.1 содержится определение функции, которая принимает мас-
сив типа "Hours_array" (см. программу 1.1) и возвращает среднее количество часов,
Отработанных сотрудниками группы.
Float average(Hours_array hrs)
{
float total = 0;
int count;
for (count = 0; count < NO_OF_EMPLOYEES; count++)
total += float(hrs[count]);
return (total/NO_OF_EMPLOYEES);
}
Фрагмент программы 2.1.
Эту функцию можно сделать более универсальной, если размер массива не
|
|
фиксировать в ее определении, а передать в качестве второго параметра:
float average(int list[], int length)
{
float total = 0;
int count;
for (count = 0; count < length; count++)
total += float(list[count]);
return (total/length);
}
В этом примере показан очень распространенный способ оформления функций,
работающих с массивами: в одном параметре передается длина массива, а в другом –
Сам массив, причем в описании параметра-массива не указывается длина массива (на-
пример, "int list[]").
Параметры-массивы всегда передаются по ссылке (а не по значению), хотя при
их описании в заголовке функции символ "&" не указывается. Правило "массивы все-
67
гда передаются по ссылке" введено для того, чтобы функции не делали собственных
Внутренних копий переданных им массивов – для больших массивов это могло бы
Привести к нерациональным затратам памяти. Следовательно, как и параметры по
Ссылке, рассматривавшиеся в 3-ей лекции, все изменения элементов параметров-
Массивов внутри функций будут видны и в вызывающей функции.
Далее показана функция (фрагмент программы 2.2), принимающая в качестве
Параметров три массива. После ее вызова каждый элемент третьего массива будет ра-
Вен сумме двух соответствующих элементов первого и второго массивов.
void add_lists(int first[], int second[], int total[],
Int length)
{
int count;
for (count = 0; count < length; count++)
total[count] = first[count] + second[count];
}
Фрагмент программы 2.2.
В целях безопасности, для защиты от случайного изменения элементов масси-
ва, в описание первых двух параметров функции добавим модификатор типа "const":
void add_lists(const int fst[], const int snd[], int tot[],
Int len)
{
int count;
for (count = 0; count < len; count++)
tot[count] = fst[count] + snd[count];
}
Теперь компилятор не будет обрабатывать ни один оператор в определении
функции, который пытается модифицировать элементы константных массивов "fst"
или "snd". Фактически, ограничение, накладываемое модификатором "const" в дан-
Ном контексте, в некоторых ситуациях оказывается слишком строгим. Например,
компилятор выдаст ошибку при обработке следующих двух функций:
void no_effect(const int list[])
{
do_nothing(list);
}
void do_nothing(int list[])
{
;
}
Фрагмент программы 2.3.
Ошибка компиляции программы 2.3 объясняется тем, что, хотя фактически
функция "do_nothing(...)" не выполняет никаких действий, но в ее заголовке отсут-
ствует модификатор "const". Когда компилятор в теле функции "no_effect(...)"
встретит вызов функции "do_nothing(...)", то он обратится только к заголовку функ-
68
ции "do_nothing(...)", и выдаст ошибку о невозможности передачи константного
Массива в эту функцию.
Сортировка массивов
По отношению к массивам часто возникает задача сортировки по убыванию
Или возрастанию. Разработано много различных алгоритмов сортировки, например,
пузырьковая сортировка и быстрая сортировка. В этом параграфе кратко рассматри-
вается один из простейших алгоритмов сортировки – сортировка методом выбора
наименьшего элемента.
Основные действия алгоритма для сортировки массива длиной L заключаются
в следующем:
Для каждого значения индекса i выполнить два действия:
1) Среди элементов с индексами от i до (L -1) найти