Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pesni_o_Paskale_2012-11-23.pdf
Скачиваний:
35
Добавлен:
19.03.2016
Размер:
5.16 Mб
Скачать

Глава 37 Ввод и вывод множеств

Мы узнали о множествах и приспособили их к директорской задаче. Чтобы покончить с нею, cделаем ещё пару пустяков: организуем ввод и вывод множеств. Для ввода-вывода строк и простых типов данных годятся процедуры Read[ln] и Write[ln]. Но сейчас все не так просто, — эти процедуры не способны работать ни с множествами, ни с другими сложными типами данных. Однако ж «нормальные герои всегда идут в обход», — пойдем так и на этот раз.

Вывод множества в текстовый файл

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

Раз уж процедура Writeln не печатает множество одним махом, выведем каждый его элемент по отдельности — ведь это обычные числа или символы. Проверяя все возможные элементы множества, будем печатать лишь те, что входят в него — в этом основная идея. Напомню, что для такой проверки подходит операция IN. Дополнив её циклом со счетчиком, соорудим несложную процедуру распечатки числового множества. Вот она вместе с программой для её проверки.

{ P_37_1 – вывод множества в файл }

 

type TSet = set of 1..255;

{ объявление типа «множество» }

{----- Процедура вывода множества в файл -----}

procedure WriteSet(var aFile: text; const aSet : TSet);

var k : integer;

 

 

begin

 

 

for k:=1 to 255 do

{ цикл по всем элементам множества}

if k in aSet

{ если K входит в множество }

then Write(aFile, k:4);

{ печатаем в строке }

Writeln(aFile); { по окончании – переход на следующую строку }

end;

262

 

 

 

Глава 37

 

 

 

Ввод и вывод множеств

 

 

 

 

 

{----- Программа для проверки процедуры WriteSet -----}

 

 

var S1 : TSet;

F: text;

 

 

 

begin

 

 

 

 

Assign(F, ''); Rewrite(F);

{ связываем файл с экраном! }

 

 

S1:= [3, 10, 25];

 

{ значение множества }

 

 

WriteSet(F, S1);

 

{ печатаем }

 

 

Readln;

 

 

 

 

Close(F);

 

 

 

 

end.

 

 

 

 

 

 

 

 

В первой строке объявлен тип данных TSet, он может содержать целые числа от 1 до 255. Процедура распечатки WriteSet принимает по ссылке два параметра: файловую переменную и множество, которое надо распечатать. Внутри процедуры работает цикл FOR, перебирающий все возможные элементы множества. Те из них, что содержатся в нем, печатаются в текущей строке. По завершении цикла оператор Writeln переводит позицию записи на следующую строку файла.

Обратите внимание: множество передано в процедуру по ссылке CONST. Передача в процедуры множеств, строк и других сложных типов данных по ссылкам CONST и VAR — это обычная практика. Так повышается скорость работы программ и уменьшается объём памяти, занимаемый параматрами.

Теперь взгляните на оператор Assign(F,''), который назначает файловой переменной пустое имя файла. Так файловая переменная связывается с экраном дисплея (при выводе данных), либо с клавиатурой (при вводе). А когда вам потребуется вывести результаты в дисковый файл, достаточно будет задать нужное имя файла, не меняя процедуры WriteSet (этот прием — подстановка пустого имени — не работает в Pascal ABCNet).

Примечание. В современные версии Паскаля (Delphi) для обработки множеств введён вариант цикла FOR-IN-DO. С ним вывод множества станет ещё проще:

for k in aSet do Write(aFile, k:4);

Ввод множества из текстового файла.

Разобравшись с распечаткой множества, перейдем к вводу его из файла. Есть соображения на этот счет? Здесь пригодится опыт чтения чисел из строки текстового файла, — вспомните обработку классного журнала. Добавить число к множеству мы тоже умеем, — для этого надо объединить его с множеством, состоящим из добавляемого числа. На этих идеях построена процедура ввода, показанная ниже вместе с тестирующей её программой.

