- •Аннотация
- •Условия использования
- •Оглавление
- •Содержание
- •Только для взрослых
- •Десять лет спустя
- •Чему нас учат семья и школа?
- •Крошка сын к отцу пришел
- •Азбучные истины
- •Что я могу еще сказать?
- •Благодарности
- •Детям до 16-ти
- •Глава 1 Путь далек у нас с тобою…
- •Компьютер
- •Компилятор
- •Личный багаж
- •Компьютерная литература
- •В здоровом теле – здоровый дух
- •Вместе весело шагать по просторам!
- •Повторение – мать учения
- •Соглашения
- •Итоги
- •Глава 2 Вместо теории
- •Миф о думающих машинах
- •Загадочные коды
- •Языки программирования и компиляторы
- •Следующий шаг –
- •Итоги
- •Глава 3 Консольный интерфейс
- •Что такое интерфейс?
- •Консольный интерфейс
- •Прикосновение к консольному интерфейсу
- •А почему не «окна»?
- •Итоги
- •Глава 4 Оружие – к бою!
- •Оружейный прилавок
- •Free Pascal
- •Настройка ярлыка
- •Free Pascal
- •Установка справочной системы
- •Итоги
- •Глава 5 Программа номер один
- •Постановка задачи
- •Создание файла
- •Наполнение файла
- •Компиляция
- •Процедура вывода (печати)
- •Запуск программы
- •Итоги
- •Глава 6 Подготовка к следующему штурму
- •Еще об исходных файлах
- •Управление окном редактора
- •Борьба с ошибками
- •Итоги
- •Глава 7 Развиваем успех
- •Операторы и разделители
- •Программа, стой!
- •Алгоритмы
- •Блок-схемы
- •Итоги
- •Глава 8 Постоянные и переменные
- •Константы
- •Идентификаторы
- •Переменные
- •Ввод и вывод данных
- •Итоги
- •А слабо?
- •Глава 9 Переменные: продолжение знакомства
- •Представьтесь, пожалуйста!
- •Из пустого в порожнее
- •Сцепление строк
- •Инициализация переменных
- •Типизированные константы
- •Итоги
- •А слабо?
- •Глава 10 Условный оператор
- •Стой! Кто идет?
- •Вопрос ребром
- •Пост номер один
- •Неполный условный оператор
- •Пост номер два
- •Итоги
- •А слабо?
- •Глава 11 Операторный блок
- •Операторные скобки
- •Красиво жить не запретишь
- •Комментарии
- •Итоги
- •Глава 12 Цикл с проверкой в конце
- •Подтянем дисциплину
- •Нанимаем репетитора
- •Вежливый часовой
- •Досрочный выход из цикла
- •Итоги
- •Глава 13 Правда и кривда
- •Есть ли жизнь на Марсе?
- •Информация и её мерило
- •Булевы переменные
- •Ввод и вывод булевых данных
- •Логические выражения
- •С высоты птичьего полета
- •Парад логических операций
- •Итоги
- •А слабо?
- •Глава 14 Дважды два – четыре
- •Поможем братьям нашим меньшим
- •Числа и действия с ними
- •Алгоритм экзаменатора
- •Экзаменатор, первый вариант
- •Итоги
- •А слабо?
- •Глава 15 Айда в Монте-Карло!
- •Куда ни глянь – то процедура, то функция!
- •Госпожа удача
- •Итоги
- •А слабо?
- •Глава 16 Делу время, а потехе час
- •Потемкинская лестница
- •Итоги
- •А слабо?
- •Глава 17 И вновь за парту
- •Цикл со счетчиком
- •Итоги
- •Глава 18 Аз, Буки
- •Символьный тип данных
- •Индексация
- •Длина строки
- •Распечатка строки
- •Итоги
- •Глава 19 Процедуры и функции: разделяй и властвуй
- •Снежный ком
- •Описание процедур
- •Процедуры с параметрами
- •Итоги
- •Глава 20 Процедуры: первый опыт
- •Мухи – налево, котлеты – направо!
- •Сверху вниз
- •Первые раны
- •Глобальные и локальные
- •Локально – это разумно!
- •Неподдающаяся строка
- •Итоги
- •Глава 21 Отладка
- •Отладчик
- •Жучки, вылезайте!
- •Ссылка на переменную
- •Итоги
- •Глава 22 О передаче параметров
- •Процедура обмена
- •Замена символов в строке
- •О передаче строк
- •Итоги
- •Глава 23 Функции
- •Объявление функции
- •Пример функции
- •Подсчет символов в строке
- •Возврат строк
- •Когда результат не важен
- •Неявная переменная Result
- •Итоги
- •Глава 24 Криптография
- •Секреты Юлия Цезаря
- •Суть проблемы
- •О кодировании символов
- •Чудесные превращения
- •Шифрование символа
- •Расшифровка символа
- •Итоги
- •А слабо?
- •Глава 25 Текстовые файлы
- •Файлы хорошие и разные
- •Формат текстовых файлов
- •Доступ к текстовым файлам
- •Чтение из файла
- •Последовательный доступ к файлу
- •Самореклама
- •Цикл с проверкой в начале
- •Итоги
- •Глава 26 Я не читатель, — я писатель!
- •Запись в текстовый файл
- •Пример записи в файл
- •Завершение шпионского проекта
- •Итоги
- •А слабо?
- •Глава 27 Дайте кораблю минутный отдых!
- •Ошибка ошибке рознь
- •Фатальные ошибки
- •«Простительные» ошибки
- •Опции компилятора
- •Обработка ошибок ввода-вывода
- •Директивы компилятора
- •Директиву – в студию!
- •Парад директив
- •Итоги
- •А слабо?
- •Глава 28 Редактор и справочная система
- •Небьющиеся окна
- •Буфер обмена
- •Справочная система
- •Итоги
- •Глава 29 Читайте по-новому
- •Полицейская база данных, версия 1
- •Полицейская база данных, версия 2
- •Итоги
- •Глава 30 Журнальная история
- •Статистика знает все?
- •Строим планы
- •Барабаним по клавишам
- •Первый блин
- •Блин второй
- •Спецификатор ширины поля
- •«Развесные» числа
- •Итоги
- •Глава 31 Финал журнальной истории
- •Буква за буквой
- •Нелишняя предосторожность
- •Достройка программы
- •Испытание
- •Итоги
- •Глава 32 Порядковые типы данных
- •Типы данных: простые и сложные
- •Целое братство
- •Капля, переполняющая чашу
- •Инкремент и декремент
- •Диапазоны
- •Перечисления
- •Порядковые типы
- •Разумный контроль
- •Итоги
- •Глава 33 Вещественные числа
- •Изображение вещественных чисел
- •Вывод вещественных чисел
- •Типы вещественных чисел
- •Сравнение вещественных чисел
- •Типы данных пользователя
- •Совместимость и преобразование типов
- •Размеры переменных и типов данных
- •Итоги
- •Глава 34 Структура программы
- •Управляющие структуры
- •Структура программы
- •Структура процедур и функций
- •Обмен данными с подпрограммами
- •Встроенные процедуры и функции
- •Что дальше?
- •Итоги
- •А слабо?
- •Глава 35 Множества
- •В директорском кабинете
- •Первым делом, первым делом – оцифровка
- •Множества глазами математика
- •Числовые множества
- •Мощность множества, полные и неполные множества
- •Итоги
- •Глава 36 Множества в Паскале
- •Объявление множеств
- •Присвоение значений множествам
- •Операции с множествами
- •Сравнение множеств
- •Проверка на вхождение элемента в множество (операция IN)
- •Решение директорской задачи
- •Итоги
- •А слабо?
- •Глава 37 Ввод и вывод множеств
- •Вывод множества в текстовый файл
- •Ввод множества из текстового файла.
- •Директорская задача, первый вариант
- •Директорская задача, второй вариант
- •Итоги
- •Глава 38 Множества «в бою»
- •Активисты, шаг вперед!
- •Подвиг контрразведчика
- •В тридевятом царстве
- •Решето Эратосфена
- •Мелочь, а приятно
- •Итоги
- •А слабо?
- •Глава 39 Командная игра (массивы)
- •Снежная лавина
- •А где же волшебная палочка?
- •Массивы вокруг нас
- •Объявление массивов
- •Доступ к элементам (индексация)
- •Ввод и вывод массивов
- •Ошибки индексации
- •Итоги
- •Глава 40 Пристрелка на знакомых мишенях
- •Вопрос-ответ – добиваемся гибкости
- •Полицейская база данных – ускоряем поиск
- •Еще раз о статистике
- •Итоги
- •Глава 41 По порядку, становись!
- •Пиратская справедливость
- •Пузырьковая сортировка
- •Электронная делёжка
- •Возвращение на футбольное поле
- •Итоги
- •Глава 42 Кто ищет, тот всегда найдет
- •Где эта улица, где этот дом?
- •Последовательный поиск
- •Двоичный поиск
- •Исследование двоичного поиска
- •Ах, время, время!
- •Логарифмы? Это просто!
- •Итоги
- •Глава 43 Сортировка по-взрослому
- •Сортировка выбором
- •Быстрая сортировка
- •Процедура быстрой сортировки
- •О рекурсии и стеке
- •Алгоритмы, на старт!
- •Итоги
- •Глава 44 Строки
- •Строка – особый род массива
- •Укороченные строки
- •Операции со строками
- •Подсчет слов в строке
- •Контекстная замена
- •Итоги
- •Глава 45 Очереди и стеки
- •Вовочка в потоке событий
- •Танцевальный кружок
- •Скитания товарного вагона
- •Сортировочная горка
- •Итоги
- •Глава 46 Огромные числа
- •Сколько звезд на небе?
- •Сложение «в столбик» никто не отменял
- •Великая стройка
- •Длинная арифметика
- •Итоги
- •А слабо?
- •Глава 47 Системы счисления
- •Из тьмы веков
- •Число и его изображение
- •Десятичная система
- •Двоичная система
- •Шестнадцатеричная система
- •Другие системы счисления
- •Изображение числа в заданной системе счисления
- •Обратное преобразование
- •Итоги
- •Глава 48 Железная логика
- •Два взгляда на компьютерные «кирпичики»
- •Логические операции в регистрах
- •Сдвиги влево и вправо
- •Итоги
- •Глава 49 Сложные массивы
- •На поклон к Науке
- •Имперское строительство
- •Крестики-нолики
- •Итоги
- •А слабо?
- •Глава 50 Неспортивные рекорды (записи)
- •Кушать подано!
- •Записи
- •Второй тайм
- •Дополнительное время
- •Итоги
- •Глава 51 Указатели в море памяти
- •Погружение в оперативную память
- •«Планировка» памяти
- •Указатели, первое знакомство
- •Объявление указателей
- •Копирование указателей, пустой указатель
- •Сравнение и проверка указателей
- •Разыменование указателей
- •Нетипичный указатель
- •Примеры с указателями
- •Итоги
- •Глава 52 Динамические переменные
- •Аппетит является к обеду
- •Одолжите памяти немножко!
- •Выделение памяти
- •Освобождение памяти
- •Предупреждён – значит, вооружен
- •Итоги
- •Глава 53 Массив указателей
- •Базу данных – в кучу
- •Сортировка массива указателей
- •Итоги
- •А слабо?
- •Глава 54 Односвязные списки
- •Чудесное сочетание
- •Проблема курицы и яйца
- •Вяжем список
- •Распечатка списка
- •Поиск в несортированном списке
- •Сортированные списки
- •Поиск в сортированном списке
- •Итоги
- •Глава 55 Слова, слова, слова…
- •Частотный анализ текста
- •Слово за слово
- •Структура записи
- •Алгоритм
- •А слабо?
- •Глава 56 И снова очереди, и снова стеки…
- •Шутить изволите?
- •Танцуют все!
- •Итоги
- •Глава 57 Графомания
- •Видимое представление графа
- •Внутреннее представление графа
- •Ввод и вывод графа
- •Итоги
- •Глава 58 По графу шагом марш!
- •Империя номер два
- •Структура узла
- •В рассыпную!
- •Аты-баты
- •Итоги
- •Глава 59 Крупные проекты
- •О модулях и разделении труда
- •Модули
- •Дробление модуля – «смертельный» номер
- •Компиляция проекта
- •Инициализация модуля
- •Структура модуля
- •О совпадении имен
- •Сборочный цех
- •Фирменные библиотеки
- •Динамически загружаемые библиотеки (DLL)
- •Итоги
- •Глава 60 Мелкие хитрости
- •Включаемые файлы
- •Условная компиляция
- •Итоги
- •Глава 61 «Кубики» программиста (ООП)
- •Фокус-покус
- •Вместо паяльника
- •На трех китах
- •Инкапсуляция
- •Наследование
- •Приборостроение
- •Гражданское строительство
- •Динамические объекты
- •Полиморфизм
- •Сокрытие полей и методов
- •Итоги
- •Глава 62 Самое интересное только начинается!
- •Крупицы мастерства
- •Программисты, на старт!
- •Приложение А Установка и настройка IDE Borland Pascal
- •Borland Pascal, состав дистрибутива
- •Borland Pascal
- •Установка
- •Организация рабочей папки
- •Создание и настройка ярлыка
- •Пробный запуск
- •Предварительная настройка
- •Русификация консольного окна
- •Turbo Pascal School Pak
- •Приложение Б Консольная программа в среде Delphi
- •Создание пустого консольного приложения
- •Настройка и сохранение консольного приложения
- •Русификация консольного приложения
- •Приложение В Особенности IDE Pascal ABCNet
- •Приложение Ж Директивы управления компиляцией
- •Приложение З Назначение пунктов меню
- •Приложение И Стандартная кодировка символов MS-DOS
- •Приложение К Некоторые встроенные процедуры и функции
- •Приложение М Пример олимпиадной задачи
- •Библиография
Глава 56 И снова очереди, и снова стеки…
Новейшая версия полицейской базы данных и частотный анализатор текста укрепили ваш опыт по части динамических переменных. И все-таки, один момент нами упущен. Пока мы лишь добавляли данные в кучу, не утруждая себя её очисткой, — в решаемых задачах этого не требовалось. Но так будет не вечно, когда-то придется освобождать кучу от ненужных переменных. В этой главе мы рассмотрим два таких случая на примере знакомых нам очередей и стеков.
Шутить изволите?
Однажды, это было 1-го апреля, придворный программист Ник получил от приятеля странную «электрошку». Письмо содержало загадочный текст, очень похожий на программу, вот несколько его первых строк.
end.
Close(F);
while Pop(S) do Writeln(F, S);
{Пока стек не пуст, извлекаем и печатаем строки } Assign(F, 'P_56_1.out'); Rewrite(F);
{Открываем выходной файл }
Close(F);
end;
Приятель умолял Ника найти здесь ошибку.
Приняв во внимание 1-е апреля, Ник заподозрил розыгрыш и всмотрелся в эту абракадабру внимательней. Вскоре он сообразил, что строки в файле следуют в обратном порядке: последняя стоит первой, а первая — последней. Достойным ответом приятелю, — рассудил Ник, — будет правильный текст этой же программы. Но как переставить строки? Вручную, редактором текста? «Не царское это дело! — возмутился его разум, — пусть этим займется компьютер». И Ник написал программу для преобразования файла. Последуем за Ником.
Вы уже знакомы со стеком — временным хранилищем данных, из которого последний вставленный элемент извлекается первым (сообразно с дисциплиной LIFO). Стек — отличное средство для перестановки данных шиворот навыворот и задом наперед. Хранилищем данных в нашем первом стеке была строка, а хранимыми элементами — символы (загляните в главу 45). Скромные возможности того стека не помешали нам решить задачу о сортировочной горке.
Но чаще в стеке надо сохранять не символы, а крупные и сложные элементы данных. Так будет и в программе Ника, где элементом данных является строка. Как организовать стек из строк?
441
Глава 56 И снова очереди, и снова стеки…
Вспомним порядок элементов при вставке их в список: последний элемент оттесняет соседей, становясь на первое место. А это значит, что, извлекая элементы от головы к хвосту списка, мы получим их в обратном порядке (рис. 127).
Stack – голова списка
Адрес_3
Строка_1 |
Строка_2 |
Строка_3 |
NIL |
Адрес_1 |
Адрес_2 |
Рис. 127 – Порядок следования в стеке первых трех строк |
После извлечения элемента из стека (в данном случае — строки) отпадет нужда в хранившей его динамической переменной. К чему засорять память? Ведь этот ценный ресурс нам еще пригодится. Так давайте удалять из кучи ненужные динамические переменные.
Работу начнем, как обычно, с конструирования элемента списка. Этим элементом будет запись, включающая строку и указатель на следующую запись.
type PRec = ^TRec; |
{ Тип указатель на запись } |
TRec = record |
{ Тип запись для хранения связанных строк } |
mStr : string; |
{ хранимая строка } |
mNext : PRec; |
{ указатель на следующую запись } |
end; |
|
|
|
Напомню, что со стеком выполняются, по меньшей мере, две операции: помещение в стек PUSH, и извлечение из стека POP. В нашем случае процедура записи в стек будет объявлена так.
procedure Push(const arg : string);
Аргументом процедуры является ссылка на строку, прочитанную из файла.
Теперь об извлечении из стека. Здесь надо получить не только строку, но и сигнал о состоянии стека: пуст он, или в нем еще валяется что-то. Поэтому операцию извлечения из стека оформим булевой функцией.
442
Глава 56 И снова очереди, и снова стеки…
function Pop(var arg : string): boolean;
Строка будет возвращаться через параметр arg, — это ссылка на переменную. Но, если функция вернет FALSE, это будет сигналом того, что стек пуст и строка не возвращена.
На этом закончим рассуждения и обратимся к программе P_56_1.
{ P_56_1 – перестановка строк файла }
type PRec = ^TRec; |
{ Тип указатель на запись } |
TRec = record |
{ Тип запись для хранения связанных строк } |
mStr : string; |
{ хранимая строка } |
mNext : PRec; |
{ указатель на следующую запись } |
end; |
|
var Stack : PRec; { Голова (вершина) стека }
{ Процедура размещения строки в стеке }
procedure Push(const arg : string); var p : PRec;
begin |
|
New(p); |
{ создаем новую переменную-запись } |
p^.mStr:= arg; |
{ размещаем строку } |
{ размещаем в голове стека } |
|
p^.mNext:= Stack; |
{ указатель на предыдущую запись } |
Stack:=p; |
{ текущая запись в голове стека } |
end; |
|
{ Процедура извлечения строки из стека }
function Pop(var arg : string): boolean;
var p : PRec; |
|
begin |
|
Pop:= Assigned(Stack); |
{ Если стек не пуст, то TRUE } |
if Assigned(Stack) then begin { Если стек не пуст... } |
|
arg:= Stack^.mStr; |
{ извлекаем данные из головы стека } |
p:= Stack; |
{ временно копируем указатель на голову } |
Stack:= Stack^.mNext; { переключаем голову на следующий элемент } |
|
Dispose(p); |
{ удаляем ненужный элемент } |
end |
|
end; |
|
443
|
|
|
Глава 56 |
|
|
|
|
И снова очереди, и снова стеки… |
|
|
|
|
|
|
|
var F : text; |
S : string; |
|
|
|
begin |
{--- Главная программа ---} |
|
|
|
Stack:= nil; |
{ Инициализация стека пустым значением } |
|
{Открываем входной файл } Assign(F, 'P_56_1.pas'); Reset(F);
{Пока не конец файла, читаем строки и помещаем в стек } while not Eof(F) do begin
Readln(F, S); |
Push(S); |
end; |
|
Close(F); |
|
{Открываем выходной файл } Assign(F, 'P_56_1.out'); Rewrite(F);
{Пока стек не пуст, извлекаем и печатаем строки } while Pop(S) do Writeln(F, S);
Close(F);
end.
Процедура Push повторяет процедуру вставки элемента в список. А в теле функции Pop посмотрите на подчеркнутые операторы. После извлечения строки ненужный теперь элемент стека уничтожается процедурой Dispose(p), — так освобождается память. Но перед этим указатель на следующий элемент надо сохранить в голове списка, иначе мы потеряем ссылку на цепочку оставшихся элементов.
Изваяв программу, Ник испытал её волшебное действие на её собственном тексте. Каково же было его удивление, когда результат совпал с абракадаброй, полученной от приятеля! Вот такое чудесное совпадение!
Танцуют все!
Ох уж эти танцы… Задачу о танцевальном кружке мы решили в 45-й главе. Освежите её в памяти, поскольку новый вариант решения будет похож на первый.
Только теперь мы изменим имена мальчиков и девочек. В том варианте, как вы помните, дети носили однобуквенные имена, и мы представили их символами. Теперь же мы дадим им настоящие человеческие имена, но для этого и очередь организуем иначе. Как? Вы уже догадались: посредством односвязного списка
(рис. 128).
444
Глава 56 И снова очереди, и снова стеки…
Queue – голова очереди
Первый элемент очереди
Адрес_3 |
Последний элемент |
|
очереди |
Строка_1 |
Строка_2 |
Строка_3 |
NIL |
Адрес_1 |
Адрес_2 |
Рис. 128 – Размещение в очереди трех строк |
Кажется, что этот рисунок совпадает с рисунком для стека. Так оно и есть. Только элементы теперь извлекаются в ином порядке. Первым элементом в очереди назначим тот, что в хвосте списка. Значит, по сравнению со стеком, в очереди все наоборот: первым элементом очереди является последний элемент списка, и для доступа к нему придется пробежать по всей цепочке ссылок.
Это обстоятельство вынудит нас изменить процедуру удаления первого элемента очереди. Теперь перед удалением надо заполучить указатель на предпоследний элемент списка. В нем надлежит поставить заглушку NIL, чтобы отцепить первый элемент очереди (рис. 129). В этом состоит главная премудрость обращения с очередью строк.
Queue – голова очереди
Старый первый Новый первый элемент P1
элемент P2
Адрес_3
Строка_1
Строка_2
Строка_3
NIL
Адрес_2
NIL
Рис. 129 – Отцепление первого элемента очереди
445
Глава 56 И снова очереди, и снова стеки…
Так же как и для стека, для очереди надо запрограммировать, по меньшей мере, две операции: установку и извлечение из нее.
Процедуру установки в очередь PutInQue объявим так.
procedure PutInQue(var Que: PRec; const arg: string);
Два её параметра — это ссылка на очередь (на голову списка) и помещаемая в очередь строка.
Для извлечения из очереди потребуется уже не процедура, а функция, назовем её GetFromQue, и объявим так.
function GetFromQue(var Que: PRec; var arg: string): boolean;
Здесь опять заметно сходство со стеком: как только очередь окажется пустой, функция сообщит об этом, вернув значение FALSE. И тогда мы отвергнем возвращаемый через ссылку arg результат.
Осталось обсудить еще одну мелочь: организацию входных данных с тем, чтобы отличать мальчиков от девочек. Имена детей поместим в файл «P_56_2.IN», а для различения мальчиков и девочек, впечатаем имена девочек с некоторым отступом (с одним или несколькими пробелами в начале строки). Вот пример такого входного файла.
Ваня
Петя
Гриша
Маша
Наташа
Коля
Семен
Света
Теперь вы готовы рассмотреть программу P_56_2.
446
Глава 56
Иснова очереди, и снова стеки…
{P_56_2 – Запись в танцевальный кружок, версия 2 }
type PRec = ^TRec; |
{ Тип указатель на запись } |
TRec = record |
{ Тип запись для хранения связанных строк } |
mStr : string[31]; |
{ хранимая строка (имя) } |
mNext : PRec; |
{ указатель на следующую запись } |
end; |
|
{ Процедура размещения строки в очереди }
procedure PutInQue(var Que: PRec; const arg: string);
var p: PRec; |
|
begin |
|
New(p); |
{ создаем новую переменную-запись } |
p^.mStr:= arg; |
{ размещаем строку } |
{ размещаем указатель в голове очереди } |
|
p^.mNext:= Que; |
{ указатель на предыдущую запись } |
Que:=p; |
{ текущая запись в голове очереди } |
end; |
|
{ Извлечение строки из начала очереди (из конца списка) } function GetFromQue(var Que: PRec; var arg: string): boolean; var p1, p2: PRec;
begin
GetFromQue:= Assigned(Que); if Assigned(Que) then begin
{Поиск первого элемента очереди } p1:= Que; p2:=p1;
{если в очереди только один элемент, цикл не выполнится ни разу! } while Assigned(p1^.mNext) do begin
p2:=p1; |
{ текущий } |
p1:=p1^.mNext; |
{ следующий } |
end; |
|
{теперь p1 указывает на первый элемент очереди, а p2 – на второй
(или на тот-же самый, если в очереди всего один элемент) }
arg:= p1^.mStr; |
{ извлекаем данные } |
if p1=p2 |
{ если в очереди был один элемент... } |
then Que:= nil |
{ очередь стала пустой } |
else p2^.mNext:= nil; |
{ а иначе отцепляем первый элемент } |
Dispose(p1); |
{ освобождаем память первого элемента } |
end; |
|
end; |
|
447
|
|
|
Глава 56 |
|
|
|
|
И снова очереди, и снова стеки… |
|
|
|
|
|
|
|
var |
|
|
|
|
Boys |
: PRec; |
{ очередь мальчиков } |
|
|
Girls |
: PRec; |
{ очередь девочек } |
|
|
S1, S2 : String; { строки с именами } |
|
||
|
Boy: boolean; |
{ признак чтения имени мальчика } |
|
|
|
F_In, F_Out : Text; { входной и выходной файла } |
|
||
|
begin |
{--- Главная программа ---} |
|
|
|
{ Очищаем очереди мальчиков и девочек } |
|
||
|
Boys := nil ; |
{ очередь мальчиков } |
|
|
|
Girls := nil; |
{ очередь девочек } |
|
Assign(F_In, 'P_56_2.in'); Reset(F_In);
Assign(F_Out,'P_56_2.out'); Rewrite(F_Out);
{ Цикл обработки входного потока } |
|
|
while not Eof(F_In) do begin |
|
|
Readln(F_In, S1); |
{ выбираем имя из входного потока } |
|
Boy:= S1[1]<>' '; |
{ строки с именами девочек начинаются с пробела! } |
|
while S1[1]=' ' do Delete(S1,1,1); |
|
|
if Boy |
|
|
then begin { если это мальчик...} |
|
|
if GetFromQue(Girls, S2) |
{ если в очереди есть девочка } |
|
then Writeln(F_Out,S1+' + '+S2) { пару -> в выходной поток } |
||
else PutInQue(Boys, S1); |
{ а иначе мальчика в очередь } |
|
end |
|
|
else begin { а если это девочка...} |
||
if GetFromQue(Boys, S2) |
{ если в очереди есть мальчик } |
|
then Writeln(F_Out,S2+' + '+S1) { пару -> в выходной поток } |
||
else PutInQue(Girls, S1); |
{ а иначе девочку в очередь } |
|
end |
|
|
end;
Close(F_In); Close(F_Out); end.
448