Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Мансуров. Основы программирования в среде Lazarus. 2010

.pdf
Скачиваний:
45
Добавлен:
27.04.2021
Размер:
6.3 Mб
Скачать

Глава 3 Более сложные элементы языка

____________________________________________________________________

day[2]:= 0.34;

Другими словами, каждый элемент массива определяется именем массива и номером элемента в квадратных скобках. Говорят еще индекс массива. При-

чем в качестве индекса можно использовать арифметическое выражение целого типа.

В описании массива после имени в квадратных скобках указывается ми-

нимальное значение индекса, затем две точки без пробелов и максимальное значение индекса. В нашем случае массив day состоит из 365 элементов, ну-

мерация идет от 1 до 365 т.е. шаг нумерации по умолчанию всегда равен 1.

При использовании массивов запись программы становится намного коро-

че и наглядней.

Пусть, например, в начале, все элементы массива day должны быть при-

равнены 0.

Вместо того, чтобы писать

day[1]:= 0; day[2]:= 0;

и т.д.

day[365]:= 0;

мы можем поступить следующим образом:

var

day: array[1..365] of real; k: integer;

begin

for k:= 1 to 365 do day[k]:= 0;

Пример.

Пусть имеются 2 массива типа string. В одном массиве содержатся фа-

милии людей, а в другом номера их домашних телефонов. Написать программу,

191

3.4 Массивы

____________________________________________________________________

которая в цикле по номеру телефона выводит на экран фамилию этого абонен-

та.

program phone_1; {$mode objfpc}{$H+} uses

CRT, FileUtil, SysUtils; var

name: array[1..50] of string[30]; tel: array[1..50] of string[3]; k: integer;

phone: string[3]; begin

for k:=1 to 50 do begin

writeln(UTF8ToConsole('Введите фамилию')); readln(name[k]); writeln(UTF8ToConsole('Введите номер телефона')); readln(tel[k]);

{Удаляем ведущие и ведомые ("хвостовые") пробелы}

tel[k]:= Trim(tel[k]);

end;

writeln(UTF8ToConsole('Ввод данных закончен')); writeln(UTF8ToConsole('Для поиска абонента введите')); writeln(UTF8ToConsole('номер его телефона')); writeln(UTF8ToConsole('Для выхода из программы')); writeln(UTF8ToConsole('введите ''***'''));

phone:= '';

while phone <> '***' do

192

Глава 3 Более сложные элементы языка

____________________________________________________________________

begin

writeln(UTF8ToConsole('Введите номер телефона'));

readln(phone);

for k:= 1 to 50 do

if tel[k] = phone then

writeln(UTF8ToConsole('Фамилия этого абонента '),

name[k]);

end;

end.

Недостаток этой программы в том, что если указанный номер телефона в массиве не существует, то никаких сообщений на этот счет на экран не выво-

дится. Кроме того, после того как найден абонент, например для k=2, програм-

ма ещѐ 48 раз прокрутит цикл. Как модифицировать программу?

program phone_2; {$mode objfpc}{$H+} uses

CRT, FileUtil, SysUtils; var

name: array[1..50] of string[30]; tel: array[1..50] of string[7]; k: integer;

phone: string[7]; found: boolean;

begin

for k:= 1 to 50 do begin

writeln(UTF8ToConsole('Введите фамилию'));

193

3.4 Массивы

____________________________________________________________________

readln (name[k]);

writeln(UTF8ToConsole('Введите номер телефона'));

readln(tel[k]);

{Удаляем ведущие и ведомые ("хвостовые") пробелы}

tel[k]:= Trim(tel[k]);

end;

writeln(UTF8ToConsole('Ввод данных закончен')); writeln(UTF8ToConsole('Для поиска абонента введите')); writeln(UTF8ToConsole('номер его телефона')); writeln(UTF8ToConsole('Для выхода из программы')); writeln(UTF8ToConsole('введите ''***'''));

phone:= '';

while phone <> '***' do begin

found:= false;

writeln(UTF8ToConsole('Введите номер телефона')); readln(phone);

for k:= 1 to 50 do

if tel[k]= phone then begin

writeln(UTF8ToConsole('Фамилия этого абонента '), name[k]);

found:= true; break;

end;

if not found then

writeln(UTF8ToConsole('Абонента с таким номером нет')); end;

end.

194

Глава 3 Более сложные элементы языка

____________________________________________________________________

Здесь мы ввели булевую переменную found, которой присваиваем значе-

ние true, если абонент с указанным номером найден. Затем мы "досрочно"

выходим из цикла for командой break. Во внешнем цикле, если абонент не найден, выводим соответствующее сообщение на экран.

Если вы несколько раз запускали программу, то могли видеть, что каждый раз приходится заново вводить фамилии и телефоны. Вводить их при каждом новом прогоне программы явно неудобно. Единственный выход – сохранить введенные данные в файле. Но, поскольку, мы еще использование файлов в Паскале не изучали, введем признак окончания ввода. Договоримся, что если вместо очередной фамилии мы введем строку '***', то это означает, что ввод данных закончен. Теперь мы можем вводить лишь несколько фамилий и теле-

фонов только для того, чтобы убедиться в работоспособности программы.

program phone_3; {$mode objfpc}{$H+} uses

CRT, FileUtil, SysUtils; var

name: array[1..50] of string[30]; tel: array[1..50] of string[7]; fam: string[30];

k, n: integer; phone: string[7]; found: boolean;