263

 

 

 

 

Глава 37

 

 

 

 

Ввод и вывод множеств

 

 

 

 

 

{ P_37_2 – ввод и вывод числового множества }

 

 

type

TSet = set of 1..255; { объявление типа «множество» }

 

 

 

{----- Процедура чтения множества из файла -----}

 

 

procedure ReadSet(var aFile: text; var aSet : TSet);

 

 

var

k : integer;

 

 

 

 

 

begin

While not Eoln(aFile) do begin

{ пока не конец строки }

 

 

 

 

 

 

Read(aFile, K);

 

{ читаем очередное число }

 

 

 

aSet:= aSet+[K];

 

{ и добавляем к множеству }

 

 

 

end;

 

 

 

 

 

end;

Readln (aFile);

 

 

{ переход на следующую строку }

 

 

{----- Процедура распечатки множества в файл -----}

 

 

 

 

 

procedure WriteSet(var aFile: text; const aSet : TSet);

 

 

var k : integer;

 

 

 

 

 

begin

for k:=1 to 255 do

{ цикл по всем элементам множества}

 

 

 

 

 

 

if k in aSet

{ если входит в множество }

 

 

 

then Write(aFile, k:4); { печатаем в строке }

 

 

end;

Writeln(aFile);

{ по окончании переход на следующую строку }

 

 

 

 

 

 

 

 

 

{----- Программа для проверки процедуры ввода -----}

 

 

var

S1 : TSet;

F, D: text;

 

 

 

 

begin

Assign(F, ''); Rewrite(F);

{ вывод на экран }

 

 

 

 

 

 

Assign(D, ''); Reset(D);

{ ввод с клавиатуры }

 

 

 

S1:= [];

 

{ перед вводом опустошаем множество }

 

 

 

ReadSet(D, S1);

 

{ вводим множество из файла }

 

 

 

WriteSet(F, S1);

Readln;

{ распечатаем для проверки }

 

Close(F); Close(D);

end.

Полагаю, что комментарии поясняют все. Обязательно проверьте работу этой программы. Учтите, что вводить данные вы будете с клавиатуры: напечатайте в одной строке несколько чисел, разделяя их пробелами, а затем нажмите Enter.

Директорская задача, первый вариант

Освоив ввод и вывод множеств, мы вплотную подошли к полному решению директорской задачи. Напомню, что суть решения заключается всего в одном операторе:

264

Глава 37

Ввод и вывод множеств

R:= [1..250] – (S1 + S2 + S3);

Теперь добавим ввод и вывод множеств. Чтобы не занимать место повторами показанных ранее процедур, я представлю решение в целом.

{ P_37_3 – решение директорской задачи, вариант 1 }

const

CMax

=

20;

{ мощность множества, реально 250 }

type

TSet

=

set of 1..CMax;

{ объявление типа «множество» }

procedure WriteSet(var aFile: text; const aSet : TSet); { взять из P_37_2 }

procedure ReadSet(var aFile: text; var aSet : TSet); { взять из P_37_2 }

var R, S1, S2, S3 : TSet;

FileIn, FileOut: text;

begin {----- Главная программа -----}

{ Открытие входного файла }

Assign(FileIn, 'P_37_3.in'); Reset(FileIn); { Создание выходного файла }

Assign(FileOut, 'P_37_3.out'); Rewrite(FileOut); { Ввод множеств из входного файла }

S1:=[];

ReadSet(FileIn, S1);

S2:=[];

ReadSet(FileIn, S2);

S3:=[];

ReadSet(FileIn, S3);

R:= [1..CMax] – (S1+S2+S3);

{ Решение }

WriteSet(FileOut, R);

{ Вывод решения в выходной файл }

Close(FileIn);

Close(FileOut);

end.

Для ввода и вывода множеств используем дисковые файлы, поэтому оператор Readln в конце программы не нужен. Для облегчения проверки я уменьшил число учеников — константу CMax — с 250 до 20. При тестировании программы входной файл содержал следующие строки:

265