- •Предисловие
- •Основы программирования
- •Понятие алгоритма.
- •Алгоритм Евклида.
- •Задача о поездах и мухе
- •Вместо лирического отступления
- •Этапы подготовки задачи для решения на компьютере
- •Примеры разработки алгоритмов
- •Решение квадратного уравнения.
- •Вычисление интегралов
- •Обработка результатов эксперимента
- •Решение системы линейных алгебраических уравнений
- •Введение в язык программирования Pascal
- •Основные элементы языка
- •Переменные. Стандартные типы.
- •Операции отношения
- •Раздел описаний переменных
- •Выражения. Порядок выполнения операций.
- •Константы
- •Комментарии в программе
- •Операторы
- •2.1.7.1. Оператор присваивания
- •2.1.7.2. Операторы ввода/вывода
- •2.1.7.3. Операторы инкремента и декремента
- •Среда разработки Lazarus
- •Русский язык в консольных приложениях
- •Первая программа
- •Открытие существующего проекта
- •Другие способы создания консольных приложений
- •Типовой пустой проект
- •Операции с целыми числами
- •Вместо лирического отступления 2
- •Стандартные функции с целыми аргументами
- •Операции с вещественными числами (тип real).
- •Форматирование вывода
- •Одновременное использование вещественных и целых чисел.
- •Другие стандартные функции с вещественными аргументами
- •Булевы переменные
- •Условные операторы.
- •2.1.22.1 Оператор if …. then
- •2.1.22.2. Оператор if …then ... else
- •Операторы цикла
- •2.1.23.1. Оператор цикла с предусловием
- •2.1.23.2. Оператор цикла с постусловием
- •2.1.23.3. Оператор цикла с параметром.
- •2.1.23.4. Второй вариант оператора цикла с параметром
- •Оператор выбора case
- •Организация простейшего контроля ввода данных.
- •Вычисление сумм сходящихся рядов
- •Реализация некоторых алгоритмов главы 1.
- •Программа решения задачи о поездах и мухе
- •Программа вычисления определенного интеграла
- •Более сложные элементы языка
- •Общая структура Паскаль – программы
- •Процедуры и функции
- •3.1.1.1 Структура процедуры
- •3.1.1.2. Структура функции
- •3.1.1.3 Глобальные и локальные переменные
- •3.1.1.4 Способы передачи параметров
- •3.1.1.5 Процедуры завершения
- •Еще раз о типах данных
- •Классификация типов данных
- •3.2.1.1 Целый тип
- •3.2.1.2. Интервальный тип
- •3.2.1.3. Перечислимый тип
- •3.2.1.4. Множества
- •3.2.1.5. Логический тип
- •3.2.1.6. Вещественный тип
- •3.2.1.7. Указатели
- •Обработка символьной информации в Паскале
- •Символьные и строковые типы данных.
- •3.3.1.1. Тип Char
- •3.3.1.2. Функции для работы с символами
- •3.3.1.3. Тип String
- •3.3.1.4. Строковые процедуры и функции
- •Массивы
- •Динамические массивы
- •Программа решения системы линейных алгебраических уравнений методом Гаусса
- •3.4.1.1. Вариант 1 – с goto
- •3.4.1.2. Вариант 2 – без goto
- •3.4.1.3. Вариант 3 – наилучшая реализация
- •Модули в Паскале
- •Структура модуля
- •Системные модули
- •3.5.2.1. Модуль CRT
- •Файлы
- •Тип данных – запись
- •Файловые типы
- •Процедуры для работы с файлами
- •3.6.3.1. Общие процедуры для работы с файлами всех типов
- •3.6.3.2. Процедуры для работы с текстовыми файлами
- •3.6.3.3. Процедуры для работы с типизированными файлами
- •3.6.3.4. Процедуры для работы с нетипизированными файлами
- •3.6.3.5. Организация контроля ввода/вывода при работе файлами
- •3.6.3.6. Создание простой базы данных с типизированными файлами.
- •Алгоритмы сортировки
- •Обменная сортировка (метод "пузырька")
- •Сортировка выбором
- •Сортировка вставками
- •Метод быстрой сортировки
- •Алгоритмы поиска
- •Поиск в массивах
- •Вставка и удаление элементов в упорядоченном массиве
- •Динамические структуры данных
- •Представление в памяти компьютера динамических структур.
- •Реализация стека с помощью массивов
- •Указатели
- •Стандартные операции с линейными списками
- •Реализация динамических структур линейными списками
- •4.3.6.1. Реализация стека
- •4.3.6.2. Реализация очереди с помощью линейного списка
- •4.3.6.3. Реализация двоичного дерева с помощью линейного списка
- •Сортировка и поиск с помощью двоичного дерева
- •Три источника и три составные части ООП.
- •Классы и объекты.
- •Обращение к членам класса.
- •Инкапсуляция
- •Спецификаторы доступа.
- •Свойства.
- •Наследование
- •Полиморфизм
- •Раннее связывание.
- •Позднее связывание.
- •Конструкторы и деструкторы.
- •Элементы графического интерфейса
- •Различия между консольными и графическими приложениями
- •Визуальное программирование в среде Lazarus
- •Создание графического приложения
- •Форма и ее основные свойства
- •Компоненты
- •Обработчики событий
- •Простейшие компоненты
- •6.3.5.1. Компонент TLabel
- •6.3.5.2. Кнопки TButton, TBitBtn и TSpeedButton
- •6.3.6.1. Компонент TEdit
- •6.3.6.2. Компонент TLabeledEdit
- •6.3.7.1. Компонент TMaskEdit
- •Специальные компоненты для ввода чисел
- •Тестирование и отладка программы
- •Компоненты отображения и выбора данных
- •6.3.10.1. Компонент TMemo
- •6.3.10.2. Компонент TStringGrid
- •6.3.10.3. Компоненты выбора
- •Компонент TListBox
- •Компонент TComboBox
- •Компоненты выбора – переключатели
- •6.3.10.4. Компоненты отображения структурированных данных
- •Компонент TTreeView
- •Компонент TListView
- •Организация меню. Механизм действий - Actions
- •6.3.11.1. Компонент TMainMenu
- •6.3.11.2. Компонент TToolBar
- •6.3.11.3. Компонент TActionList
- •6.3.11.4. Создание приложений с изменяемыми размерами окон
- •Послесловие
- •Литература
- •Алфавитный указатель
3.4 Массивы
____________________________________________________________________
3.4.Массивы
Внекоторых случаях приходится сталкиваться с ситуацией, когда должно использоваться относительно много переменных одного типа.
Представим себе программу, которая позволяет вычислить определенные метеорологические данные и в которой всегда будет не меньше 365 перемен-
ных. Таким образом можно присваивать отдельным переменным метеорологи-
ческие данные по отдельным дням всего года.
В принципе сейчас нет никакой проблемы, чтобы объявить тип real у 365
переменных, используя запись.
var day1, day2, day3 и т.д. day365:real;
Однако в Паскале нельзя писать и "т.д.". Нужно перечислить все перемен-
ные. Для этого нужна по крайней мере страница. Если теперь нужно подсчи-
тать среднее арифметическое на один день, то нужно записать:
sred:= (day1+day2+и т.д. day365)
и опять как быть с "и т.д."?
Для таких случаев Паскаль предоставляет возможность введения большого числа переменных одного и того же типа, используя простые выражения.
Эта возможность в Паскале реализуется с помощью так называемых мас-
сивов. Используется служебное слово array, которое указывает на ряд пере-
менных одного и того же типа и имеющих одно имя.
Например:
var
day: array[1..365] of real;
С помощью этого описания определяется массив day состоящий из 365
элементов (переменных) вещественного типа. Каждый элемент массива может использоваться как отдельная переменная. Можно записать:
day[1]:= 1.25;
190
Глава 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