begin n:= 0;

writeln(UTF8ToConsole('Введите фамилию')); writeln(UTF8ToConsole('Чтобы закончить ввод введите "***"'));

for k:= 1 to 50 do

195

3.4 Массивы

____________________________________________________________________

begin

readln (fam);

if fam = '***' then break;

name[k]:= fam;

n:= n + 1;

writeln(UTF8ToConsole('Введите номер телефона'));

readln(tel[k]);

{Удаляем ведущие и ведомые ("хвостовые") пробелы}

tel[k]:= Trim(tel[k]);

writeln(UTF8ToConsole('Введите фамилию'));

end;

if n = 0 then exit;

writeln(UTF8ToConsole('Ввод данных закончен')); writeln(UTF8ToConsole('Для поиска абонента введите')); writeln(UTF8ToConsole('номер его телефона')); writeln(UTF8ToConsole('Для выхода из программы')); writeln(UTF8ToConsole('введите ''***'''));

phone:= ' ';

while phone <> '***' do begin

found:= false;

writeln(UTF8ToConsole('Введите номер телефона')); readln(phone);

for k:= 1 to n do

if tel[k] = phone then begin

writeln(UTF8ToConsole('Фамилия этого абонента '), name[k]);

found:= true;

196

Глава 3 Более сложные элементы языка

____________________________________________________________________

break;

end;

if not found then

writeln(UTF8ToConsole('Абонента с таким номером нет'));

end;

end.

И опять не останавливаемся на достигнутом, ищем недостатки в програм-

ме, улучшаем и совершенствуем ее. Собственно так и поступают все разработ-

чики программ. Они распространяют свои программные продукты версиями,

улучшая и совершенствуя свою программу от версии к версии.

В нашем случае мы научились вводить меньше данных, чем зарезервиро-

вали в массивах name и tel, но компилятор распределит память для всего объ-

ема массивов. Значит, часть памяти останется неиспользованной. Налицо нера-

циональное использование памяти. Хотя для современных компьютеров про-

блемы с объемами доступной памяти не столь остры, как в недавнем прошлом,

все же ни один профессиональный программист не пойдет на резервирование памяти, так сказать, "про запас", использует ровно столько памяти, сколько ему нужно. Для исправления этого недостатка в нашей программе воспользуемся так называемыми динамическими массивами.

3.4.1 Динамические массивы

Динамический массив – это массив, память для которого выделяется дина-

мически во время выполнения программы. А в момент компиляции его реаль-

ный размер неизвестен. Компилятор просто выделяет память для указателя на этот массив (4 байта).

При описании динамического массива границы не указываются, а указыва-

ется только его тип, например:

197

3.4 Массивы

____________________________________________________________________

var

name array of string[30];

tel array of string[7];

Перед использованием такого массива необходимо установить размер мас-

сива с помощью процедуры SetLength(имя массива, размер), например:

SetLength(name, 50);

В этом случае для массива name будет выделено (динамически!) память для размещения 50 элементов.

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

пример, описывается 3-х мерный динамический массив:

a: array of array of array of integer;

Выделим под этот массив память:

SetLength(a, 50, 50, 50);

После использования динамических массивов, память, распределенная для них, будет автоматически освобождена. Но можно и "вручную" освободить па-

мять, занимаемую динамическим массивом. Для этого достаточно присвоить массиву значение nil.

a:= nil;

Поскольку для реализации динамических массивов используется механизм указателей, применение оператора присваивания

b:= a;

где a и b динамические массивы не приведет к созданию нового массива b,

а будут созданы два указателя, ссылающиеся на одни и те же участки памяти.

Т.е. изменение элемента массива b приведет к изменению соответствующего элемента массива a, поскольку фактически это одно и то же данное, только с разными именами (в нашем случае a и b).

Для того чтобы создать другой массив идентичный по содержанию необ-

ходимо использовать процедуру Copy(), например:

198

Глава 3 Более сложные элементы языка

____________________________________________________________________

b:= Copy(a);// полная копия массива a

Можно скопировать часть массива:

b:= Copy(a, 5, 5);

В новый массив b будет скопировано 5 элементов массива a, начиная с пя-

того элемента.

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

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

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

мера массива использовали функцию high(), а в процедуру передали факти-

ческий размер массива через параметр.

program phone_4; {$mode objfpc}{$H+} uses

CRT, FileUtil, SysUtils; var

name: array of string[30]; tel: array of string[7]; n: integer;

phone: string[7];

{Эта функция осуществляет поиск абонента по его номеру телефона}

function find_data (var name: array of string[30];

var tel: array of string[7];

199

3.4 Массивы

____________________________________________________________________

phone:string[7]): boolean;

var

k: integer; begin

find_data:= false;

for k:= 0 to high(tel) do

if (tel[k] = phone) and (phone <> '') then begin

writeln(UTF8ToConsole('Фамилия этого абонента '), name[k]);

find_data:= true;

break;

end;

end;

{Процедура ввода фамилий и номеров телефонов}

procedure data_input(var name: array of string[30]; var tel: array of string[7]; var n: integer);

var

k: integer; fam: string[30];

begin

writeln(UTF8ToConsole('Введите фамилию')); writeln(UTF8ToConsole('Чтобы закончить ввод введите "***"'));

for k:= 0 to n - 1 do

begin

//запомним текущий индекс в переменной n n:= k; // по его значению мы потом

//установим фактический размер массивов

200