информатика. Структурированные типы. Массивы. Записи. Множества. Структурированные типы
Скачать 37.07 Kb.
|
Структурированные типы. Массивы. Записи. Множества. Структурированные типы. К структурированным типам относятся: массивы, записи, множества, файлы. Их объединяет то, что переменные данных типов содержат в себе информацию в виде своеобразных структур. Файлы, в свою очередь, бывают типизированные, текстовые и нетипизированные. Они заслуживают отдельного параграфа и их мы рассмотрим позже. Массивы. Переменная типа массив может содержать в себе не одно, а несколько значений какого-либо типа, в том числе это может быть и структурированный тип. Например, мы имеем ряд целых чисел: 4,3,45,55. Что бы хранить этот ряд чисел мы можем создать 4 переменные: i1,i2,i3,i4. А теперь представьте себе, что этот ряд содержит не 4, а 40 целых чисел. Будет достаточно «муторно» набирать вручную 40 переменных. Что бы облегчить данную задачу существуют массивы. В данном случае мы можем создать одну переменную, которая будет содержать в себе 40 значений целых чисел. Делается это следующим образом: var M:array [1..40] of integer; После имени переменной, после двоеточия, пишется слово array затем в квадратных скобках указывается диапазон значений индексов, пишется слово of и указывается тип значений, которые будут содержаться в массиве. Индексы необходимы для того, что бы можно было обращаться к тому или иному значению, т.е. у каждого значения есть свой индекс. Индексами могут быть только переменные порядковых типов. Что бы обратиться к какому либо значению в тексте программы необходимо после имени массива в квадратных скобках указать индекс, например в следующем примере мы присваиваем четвёртому элементу массива значение 45: M[4]:=45; Наглядно продемонстрировать структуру массива может следующая таблица:
Так же стоит отметить, что в отличии от просто переменных, значения в массиве удобно обрабатывать благодаря индексам, с помощью цикла for to do. Если у вас в программе будут существовать несколько одинаковых массивов, то (так же как и с порядковыми типами), можно вначале объявить тип массива, а потом объявить переменные этого типа. Для создания своего типа в разделе описания типов, после слова Type, пишется имя типа, затем знак равно затем слово array, далее в квадратных скобках указывается диапазон значений, слово of и тип значений. Например: Type massiv = array [1..40] of integer; var M:massiv; Далее пример программы с массивами: Type massiv = array [1..40] of integer; var M:massiv; S:array [1..40] of char; i:integer; begin //Заполняем массивы for i:=1 to 40 do begin M[i]:=random(1000); S[i]:=chr(random(32,255)); end; //Выводим массивы на экран for i:=1 to 40 do write(M[i]:4,' '); writeln; for i:=1 to 40 do write(S[i]); end. _________________________________________________________________________ 213 523 258 763 821 355 774 750 37 773 300 271 512 456 623 939 743 438 261 565 390 34 362 9 235 778 646 590 938 707 694 586 823 121 561 5 405 912 464 796 NQAOЛбя[щcЏC%бµэfsЂэјb№Р/#(їqTйBr†t§Р§ъШ Обратите внимание, что переменная i в цикле for to do одновременно является счётчиком цикла и индексом массива. В этом и заключается удобство обработки массивов по сравнению с просто переменными. Так же стоит заметить, что в данной программе была использована системная функция random, которая была рассмотрена в предыдущем параграфе. Ей удобно заполнять массив, что бы ни придумывать значения самому. Очень часто заполнение массивов случайными числами необходимо для проверки работоспособности программы. Ещё стоит отметить следующий нюанс, если вы укажете индекс, выходящий за рамки указанного диапазона, то это приведёт к ошибке во время выполнения программы. При компиляции данная ошибка не будет выведена. Поэтому будьте внимательны при обработке массива в цикле for to do, вы должны указать начальное и конечное значения, соответствующие указанному диапазону индексов массива. Выше было сказано, что индексами могут быть переменные любого порядкового типа. Однако есть исключение, из всех порядковых типов индексами не могут быть переменные типа LongInt, и тип-диапазон, созданный на основе типа LongInt. Далее небольшой пример: var m:array ['A'..'Z'] of integer; c:char; begin for c:='A' to 'Z' do begin m[c]:=random(500); write(m[c],' '); end; end. _________________________________________________________________________ 200 249 404 152 256 334 336 265 136 404 274 61 107 141 317 368 127 241 423 31 185 475 267 90 227 69 Все массивы, которые были приведены в примерах, называют одномерными т.к. они имеют лишь один индекс. Массивы могут быть двух, трёх и более мерными. При этом они имеют два, три и более индекса. При объявлении многомерного массива или типа массива в квадратных скобках необходимо указать через запятую не один диапазон индексов, а несколько. Пример: var m: array [1..5,1..5] of integer; i,k:integer; begin writeln(' 1 2 3 4 5'); writeln; for i:=1 to 5 do begin write(i,' '); for k:=1 to 5 do begin m[i,k]:=random(100); write(m[i,k]:4); end; writeln; end; end. _____________________________________ 1 2 3 4 5 1 22 41 68 8 40 2 91 57 2 17 92 3 41 38 46 91 55 4 17 82 92 93 80 5 17 94 36 49 9 В данном примере был объявлен двухмерный массив в котором имеется два индекса. Оба индекса имеют диапазон от одного до пяти. Такой массив можно сравнить с матрицей размера 5x5, что наглядно видно из результата работы программы. Т.е. любой двумерный массив можно воспринимать как двухмерную матрицу со столбцами и строками. Первый диапазон индексов в данном примере является строками, и формируется переменной i, а второй диапазон индексов является столбцами и формируется переменной k. В 8 параграфе была приведена программа SortirovkaBookv. Она располагала по алфавиту четыре буквы. С помощью массива данная задача может быть решена по-другому: Var c: array [1..4] of char; temp:char; i,k:byte; begin c[1]:='к'; c[2]:='ф'; c[3]:='в'; c[4]:='а'; for k:=1 to 3 do for i:=1 to 3 do begin if c[i+1] begin temp:=c[i+1]; c[i+1]:=c[i]; c[i]:=temp; end; end; for i:=1 to 4 do write(c[i]:2); end. __________________________________ а в к ф Таким образом мы можем обработать массив символов любого размера, не меняя количества строчек кода, тогда как в программе из предыдущего параграфа пришлось бы добавлять количество строчек пропорционально количеству символов. Преимущество использования массивов налицо. Плюс ко всему сказанному следует сказать, для того что бы элементам одного массива присвоить значения элементов другого массива не обязательно использовать цикл for to do, для этого можно использовать оператор присваивания, при этом размерность массивов должна быть одинаковая: var m1,m2: array [1..5] of integer; begin ......... m1:=m2; ......... end. Так же стоит заметить, что арифметические операции и операции сравнения с массивами неприменимы. Записи. Рассмотрим такую задачу. Необходимо написать программу учёта овощей на базе. С учётом того, что мы знаем, мы можем решить её следующим образом. Создаём два массива. Первый будет – массив символов, где каждый символ будет обозначать свой овощ. Второй будет массив целых чисел, где будет содержаться количество овощей на базе. Индексы первого массива будут соответствовать индексам второго массива. Например, если в первом массиве картошке соответствует индекс 2, то во втором массиве элемент с индексом 2 будет содержать количество картошки на базе. Приведём пример такой программы, в которой реализован поиск овоща по его символу и вывод его на экран: Var Ovoshi: array [1..5] of char;//Массив имён овощей Kolichestvo: array [1..5] of word;//Массив количеств овощей c:char;//Переменная для ввода нужного овоща i:word;//Переменная счётчик для индексов массивов begin Ovoshi[1]:='O'; Kolichestvo[1]:=30; //Огурцы Ovoshi[2]:='K'; Kolichestvo[2]:=156; //Картошка Ovoshi[3]:='P'; Kolichestvo[3]:=353; //Помидоры Ovoshi[4]:='M'; Kolichestvo[4]:=34; //Морковь Ovoshi[5]:='L'; Kolichestvo[5]:=45; //Лук c:='M';//Ввод нужного овощя //Поиск нужного овоща в массиве For i:=1 to 5 do if Ovoshi[i]=c then break; //Выод найденного овоща на экран Write('Овощей ',Ovoshi[i],' на базе находится ',Kolichestvo[i],'.'); end. _________________________________________________________________________ Овощей M на базе находится 34. В принципе здесь всё нормально, для такой задачи такой подход вполне приемлем. А теперь представьте, что нам необходимо учитывать ещё следующие данные: сорт, дата поступления, цена. В этом случае нам понадобиться уже пять массивов. В принципе можно пойти тем же путём и решить задачу с пятью массивами. Однако в Pascal есть для этого тип данных запись. Переменная типа запись может содержать в себе одновременно несколько данных различных типов. Например, создадим переменную Ovosh типа запись, которая будет содержать в себе следующие данные: название, сорт, дата поступления, цена, количество: Var Ovosh: record name:char; sort:char; data:byte; cena:byte; kol:word end; Что бы создать переменную типа запись необходимо после имени переменной и двоеточия написать слово record, затем перечислить названия данных с указанием типов этих данных и написать слово end (которое закрывает список данных). Эти данные называют полями записи. В программе доступ к этим полям осуществляется следующим образом: пишется имя переменной, затем ставится точка и пишется название поля. Между названием переменной, точкой и именем поля можно поставить пробел, ошибки не будет, однако нагляднее, если пробела нет. Следующий пример – продолжение предыдущего: begin ovosh.name:='K'; ovosh.sort:='1'; ovosh.data:=352; ovosh.cena:=9; ovosh.kol:=354; Writeln('Овощ сорт дата поступления цена количество на базе'); Writeln(ovosh.name:4,ovosh.sort:6,ovosh.data:18, ovosh.cena:6,ovosh.kol:20); end. _________________________________________________________________________ Овощ сорт дата поступления цена количество на базе K 1 96 9 354 Теперь, умея пользоваться записями, можем создать массив записей. Для этого вначале объявим тип, а затем массив значений этого типа: Type Ovosh = record name:char; sort:char; data:byte; cena:byte; kol:word end; Var Ovoshi: array [1..5] of Ovosh; begin ovoshi[1].name:='K'; ovoshi[1].sort:='1'; ovoshi[1].data:=352; ovoshi[1].cena:=9; ovoshi[1].kol:=354; Writeln('Овощ сорт дата поступления цена количество на базе'); Writeln(ovoshi[1].name:4,ovoshi[1].sort:6,ovoshi[1].data:18, ovoshi[1].cena:6,ovoshi[1].kol:20); end. _________________________________________________________________________ Овощ сорт дата поступления цена количество на базе K 1 96 9 354 Как видите, в случае с большим количеством информации, данный подход предпочтительнее. Стоит сделать небольшое отступление и сказать про переменную Ovoshi: такая структура информации называется базой данных. Причём каждый элемент массива называется записью, а name, sort, data, cena, kol – называются полями записи. При постановке задачи, данная задача может звучать следующим образом: «Необходимо создать базу данных овощей на складе». Вообще тема баз данных достаточно обширная и должна занимать целую книгу. Здесь я сделал отступление для того, что бы вы имели представление, что это такое. Поле записи может быть любого типа. Если поле записи является типом запись, то доступ к полям этой записи осуществляется с помощью ещё одной точки. Например: Type Ovosh = record name:char; sort:char end; Cena = record rubl:word; kop:byte end; Var Kartofel: record P1:Ovosh; P2:Cena; Kol:Word end; Begin Kartofel.P1.name:='K'; Kartofel.P1.sort:='1'; Kartofel.P2.rubl:=9; Kartofel.P2.kop:=52; Kartofel.kol:=542; end. В большой программе этих точек может получиться огромное количество. Что бы сократить запись кода существует оператор присоединения With do. Далее на примере предыдущей программы будут продемонстрированы различные варианты использования этого оператора: Begin With Kartofel do P1.name:='K'; With Kartofel.P1 do sort:='1'; With Kartofel.P2 do begin rubl:=9; kop:=52; end; With Kartofel do kol:=542; end. Множества. Множество в Pascal – это набор беспорядочных данных любого типа (который называется базовым). Всего переменная типа множества может содержать в себе 256 элементов, причём никаких порядковых номеров у этих элементов нет. Для того, что бы объявить переменную типа множества существует словосочетание set of, после которого следует название базового типа: var d:set of integer; Или: Type m = set of integer var d:m; Для того, что бы «заполнить» множество используется оператор присваивания, причём элементы множества указываются через запятую в квадратных скобках. При этом возможно использование типа диапазон, т.е. указать начальное и конечное значения через две точки, тогда все значения, входящие в этот диапазон, будут принадлежать множеству. Пример: d:=[5,2,4..9]; Множество можно вывести на экран с помощью процедуры Write или Writeln: begin d:=[5,2,4..9]; write(d); end. ________________ [2,4,5,6,7,8,9] Обратите внимание, что при выводе на экран элементы располагаются в порядке возрастания, и что повторяющихся элементов нет. Множество можно объявить как константу: Const YN:set of char = ['Y','y','N','n']; Для работы с множествами существуют следующие операции: Операция сложения (объединение множеств). В результате сложения множеств получается новое множество, в котором присутствуют все элементы всех складываемых множеств, но в единственном экземпляре: var M,m1,m2:set of integer; begin m1:=[5,2]; m2:=[5,6..8]; M:=m1+m2+[1]; write(M); end. _________________________ [1,2,5,6,7,8] Далее пример как можно с помощью операции сложения заполнить множество из 10 элементов случайными числами: var M:set of integer; i:byte; begin for i:=1 to 10 do M:=M+[random(100)]; write(M); end. ______________________________ [2,11,25,35,44,45,65,72,84,94] Операция вычитания (разность множества). В результате вычитания множеств получается новое множество, в котором присутствуют все элементы первого множества за исключением тех элементов, которые присутствуют во втором. Или другими словами из первого множества убираются элементы, которые есть во втором множестве. Пример: var M,m1,m2:set of integer; begin m1:=[5,2]; m2:=[5,6..8]; M:=m1-m2-[7]; write(M); end. __________________________ [2] Умножение множеств (пресечение множеств). В результате умножения двух множеств получается множество, в котором содержатся только те элементы, которые присутствуют в первом и втором множествах: var M,m1,m2:set of integer; begin m1:=[5,2]; m2:=[5,6..8]; M:=m1*m2; write(M); end. _________________________ [5] Сравнение множеств. Множества можно сравнивать друг с другом. Множества считаются равными, если все элементы одного множества присутствуют в другом. Для сравнения используются знак равно (=) и знак не равно (<>): var m1,m2:set of integer; begin m1:=[5,2]; m2:=[5,2]; if m1 = m2 then Write('Множества равны друг другу') else Write('Множестав не равны друг другу.'); end. _____________________________________________________ Множества равны друг другу Проверка включения. Одно множество считается входящим в другое, если все его элементы содержатся в другом. Проверка включения проводится знаками больше либо равно (<=) или меньше либо равно (>=). Пример: var m1,m2:set of integer; begin m1:=[5,2];writeln('m1 = ',m1); m2:=[5,2,6..10];writeln('m2 = ',m2); if m1 <= m2 then Writeln('Множества m1 входит в множество m2') else Writeln('Множества m1 не входит в множество m2'); if m1 >= m2 then Writeln('Множества m2 входит в множество m1') else Writeln('Множества m2 не входит в множество m1'); end. ________________________________________________________________ m1 = [2,5] m2 = [2,5,6,7,8,9,10] Множества m1 входит в множество m2 Множества m2 не входит в множество m1 Проверка принадлежности. Для того, что бы проверить принадлежит ли переменная или константа множеству существует логическая операция in. С помощью данной операции удобно производить контроль вводимых данных, например: Const Y:set of char = ['Y','y']; var c:char; begin While not (c in Y) do begin Writeln('Для выхода из программы нажмите Y'); readln(c); end; end. __________________________________________________ Для выхода из программы нажмите Y u Для выхода из программы нажмите Y y В данном параграфе мы рассмотрели следующие структурированные типы данных: массивы, записи, множества. Научились ими пользоваться и узнали в каких случаях можно их использовать. Задачи. 1. Перерешать 4-ую задачу из 9 параграфа используя массивы. Соответственно создать два массива значений и . Вначале заполнить их, а затем вывести их на экран. Значения этих массивов вывести в виде 5 столбиков по 10 строчек в каждом. Соответственно порядок вывода будет сверху вниз. 2. Перерешать предыдущую задачу с помощью одного массива используя тип запись. 3. Пользователь вводит с клавиатуры символ. Необходимо вывести на экран сообщение о том, что это за символ. Это может быть буква латинского или русского алфавита, в противном случае вывести сообщение, что символ не является буквой. 4. Создать два произвольных множества целых чисел с помощью функции random. Вывести их на экран. Определить являются ли они равными. Вывести на экран элементы, которые входят в оба множества. Решение. 1. Var M,w:array [1..60] of real; r:real; i:byte; begin r:=62.83/60; For i:=1 to 60 do begin w[i]:=r*i; M[i]:=2*3202*(1+0.1143*0.065)/ ((1-w[i]/62.83)/0.065+0.065/(1-w[i]/62.83)+2*0.1143*0.065); end; Write(' w M w M w M w'); Writeln('M w M '); for i:=1 to 12 do begin write(w[i]:5:2,' ',M[i]:7:2,' '); write(w[i+12]:5:2,' ',M[i+12]:7:2,' '); write(w[i+24]:5:2,' ',M[i+24]:7:2,' '); write(w[i+36]:5:2,' ',M[i+36]:7:2,' '); write(w[i+48]:5:2,' ',M[i+48]:7:2,' '); writeln; end; end. _________________________________________________________________________ w M w M w M w M w M 1.05 424.19 13.61 531.03 26.18 708.91 38.75 1060.79 51.31 2022.49 2.09 431.43 14.66 542.40 27.23 729.20 39.79 1106.02 52.36 2173.01 3.14 438.92 15.71 554.26 28.27 750.66 40.84 1155.12 53.41 2341.02 4.19 446.68 16.75 566.65 29.32 773.40 41.89 1208.60 54.45 2526.42 5.24 454.71 17.80 579.59 30.37 797.54 42.93 1267.02 55.50 2725.78 6.28 463.04 18.85 593.14 31.42 823.20 43.98 1331.07 56.55 2928.12 7.33 471.67 19.90 607.33 32.46 850.54 45.03 1401.53 57.59 3106.33 8.38 480.63 20.94 622.21 33.51 879.72 46.08 1479.32 58.64 3200.98 9.42 489.93 21.99 637.83 34.56 910.93 47.12 1565.53 59.69 3095.63 10.47 499.60 23.04 654.25 35.60 944.38 48.17 1661.42 60.74 2603.88 11.52 509.66 24.08 671.52 36.65 980.32 49.22 1768.43 61.78 1546.67 12.57 520.13 25.13 689.72 37.70 1019.01 50.26 1888.20 62.83 0.00 2. Type TMw = record M:real; w:real end; Var Mw:array [1..60] of TMw; r:real; i:byte; begin r:=62.83/60; For i:=1 to 60 do begin Mw[i].w:=r*i; Mw[i].M:=2*3202*(1+0.1143*0.065)/ ((1-Mw[i].w/62.83)/0.065+0.065/(1-Mw[i].w/62.83)+2*0.1143*0.065); end; Write(' w M w M w M w'); Writeln(' M w M '); for i:=1 to 12 do begin write(Mw[i].w:5:2,' ',Mw[i].M:7:2,' '); write(Mw[i+12].w:5:2,' ',Mw[i+12].M:7:2,' '); write(Mw[i+24].w:5:2,' ',Mw[i+24].M:7:2,' '); write(Mw[i+36].w:5:2,' ',Mw[i+36].M:7:2,' '); write(Mw[i+48].w:5:2,' ',Mw[i+48].M:7:2,' '); writeln; end; end. Результат работы программы тот же самый. 3. Const lat:set of char = ['A'..'Z','a'..'z']; rus:set of char = ['А'..'Я','а'..'я']; Var c:char; begin Writeln('Введите символ.'); readln(c); if c in lat then writeln('Вы ввели букву латинского алфавита.'); if c in rus then writeln('Вы ввели букву русского алфавита.'); if (not(c in lat))and(not(c in rus)) then writeln('Вы ввели символ не являющийся буквой'); end. ____________________________________________________________________ Введите символ. П Вы ввели букву русского алфавита. 4. Var m1,m2,m3:set of integer; i,k:byte; begin k:=random(20); for i:=1 to k do m1:=m1+[random(-100,+100)]; k:=random(20); for i:=1 to k do m2:=m2+[random(-100,+100)]; writeln('m1'); Writeln(m1); writeln('m2'); Writeln(m2); if m1=m2 then writeln('Множества получились одинаковыми.') else writeln('Множества получились не одинаковыми.'); m3:=m1*m2; if m3<>[]then begin Writeln('В оба множества входят следующие элементы:'); writeln(m3); end else writeln('Общих элементов в множествах нет.'); end. _____________________________________________________________ m1 [-95,-87,-83,-77,-74,-71,-51,-43,-42,-32,-18,7,9,38,48,54,75,90] m2 [-87,-86,-38,-37,-23,-15,4,8,63,64,75,77,87,91] Множества получились не одинаковыми. В оба множества входят следующие элементы: [-87,75] |