Министерство общего и профессионального образования Российской Федерации РОСТОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ КАФЕДРА ...
13 downloads
317 Views
415KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Министерство общего и профессионального образования Российской Федерации РОСТОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ КАФЕДРА ТЕОРЕТИЧЕСКОЙ И ВЫЧИСЛИТЕЛЬНОЙ ФИЗИКИ _______________________________________________________________
Т. П. Шестакова МЕТОДИЧЕСКИЕ УКАЗАНИЯ по курсу "Программирование и вычислительная физика" Часть IV Типы данных языка Turbo Pascal. Указатели. Строки. Множества
г. Ростов-на-Дону 2003 г.
2
Печатается по решению учебно-методической комиссии физического факультета. Протокол N от Шестакова Т. П. Методические указания по курсу "Программирование и вычислительная физика". Часть IV. Типы данных языка Turbo Pascal. Указатели. Строки. Множества. Заказ N
3
ВВЕДЕНИЕ В четвертой части методических указаний рассматриваются возможности размещения данных в динамической памяти (в частности, организация в динамической памяти простейшей структуры данных − списка), типизированные и нетипизированные указатели, тип данных string (строки), а также стандартные процедуры и функции для работы с этими типами данных. ДИНАМИЧЕСКАЯ ПАМЯТЬ И ИСПОЛЬЗОВАНИЕ УКАЗАТЕЛЕЙ При запуске программы на языке Turbo Pascal все данные, используемые в программе, обычно размещаются в одной непрерывной области оперативной памяти, называемой сегментом данных, длина которой составляет 64 Кбайт. При работе с большим количеством данных возникают проблемы, связанные с невозможностью размещения их в сегменте данных. Для решения этих проблем язык Turbo Pascal содержит специальные средства, позволяющие использовать для хранения данных динамическую память. Динамическая память − это вся свободная область оперативной памяти, которая предоставляется программе при ее работе, за исключением сегмента данных, стека и области памяти, занимаемой самой программой. Данные размещаются в динамической памяти непосредственно при работе программы. Для этой цели используются переменные специального типа − указатели, которые в качестве своего значения содержат адрес ячейки памяти. В языке Turbo Pascal используются типизированные и нетипизированные указатели. Типизированные указатели "указывают" на переменную определенного типа (т. е. значением типизированного указателя является адрес переменной определенного типа). Тип указателя образуется из названия типа переменной, перед которым ставится значок "^". Описание типизированного указателя: type <имя типа> = ^<тип переменной>; Например, переменная p1 имеет тип IntPointer, − является указателем на переменную типа integer: type IntPointer = ^integer;
4
var p1: IntPointer; Альтернативно, переменную типа указатель можно объявлять в программе без предварительного описания самого типа: var <имя переменной>: ^<тип переменной>; var p2: ^real; Типизированному указателю, указывающему на переменную одного типа, нельзя присвоить в качестве значения адрес переменной другого типа, иными словами, оператор p1 := p2; является недопустимым. Для того, чтобы обойти эту трудность, могут быть использованы нетипизированные указатели. Нетипизированные указатели не связаны с каким-либо определенным типом данных и в то же время совместимы с типизированными указателями любого типа. Переменные − нетипизированные указатели − имеют стандартный тип pointer. Описание переменной − нетипизированного указателя: var <имя переменной>: pointer; var p0: pointer; Вследствие совместимости нетипизированных указателей с типизированными указателями любого типа допустимы следующие операторы: p0 := p1; p2 := p0; в результате значением указателя p2 становится адрес − значение указателя p1. Введение подобных сложностей оправдывается повышением надежности программы. Адрес ячейки памяти в операционной системе MS-DOS состоит из сегмента и смещения. Вся область оперативной памяти разделена на участки длиною 64 Кбайт (сегменты). Смещение показывает, на какое количество байт от начала сегмента смещена ячейка памяти. Для указания сегмента требуется 1
5
слово (2 байта), и также 1 слово (2 байта) необходимо для указания сегмента. Поэтому указатель любого типа имеет длину 4 байта (2 байта для хранения сегмента и 2 байта для хранения смещения). Указателю любого типа нельзя присвоить значение вещественного или целого выражения. Подобным образом, переменной целого или вещественного типа нельзя присвоить в качестве значения адрес динамической памяти (значение некоторого указателя). Над адресом нельзя производить математические операции, например, возводить в квадрат. В языке Turbo Pascal имеются стандартные переменные-указатели, которые определяют границы динамической памяти, иначе называемой кучей. heaporg heapend heapptr
переменная-указатель на нижнюю границу динамической памяти (кучи); переменная-указатель на верхнюю границу динамической памяти (кучи); переменная-указатель на текущую границу незанятой динамической памяти (кучи).
6
Стандартные процедуры для работы с типизированными указателями: new (<переменная - типизированный указатель>) выделяет память для хранения значения переменного данного типа. В результате выполнения процедуры переменная типа указатель приобретает в качестве значения адрес, начиная с которого можно разместить данные, иначе говоря, значение, которое до обращения к процедуре new имел указатель на текущую границу незанятой динамической памяти heapptr. В то же время указатель heapptr увеличивает свое значение на то количество байт, которое необходимо для размещения в памяти данных. Например, в результате выполнения процедуры new(p1) указатель heapptr увеличит свое значение на 2 байта, т. к. именно 2 байта необходимы для хранения в памяти переменной типа integer, с которой связан указатель p1. В результате выполнения процедуры new(p2) указатель heapptr увеличит свое значение на 6 байт (6 байт − длина переменной типа real, с которой связан указатель p2). За одно обращение к процедуре new можно выделить не более 65521 байт динамической памяти. Если отсутствует свободная область памяти требуемого размера, возникает ошибка периода исполнения. dispose (<переменная - типизированный указатель>) возвращает (освобождает) ту область памяти, которая ранее была выделена для хранения данных с помощью процедуры new. При этом значение переменной типа указатель не изменяется. Однако повторное применение процедуры dispose по отношению к уже освобожденному участку памяти вызовет ошибку периода исполнения. При многократном употреблении в программе процедур new и dispose в динамической памяти появляются "дырки" (незанятые области). При очередном обращении к процедуре new отыскивается наименьший свободный участок динамической памяти, в котором можно разместить данные. Переменной типа указатель присваивается адрес начала найденного участка, а сам участок или его часть нужной длины помечается как занятая область динамической памяти. Стандартные процедуры для работы с нетипизированными указателями: getmem (<переменная - нетипизированный указатель>, <длина>) выделяет область памяти указанной длины, но не более 65521 байт за одно обращение к процедуре. Если отсутствует свободная область памяти требуемого размера, возникает ошибка периода исполнения. freemem (<переменная - нетипизированный указатель>, <длина>)
7
освобождает область памяти указанной длины, которая ранее была выделена для хранения данных с помощью процедуры getmem. Повторное применение процедуры freemem по отношению к уже освобожденному участку памяти вызовет ошибку периода исполнения. Стандартные процедуры для работы с указателями любого типа: mark (<переменная-указатель>) переменной типа указатель присваивается текущее значение указателя heapptr, однако область памяти для хранения данных не выделяется. (Область памяти для хранения данных выделяется только процедурой new). Таким образом, можно отметить нижнюю границу области памяти, которая впоследствии может быть освобождена с помощью процедуры release. release (<переменная-указатель>) освобождает область динамической памяти, начиная с адреса, который имеет своим значением переменная типа указатель (это значение переменная должна была получить раньше в результате выполнения процедуры mark) до верхней границы динамической памяти. Совместное использование процедур dispose и release в одной программе не рекомендуется. Стандартные функции для работы с указателями: addr (<имя переменной, процедуры или функции>) функция типа pointer. Ее значением является адрес аргумента. maxavail функция типа longint. Ее значением является длина в байтах наибольшего непрерывного участка динамической памяти. За один вызов процедуры new или getmem нельзя выделить область памяти большей длины, чем значение функции maxavail. memavail функция типа longint. Ее значением является общая длина в байтах свободной области динамической памяти. ofs (<выражение любого типа, имя процедуры или функции>) функция типа word. Ее значением является смещение адреса аргумента. prt (<сегмент>, <смещение>) функция типа pointer. Определяет адрес по указанным сегменту и смещению. Аргументы функции должны быть выражениями типа word.
8
seg (<выражение любого типа, имя процедуры или функции>) функция типа word. Ее значением является сегмент адреса аргумента. sizeof (<имя переменной, функции или типа данных>) функция типа word. Ее значением является длина в байтах внутреннего представления аргумента. Для того, чтобы сослаться на данные, размещенные в динамической памяти, нужно вслед за именем переменной-указателя поставить значок "^". Например, чтобы разместить целое число 4 по адресу, который имеет своим значением указатель p1, мы должны написать: p1^ := 4; чтобы разместить действительное число 3.21 по адресу, который имеет своим значением указатель p2, мы должны написать: p2^ := 3.21; Сформулируем правило: Переменная типа указатель имеет своим значением адрес динамической памяти, по которому размещается переменная определенного типа (которому соответствует тип указателя). Если за именем переменной типа указатель следует значок "^", имеется в виду не адрес динамической памяти (значение переменной), а данные, которые размещаются по этому адресу. Указатели часто используются для размещения в динамической памяти структур данных. Простым примером такой структуры данных являются списки. Список состоит из элементов типа запись, одним из полей которой является указатель на следующий элемент списка. Указатель последнего элемента списка имеет своим значением nil (ничто), т. е. ни на что не указывает. В качестве примера использования указателей рассмотрим небольшую программу, которая размещает в динамической памяти данные − целые числа. Данные образуют структуру − связанный список. Каждый элемент списка имеет тип element, указатель на элемент списка имеет тип ElementPointer. Обратите внимание, что при объявлении типа ElementPointer мы сослались на тип element, который не был предварительно объявлен в программе. Для указателей сделано исключение из правила, в соответствие с которым каждый идентификатор, в то числе и имя типа, должен быть описан до его использования в программе. Именно это исключение и позволяет размещать в динамической памяти данные в виде списков. Введем переменную list, указывающую на первый элемент списка:
9
var list: ElementPointer; Наша программа будет содержать процедуру добавления в список нового элемента NewElement и процедуру вывода элементов списка на экран PrintList. Для того, чтобы несколько усложнить задачу, пусть новый элемент помещается после элемента, содержащего меньшее целое число, и перед элементом, содержащим большее или равное целое число. Program Pointers; type ElementPointer = ^Element; Element = record datum: integer; next: ElementPointer end; var list: ElementPointer; n: integer; Procedure NewElement(var l: ElementPointer; i: integer); {Процедура добавления в список нового элемента. Параметрами процедуры являются указатель на первый элемент списка l и целое число n, которое необходимо внести в список} var p, q, r: ElementPointer; begin {NewElement} new(q); {Выделение динамической памяти для нового элемента списка} q^.datum := n; {В поле datum очередного элемента списка сохраняется целое число n} if l = nil then begin l := q; q^.next := nil {Список был пуст. Указатель на его первый элемент "ни на что
10
не указывал". Теперь этот указатель указывает на добавленный элемент} end else if l^.datum > n then begin {Первый элемент списка содержит число, превышающее n. Новый элемент, содержащий число n в поле datum, помещается в начало списка} q^.next := l; l := q end else begin p := l; {Перемещаясь по списку, находим элемент, который в поле datum содержит число, превышающее n} while p^.datum <= n do begin r := p; {Запоминаем указатель на предшествующий элемент} p := p^.next {Переходим к следующему элементу} end; {Теперь указатель p указывает на найденный элемент} {Помещаем новый элемент перед элементом, который в поле datum содержит число, превышающее n} r^.next := q; q^.next := p end end; {NewElement}
11
Procedure PrintList(l: ElementPointer); {Процедура последовательно выводит на экран элементы списка. Параметром процедуры является указатель на первый элемент списка l} begin {PrintList} if l = nil then begin writeln; writeln(' Конец списка') {Следующего элемента списка не существует. Указатель l "ни на что не указывает"} end else begin write(l^.datum:5); {Вывод на экран очередного элемента списка - целого числа, содержащегося в поле datum записи l} PrintList(l^.next) {Рекурсивный вызов процедуры PrintList. Параметром вызова является указатель на следующий элемент списка, содержащийся в поле next записи l} end end; {PrintList} begin {Program} list := nil; {При начале работы программы список пуст. Указатель на первый элемент списка list имеет значение nil, т. е. "ни на что не указывает"} write('Последовательно вводите '); writeln('элементы списка.'); writeln('Для окончания ввода введите 0'); readln(n); while n <> 0 do begin NewElement(list, n);
12
{Добавление
нового
элемента} readln(n) end; PrintList(list) {Вывод на экран элементов списка} end. СТРОКИ В языке Turbo Pascal есть специальный строковый тип данных − стандартный тип string. Описание строкового типа: type <имя типа> = string[<максимальное число символов в строке>]; <максимальное число символов в строке> должно задаваться любой константой порядкового типа, значение которой не превосходит 255. Если число символов в строке не указано, оно принимается максимально возможным, равным 255. Примеры: type TextString = string[80]; {Строка текста - последовательность из 80 символов} WordString = string[10]; {Слово - последовательность из 10 символов} Альтернативно, переменную типа string можно объявлять в программе без предварительного описания самого типа: Описание переменной строкового типа: var <имя переменной>: string[<максимальное число символов в строке>]; var st, st1: string[20];
13
Тип string[n] (строка) в языке Turbo Pascal во многом аналогичен типу array [0..n] of char, т. е. одномерному массиву символов (n − максимальное количество символов в строке, некоторая константа). В отличие от обычного массива, однако, количество символов в строке может меняться от 0 до n. К каждому символу в строке можно обращаться так же, как к элементу массива, например, if st[5] = 'a' then ... Первый байт в строке имеет индекс 0 и содержит текущую длину строки. При выполнении над строкой различных операций длина строки может изменяться. Операции над строками в языке Turbo Pascal: + сцепление двух строк. Например, st := 'a' + 'b'; {Строка st содержит "ab"} st := st + 'c'; {Строка st содержит "abc"} Операции сравнения: = равно; <> не равно; < меньше; > больше; <= меньше или равно; >= больше или равно При сравнении двух строк символы обеих строк сравниваются попарно друг с другом таким образом, что первый символ первой строки сравнивается с первым символом второй строки, второй символ первой строки сравнивается со вторым символом второй строки и т. д. Если одна строка короче другой, недостающие символы заменяются нулями. Фактически сравниваются коды символов, поэтому при сравнении строк нужно иметь в виду таблицу кодов символов. Например, цифры '0'..'9' имеют коды 048..057, большие буквы латинского алфавита 'A'..'Z' имеют коды 065..090, поэтому 'A' < 'D'; 'AB' < 'ABC'; 'A' > '1'; 'ABD' > 'ABC'.
14
Стандартные
процедуры
для работы со строками:
delete (<строка>, <номер первого символа>, <число символов>) удаление из указанной строки заданного числа символов, начиная с символа с указанным номером. Например, st := '12345'; {Строка st содержит 12345} delete(st, 2, 3); {Строка st содержит 15} insert (<подстрока>, <строка>, <номер первого символа>) вставка указанной подстроки в заданную строку, начиная с символа с указанным номером. Например, st1 := '345'; {Строка st1 содержит 345} insert('-', st1, 2); {Строка st1 содержит 3-45} str (<вещественное или целое число>: <общее количество символов>: <число символов после запятой>, <строка>) преобразование вещественного или целого числа в строку символов, подобно тому, как это делает стандартная процедура writeln. Формат представления чисел, может быть определен программистом аналогично тому, как это можно сделать при выводе данных на экран. Например, при выводе вещественных чисел можно указать число цифр после запятой и полное число десятичных знаков, включая знак числа и десятичную точку. st := '12345'; {Строка st содержит 12345} str(pi:5:2, st); {Строка st содержит 3.14}
15
val (<строка>, <вещественная или целая переменная>, <код выполнения преобразования>) преобразование строки символов в вещественное или целое число, которое становится значением указанной вещественной или целой переменной. Если преобразование прошло успешно, код выполнения преобразования содержит 0, в противном случае он содержит номер позиции в указанной строке, где обнаружен символ, не соответствующий формату числа. В последнем случае значение указанной переменной не изменяется. В строке допускаются ведущие пробелы (находящиеся в начале строки), в то время как ведомые пробелы (находящиеся в конце строки) не допускаются. Например, val(' 3.1415', x, code); {Переменная x получает значение 3.1415, а параметр code - 0} val('3.1415 ', x, code); {Значение переменной x не изменяется, а параметр code получает значение 7 - номер позиции первого пробела после записи числа 3.1415} val('3,1415', x, code); {Значение переменной x не изменяется, а параметр code получает значение 2 - номер позиции, в которой вместо точки стоит запятая в записи числа 3.1415} Стандартные функции для работы со строками: concat (<строка 1>, <строка 2>, ... <строка N>) функция типа string, ее значением является строка, которая представляет собой сцепление указанных строк. Например, st := concat('12', '345'); {Строка st содержит 12345}
16
copy (<строка>, <номер первого символа>, <число символов>) функция типа string, ее значением является строка, получаемая копированием из указанной строки заданного число символов, начиная с символа с указанным номером. Например, st := '12345'; {Строка st содержит 12345} st1 := copy(st, 2, 3); {Строка st1 содержит 234} length (<строка>) функция типа integer, ее значением является длина строки (число символов в строке). Например, st := '12345'; n := length(st); {n - длина строки st - равна 5} pos (<подстрока>, <строка>) функция типа integer, ее значением является номер символа (позиции), начиная с которого указанная подстрока входит в заданную строку. Если в строке указанная подстрока не найдена, функция имеет значение 0. Например, st := '12345'; n := pos('2', st); {n - позиция символа '2' в строке st - равна 2} upcase (<символ>) функция типа char, заменяет строчные латинские буквы на заглавные. Ее аргументом должна быть строчная буква латинского алфавита, ее значением является соответствующая заглавная буква. Если в качестве аргумента функции upcase указан любой другой символ (в том числе строчная буква русского алфавита), значением функции является тот же символ без изменения. Если при обращении к некоторой процедуре или функции необходимо использовать переменную типа string, этот тип, так же, как и в случае массива, должен быть описан заранее. Иными словами, объявление процедуры Procedure p1 (s: string[10]); является недопустимым. Правильным в данном случае будет Procedure p1 (s: WordString); (см. выше описание типа WordString).
17
В качестве примера рассмотрим программу, которая создает текстовой файл (напомним, что в языке Turbo Pascal текстовой файл рассматривается как совокупность строк). После создания файла программа предоставляет пользователю возможность корректировать файл − заменять одни последовательности символов на другие, задаваемые пользователем, в частности, заменять целые слова. Предполагается, что файл состоит из строк, каждая из которых содержит не более 60 символов. Program Strings; var f: text; name: string[8]; a: 0..1; Procedure CreateFile; {Процедура создания файла и ввода в него необходимой информации} var s: string[60]; begin {CreateFile} write('Введите имя файла '); write('(не более 8 символов): '); readln(name); writeln; assign(f, name + '.dat'); {Имя файла получает расширение .dat} rewrite(f); {Открываем файл для записи} write('Вводите текст в файл, '); write('последовательно набирая '); writeln('на клавиатуре строки.'); write('Каждая строка должна содержать '); writeln('не более 60 символов.'); write('Ввод каждой строки завершайте '); writeln('нажатием клавиши Enter.'); write('Для окончания ввода текста '); writeln('нажмите клавиши Ctrl-Z и Enter.'); writeln; while not eof do begin readln(s); {Ввод очередной строки s}
18
writeln(f, s) {Запись очередной строки s в файл} end; writeln; close(f) end; {CreateFile} Procedure PrintText; {Процедура вывода содержащегося в файле текста на экран} var s: string[60]; begin {PrintText} assign(f, name + '.dat'); reset(f); {Открываем файл для чтения} write('Файл ', name, '.dat содержит '); writeln('следующий текст:'); writeln; while not eof(f) do begin readln(f, s); {Из файла считывается очередная строка s} writeln(s) {Строка s выводится на экран} end; writeln; close(f) end; {PrintText} Procedure Replacement; {Процедура корректировки текста замена неправильно введенных последовательностей символов} var f1: text; s, s1, s2: string[60]; i: byte; a1: 0..1; begin {Replacement}
19
write('Введите последовательность '); writeln('символов,'); write('которую необходимо найти в файле '); writeln(name, '.dat и заменить:'); readln(s1); {Строка s1 содержит текст, который следует заменить} writeln; write('Введите новую '); writeln('последовательность символов,'); write('которую необходимо '); write('поместить на место '); writeln('неправильной последовательности:'); readln(s2); {Строка s2 содержит новый текст} writeln; write('Вы хотите, чтобы заменялись '); writeln('только целые слова'); write('(т. е. указанные Вами '); write('последовательности, '); writeln('сопровождаемые пробелами '); write('в начале и в конце)? '); writeln('1 - да, 0 - нет: '); readln(a1); writeln; if a1 = 1 then begin s1 := ' ' + s1 + ' '; s2 := ' ' + s2 + ' ' end; rename(f, name + '.bak'); reset(f); {Старый файл переименовываем, изменяя его расширение. Он имел расширение .dat, теперь файл будет иметь расширение .bak. После переименования открываем его для чтения} assign(f1, name + '.dat'); rewrite(f1); {Открываем новый файл с расширением .dat для записи исправленного текста} while not eof(f)
20
do begin readln(f, s); {Считываем очередную строку s из старого файла} i := pos(s1, s); {Определяем позицию в этой строке первого символа подстроки s1, которую нужно заменить} while i <> 0 do begin delete(s, i, length(s1)); {Удаляем подстроку s1 из строки s} insert(s2, s, i); {Вставляем новую подстроку s2 в строку s} i := pos(s1, s) end; writeln(f1, s) {Записываем исправленную строку s в новый файл} end; close(f); erase(f); {Удаляем старый файл с расширением .bat, который больше не нужен} close(f1) end; {Replacement} begin {Program} CreateFile; PrintText; repeat write('Вы хотите отредактировать '); write('текст? 1 - да, 0 - нет: '); readln(a); writeln; if a = 1 then begin Replacement; PrintText
21
end; until a = 0; writeln end. {Program} МНОЖЕСТВА Множество − это набор однотипных логически связанных между собой объектов. Характер связей между объектами подразумевается программистом, но никак не контролируется языком Turbo Pascal. В отличие от массивов и записей, которые содержат постоянное число компонентов, количество элементов, входящих в множество, непостоянно. Количество элементов может меняться от 0 до 256. Множество, не содержащее элементов, называется пустым. Порядок следования элементов в множестве не имеет значения. Два множества считаются эквивалентными, если они содержат одинаковые элементы. Если все элементы одного множества входят также в другое множество, говорят, что первое множество включено во второе. Принимается, что пустое множество включено в любое другое. Для описания множества необходимо указать тип его элементов. Элементы могут быть любого порядкового типа, за исключением типов word, integer, longint. Описание множества: type <имя типа> = set of <тип элементов>; type symbol = set of 'A'..'F'; digit = set of 0..9; var s1, s2, s3: symbol; s4, s5, s6: digit; Альтернативно, переменную типа set можно объявлять в программе без предварительного описания самого типа: var <имя переменной>: set of <тип элементов>; Множество задается либо заданием списка его элементов через запятую в квадратных скобках, либо указанием типа-диапазона, к которому принадлежат элементы множества. Примеры: s1 := ['a', 'b', 'c']; s2 := ['c', 'b', 'a'];
22
s3 s4 s5 s6
:= := := :=
['b', 'c']; [0..3, 6]; [4, 5]; [3..9];
Операции над множествами в языке Turbo Pascal: * +
-
= <>
<= >=
in
пересечение множеств. Результат содержит элементы, которые входят в оба множества. Например, s4 * s6 содержит [3, 6]; s4 * s5 − пустое множество. объединение множеств. Результат содержит элементы первого множества и элементы второго множества, которые не вошли в первое. Например, s4 + s5 содержит [0, 1, 2, 3, 4, 5, 6]; s5 + s6 содержит [3, 4, 5, 6, 7, 8, 9]. разность множеств. Результат содержит те элементы первого множества, которые не принадлежат второму. Например, s6 s5 содержит [3, 6, 7, 8, 9]; s4 - s5 содержит [0, 1, 2, 3, 6]. проверка эквивалентности множеств. Результат имеет значение true, если множества эквивалентны. Например, s1 эквивалентно s2: s1 = s2. проверка неэквивалентности множеств. Результат имеет значение true, если множества неэквивалентны. Например, s3 неэквивалентно s2: s3 <> s2. проверка включения множеств. Результат имеет значение true, если первое множество включено во второе. Например, s3 включено в s2: s3 <= s2. проверка включения множеств. Результат имеет значение true, если второе множество включено во второе. Например, s3 включено в s2: s2 >= s3. проверка принадлежности элемента данному множеству. Результат имеет значение true, если значение указанного выражения принадлежит данному множеству. Например, 3 принадлежит s6: 3 in s6 = true; 4 не принадлежит s1: 2 * 2 in s1 = false.
23
Процедуры для работы с множествами: include (<множество>, <элемент>) включение в указанное множество нового элемента. exclude (<множество>, <элемент>) исключение указанного элемента из множества. В качестве примера работы с множествами рассмотрим следующую небольшую программу. Задано множество натуральных чисел от 1 до n (n не может превосходить 255, так как в любом множестве в языке Turbo Pascal не может содержаться более 256 элементов, считая с 0). Из этого множества необходимо получить новое множество, содержащее только те из натуральных чисел от 1 до n, которые являются квадратами натуральных чисел. Program Sets; var n, i: integer; s: set of 1..255; begin write('Задайте число элементов множества '); writeln(N <= 255): '); readln(n); s := [1..n]; {Задаем множество, состоящее из первых n натуральных чисел} for i := 1 to n do begin {Для каждого элемента i исходного множества s проверяем, является ли он квадратом другого натурального числа. Если элемент i не является квадратом другого числа, он исключается из исходного множества} if trunc(sqrt(i)) <> sqrt(i) then exclude(s, i); {Если элемент i является квадратом другого числа, он по-прежнему содержится в множестве s. Выводим его на экран}
24
if i in s then write(i:5) end; {После выполнения цикла множество s содержит только те натуральные числа, которые являются квадратами других чисел} writeln end. ЛИТЕРАТУРА 1. В. Э. Фигурнов, IBM PC для пользователя. Краткий курс, М., 1999. 2. В. В. Фаронов, Turbo Pascal 7.0. Начальный курс, М., Изд-во "Нолидж", 1998. 3. Л. А. Бугаев, Г. М. Чечин, К. Н. Жучков, Методические указания к проведению практических занятий по курсу "Информатика". Вып. 1.1. Необходимые определения и команды для работы на компьютере. Элементы языка Pascal (часть I), Ростов-на-Дону, УПЛ РГУ, 1998. 4. Л. А. Бугаев, Г. М. Чечин, К. Н. Жучков, Методические указания к проведению практических занятий по курсу "Информатика". Вып. 1.4.Задачи для самостоятельного решения на компьютере, Ростов-на-Дону, УПЛ РГУ, 1998. 5. Шестакова Т. П. Методические указания по курсу "Программирование и вычислительная физика". Часть I. Основные конструкции языка Turbo Pascal. Простейшие типы данных, Ростов-на-Дону, УПЛ РГУ, 2003. 6. Шестакова Т. П. Методические указания по курсу "Программирование и вычислительная физика". Часть II. Процедуры и функции в языке Turbo Pascal. Перечисляемые типы данных, тип-диапазон и оператор case. Массивы, Ростов-на-Дону, УПЛ РГУ, 2003. 7. Шестакова Т. П. Методические указания по курсу "Программирование и вычислительная физика". Часть III. Типы данных языка Turbo Pascal. Файлы. Записи, Ростов-на-Дону, УПЛ РГУ, 2003.