Массивы в Паскале. Одномерные массивы

Билет18-19

 

Алгоритмизация задач-решение задач при помощи разных алгоритмов.

Выделяют следующие виды алгоритмов:линейный,разветляющий,циклический,комбинированный. При определений вида алгоритма пользуются ключевыми словами.

Вид алгоритма Ключевое слово структура
Алгоритм в котором есть структура следования называутся линейным Следование-это расположение действий друг за другом Количество слов нет.
Алгоритм в котором есть структура ветвления называется разветляющей. Ветвление – это выбор действия в зависимости от выполнения какого-нибудб условия. Если…то…иначе” При…(в значение если…)
Алгоритм,в котором есть структура ЦИКЛ называется циклической. Цикл-это неоднократное повторение каких либо действий. От…до. …раз Пока… Если…(в значении пока)

Алгоритмы,которые содержит несколько структур одновременно,называется комбинированной.

Следование-1-3-5-6-8-9-10-11 блок

Ветвления-4-9 блок

Цикл-7-9 блок

 

 

1.Алгоритм. Свойства алгоритма. Формы представления алгоритмов.

Алгоpитм — точное и понятное пpедписание исполнителю совеpшить последовательность действий, направленных на решение поставленной задачи.

Основные свойства алгоритмов:

1. Понятность для исполнителя

2. Дискpетность (прерывность, раздельность) — алгоpитм должен пpедставлять пpоцесс pешения задачи как последовательное выполнение пpостых (или pанее опpеделенных) шагов (этапов).

3. Опpеделенность — каждое пpавило алгоpитма должно быть четким, однозначным и не оставлять места для пpоизвола.

4. Pезультативность — это свойство состоит в том, что алгоpитм должен пpиводить к pешению задачи за конечное число шагов.

5. Массовость. Алгоpитм pешения задачи pазpабатывается в общем виде.

Формы представления алгоритмов.

• словесная (записи на естественном языке);

• графическая (изображения из графических символов);

• псевдокоды (полуформализованные описания алгоритмов на условном алгоритмическом языке;

• программная (тексты на языках программирования).

Словесный способ записи алгоритмов представляет собой описание последовательных этапов обработки данных.

Графическом представление — алгоритм изображается в виде последовательности связанных между собой функциональных блоков.

Блочные символы соединяются линиями переходов, определяющими очередность выполнения действий.

Билет21

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

Блок начала-конца алгоритма (рис. 1.1). Надпись на блоке: "начало" ("конец").

Блок ввода-вывода данных (рис. 1.2). Надпись на блоке: слово "ввод" ("вывод" или "печать") и список вводимых (выводимых) переменных.

 

Рис1 рис2

 

 

Блок решения или арифметический (рис. 1.3). Надпись на блоке: операция или группа операций.

Условный блок (рис. 1.4). Надпись на блоке: условие. В результате проверки условия осуществляется выбор одного из возможных путей (ветвей) вычислительного процесса. Если условие выполняется, то следующим выполняется этап по ветви "+", если условие не выполняется, то выполняется этап по ветви "–".

 

Рис3 рис4

 

Линей и разветлящие,цикличесеий.

Билет23

ТИПЫ ДАННЫХ

Любые данные, т.е. константы, переменные, значения функций или выражения, в Турбо Паскале характеризуются своими типами. Тип определяет множество допустимых значений, которые может тот или иной объект, а также множество допустимых операций, которые применимы к нему. Кроме того, тип определяет формат внутреннего представления данных в памяти ПК.

 

Турбо Паскаль характеризуется разветвлённой структурой типов данны

 

В Турбо Паскале предусмотрен механизм создания новых типов данных, благодаря чему общее количество типов, используемых в программе, может быть сколько угодно большим.

К простым типам относятся порядковые и вещественные типы.

Порядковые типы отличаются тем, что каждый из них имеет конечное число возможных значений. Эти значения можно определённым образом упорядочить (отсюда – название типов) и, следовательно, с каждым из них можно сопоставить некоторое целое число – порядковый номер значения.

Вещественные типы тоже имеют конечное число значений, которое определяется форматом внутреннего представления вещественного числа. Однако количество возможных значений вещественных типов настолько велико, что сопоставить с каждым из них целое число (его номер) не представляется возможным.

ПОРЯДКОВЫЕ ТИПЫ

К порядковым типам относятся целые, логический, символьный, перечисляемый и тип-диапазон.

Целые типы. Диапазон возможных значений целых типов зависит от их внутреннего представления, которое может занимать один, два или четыре байта

При использовании процедур и функций с целочисленными параметрами следует руководствоваться «вложенностью» типов, т.е. везде, где может использоваться Word, допускается использование Byte (но не наоборот), в LongInt “входит” Integer, который, в свою очередь, включает в себя ShortInt.

При дейстйствии с целыми чмслами тип результата будет соответствовать типу операндов, ф если операнды относятся к различным целым типам,- типу того операнда, который имеет максимальную мощность (максимальный диапазон значений). Возможное переполнение никак не контролируется, что может привести к недорозумениям.

Логический тип

. Значениями логического типа может быть одна из предварительно объявленных констант FALSE (ложь) или TRUE (истина).

Поскольку логический тип относится к порядковым типам, его можно использовать в операторе счётного типа.

Символьный тип. CHAR – занимает 1 байт. Значением символьного типа является множество всех символов ПК. Каждому символу присваивается целое число в диапозоне 0…255. Это число служит кодом внутреннего представления символа.

Для кодировки испоьзуется код ASCII (American Standart Code for Information Interchange – американский стандартный код для обмена информацией). Это 7-битный код, т.е. с его помощью можн озакодировать лишь 128 символов в диапозоне от 0 до 127. В то же время в 8-битном байте, отведенном для хранения символа в Турбо Паскале, можно закодировать в два раза больше символов в дапозоне от 0 до 255. Первая половина символов ПК с кодами 0…127 соответствует стандарту ASCII. Вторая половина символов с кодами 128ююю255 не ограничена жёсткими рамками стандарта и может менятся на ПК разных типов.

Символы с кодами 0…31 относятся к слжебным кодам. Если эти коды использовать в символьном тексте программы, они считаются пробелами.

Перечисляемый тип. Перечисляемый тип задаётся перечислением тех значений, которые он может получать. Каждое значение именуется некоторым идентификатором и рапологается в списке, обрамлённом круглыми скобками, напримерЖ

Type Colors = (red, white, blue);

 

Применение перечисляемых типов делает программы нагляднее

Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение списке получает порядковый номер 0, второе – 1 и т.д. максимальная мощность перечисляемого типа составляет 65536 значений, поэтому фактически перечисляемый тип задаёт некоторое подмножество целого типа WORD и может рассматриваться как компактное объявление сразу группы целочисленных констант со значениями 0,1 и т.д.

Использование перечисляемых типов повышает надёжность программы, благодаря возможности контроля тех значений, которые получают соответствующие переменные.

Тип-диапазон. Тип-диапазон есть подмножество своего базового типа, в качестве которого может выступать любой порядковый тип, кроме типа-диапазона.

Тип-диапазон задаётся границами своих значений внутри базового типа:

<мин.знач.>..<макс.знач.>

Здесь <мин.знач.> - минимальное значение типа-диапазона.

<макс.знач.> - максимальное его значение.

Type

Digit = ‘0’ ..’9’;

Dig2 = 48 .. 57;

При определении типа-диапазона нужно руководствоваться следующими правилами:

1. два символа «..» рассматриваются как один символ, поэтому между ними недопустимы пробелы.

2. левая граница диапазона не должна превышать его правую границу.

Тип-диапазон наследует все свойства базового итпа, но с ограничениями, связанными с его меньшей мощностью.

ВЕЩЕСТВЕННЫЕ ТИПЫ

В отличие от порядковых типов, значения которых всегда сопоставляются с рядом целых чисел и, следовательно, представляется в ПК абсолютно точно, значения вещественных типов определяют произвольное число лишь с некоторой конечной точностью, зависящей от внутреннего формата вещественного числа.

Билет24

Конструкции в Turbo Pascal.

1. Условный оператор IF...THEN....ELSE (Если...то...иначе) — организовывает разветвление в алгоритме программы, записывается:

IF Логическое условие THEN Оператор 1

ELSE Оператор 2;

Если выполняется логическое условие, то выполняется оператор 1. В противном случае выполняется оператор 2.

 

2. Оператор цикла с параметром FOR...TO...DO.

Для организации циклического алгоритма часто используется оператор цикла с параметром: for i:=A to B do S, где i-некоторая переменная (параметр или счетчик цикла) типа integer, A и B (B>A) выражения со значением типа integer, S-оператор (тело цикла). Если A>B, то оператор S не будет выполнен ни разу (когда параметр i возрастает). Если параметр i возрастает, то между границами его значений A и B ставится слово TO, если же i убывает, то ставится слово DOWNTO и оператор цикла выполняется при A>B.

3. Оператор цикла с предварительным условием WHILE...DO.

while логическое выражение (условие) do

begin

Операторы циклической части программы (тело цикла)

end;

4. Оператор цикла с последующим условием REPEAT...UNTIL.

Организует выполнение цикла, состоящего из любого числа операторов, с неизвестным заранее числом повторений. Тело цикла выполняется хотя бы один раз. Выход из цикла осуществляется при истинности некоторого логического выражения (условия).

Структура оператора:

REPEAT <тело цикла> UNTIL <условие>, где <тело цикла> — последовательность операторов Turbo Pascal, <условие> - выражение логического типа. Структуру оператора REPEAT...UNTIL можно также представить в виде:

REPEAT

Instruction1;

Instruction2;

.............

InstructionM;

UNTIL S;

Instruction1, Instruction2, ..., InstructionM — выполняемые операторы, составляющие тело цикла, S-логическое условие, истинность которого проверяется в конце каждого повторения.

Билет25

В языке Паскаль ввод-вывод информации осуществляется через файловые переменные.Перед тем, как осуществлять ввод-вывод, файловая переменная должна быть связана с конкретным внешним файлом с помощью процедуры Assign. Этим файлом может быть файл на магнитном диске или ленте, а также устройство вычислительного комплекса (клавиатура, экран дисплея, принтер и т.д.). Затем файл должен быть открыт для чтения и/или записи. После этого можно осуществлять организацию ввода-вывода.В Turbo Pascal имеется 3 категории файлов: текстовые (тип Text), типизированные

(file of <тип>) и файлы без типа (file) . Работа с этими категориями файлов несколько отличается друг от друга.Обычно все файлы считаются файлами последовательного доступа. Однако для типизированных файлов и файлов без типа с помощью процедуры Seek можно установить режим произвольного доступа. При этом нумерация компонент файла начинается с нуля.После работы с файлом он, как правило, должен быть закрыт процедурой Close. Это требование обязательно должно соблюдаться для файла, в который производилась запись.При работе с файлами автоматически проверяются ошибки ввода-вывода. Если проверка ошибки включена (по умолчанию или с помощью ключа компилятора {$I+}), то при возникновении ошибки выполнение программы автоматически завершается, если же проверка ошибки отключена (с помощью ключа {$I-}), программа продолжает выполняться и можно проверить результаввода-вывода с помощью функции IOResult.

Билет26

Порядок выполнения операций

В сложных выражения порядок операций определяется их приоритетом. Операции одного приоритетного уровня выполняются слева направо. Порядок операций можно изменить, воспользовавшись круглыми скобками. Значения функций вычисляются раньше, чем выполняются другие операции. Приоритетные уровни операций следующие (по убыванию приоритета):

Одноместные (унарные) операции: +, -, not.

Мультипликационные операции: *, /, div, mod, and.

Аддитивные операции: +, -, or, xor.

Операции отношения: <, <=, >, >=, =, <>.

Операторы языка Pascal

1. Составной и пустой операторы

Составной оператор - это последовательность произвольных операторов программы, заключенная в операторные скобки.

Турбо-Паскаль допускает произвольную глубину вложенности:

Begin

...

Begin

...

Begin

...

End;

End;

End;

Наличие ; перед End - пустой оператор.

2. Операторы ветвлений

Условный оператор

IF <условие> THEN <оператор1> [ELSE <оператор2>]

Условие – значение типа BOOLEAN или логическая операция. Если условие верно, выполняется оператор, или блок операторов, следующий за THEN, в противном случае выполняется блок операторов после ELSE, если он есть.

Условия могут быть вложенными и в таком случае, любая встретившаяся часть ELSE соответствует ближайшей к ней "сверху" части THEN.

Пример:

Var

A, B, C, D: Integer;

begin

A:=1;

B:=2;

C:=3;

D:=4;

If A > B Then

If C < D Then

If C < 0 Then

C:=0

{обратите внимание, что перед Else}

{пустой оператор ";"не ставится}

Else

A:=B;

end.

а могло быть и так:

If A > B Then

If C < D Then

If C < 0 Then

C:=0

Else

Else

Else A:=B

 

Рассмотрим программу, которая вводит произвольное целое число от 0 до 15 и выводит его в шестнадцатеричной системе:

Program Hex;

Var

Ch: Char;

N: Integer;

Begin

Write ('N = ');

Readln(N);

If (N >= 0) And (N <= 15) Then

Begin

If N < 10 Then

Ch:= Chr(Ord('0')+N)

Else

Ch:=Chr(Ord('A')+N-10);

End

Else

Writeln('Ошибка');

End.

3. Операторы повторений

Цикл с предопределенным числом повторений.

For <переменная цикла>:=<начальное значение> To(DownTo) <конечное значение> Do <блок операторов>

Переменная должна быть целого или перечислимого типа. При исполнении цикла переменная цикла изменяется от начального до конечного значения с шагом 1. Если стоит to, то переменная увеличивается, если downto – уменьшается.

Условия выполнения цикла проверяются перед выполнением блока операторов. Если условие не выполнено, цикл For не выполняется. Далее программа подсчитывает сумму чисел от 1 до введенного:

Program Summa;

Var

I, N, S: Integer;

Begin

Write('N = ');

Readln(N);

S:=0;

For I:=1 To N Do

S:=S + I;

Writeln ('Cумма = ', S)

End.

Условный цикл с проверкой условия перед исполнением блока операторов.

While <условие> Do <блок операторов>

Блок операторов будет исполняться, пока условие имеет значение true. Необходимо, чтобы значение условия имело возможность изменения при исполнении блока операторов, иначе исполнение цикла не закончится никогда (в DOS это приведет к зависанию компыютера). Если условие зарание ложно, блок операторов не исполнится ни разу.

Найдем машинное "эпсилон" для переменной типа Real:

Program Epsilondetect;

Var

Epsilon: Real;

Begin

Epsilon:=1;

While Epsilon + 1 > 1 Do

Epsilon: = Epsilon/2;

Writeln ('Эпсилон = ', Epsilon);

End.

Условный цикл с проверкой после выполнения блока операторов.

Repeat <тело цикла> Until <условие>

Блок операторов независимо от значения условия будет выполнен хотябы один раз. Цикл заканчивается, если после очередного исполнения блока операторов условие имеет значение true.

Пример: программа запрашивает ввод одного символа и выводит его ASCII - код, пока не будет введен пустой символ:

Program Code;

Const

Cr = 13;

Var

Ch:Char;

Begin

Repeat

Readln (Ch);

Writeln (Ch,' = ', Ord (Ch));

Until Ord (Ch) = Cr

End.

 

Оператор выбора одного из вариантов.

Case <ключ выбора> Of <список выбора> Else <оператор> End;

<ключ выбора> - выражение любого перечислимого типа,

<список выбора> - одна или более конструкций вида <значение ключа>:<блок операторов>.

Составим программу, имитирующую калькулятор. Программа вводит две строки: первая содержит два числа, разделенные пробелом или запятой, вторая - символ арифметического действия.

2 2

*

Признаком конца работы служит ввод любого символа, отличного от +, -, /, *.

Программа:

Program Calc; Var

Operation: Char; {Знак Операции}

X, Y, Z: Real;

Stop: Boolean;

Begin

Stop:= False;

repeat

Writeln; {Пустая Строка - Разделитель}

Write ('X, Y = ');

Readln (X,Y);

Write ('Операция: ');

Readln (Operation);

Case Operation Of

'+': Z: = X+Y;

'-': Z: = X-Y;

'*': Z: = X*Y;

'/': Z: = X/Y;

Else

Stop:= True;

End;

If Not Stop Then

Writeln('Z = ',Z);

Until Stop;

End.

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

Оператор безуслов ного перехода на строку с меткой.

Goto <метка>

Метка, должна быть описана в разделе описаний. Метка, описанная в процедуре (функции) локализуется в ней, поэтому передача управления извне процедуры (функции) на метку внутри нее невозможна.

Билет 27

Массивы в Turbo Pascal.

Массив — это множество однотипных элементов, объединённых общим именем и занимающих в компьютере определённую область памяти.

Количество элементов в массиве всегда конечно.

В качестве элементов массива можно использовать любой тип данных, поэтому вполне правомерно существование массивов записей, массивов указателей, массивов строк, массивов и т.д. Элементами массива могут быть данные любого типа, включая структурированные. Для описания массива предназначено словосочетание array of (массив из).

Одномерным массивом называется совокупность данных, выполняющих аналогичные функции, и обозначаемая одним именем. Если за каждым элементом массива закреплен только один его порядковый номер, то такой массив называется линейным, или одномерным <имя массива>: = array [<количество элементов>] of <тип переменной>;

Каждый элемент массива в общем виде описывается как А [I], где А — имя массива, I — номер или индекс массива (0<=I<=N, но практически употребляется 1<=I<=N) A[I] - значение элемента массива.

Действия над массивами и его элементами

Для работы с массивом как единым целым используется идентификатор массива без указания индекса в квадратных скобках. Массив может участвовать только в операциях отношения "равно", "не равно" и в операторе присваивания. Массивы, участвующие в этих действиях, должны быть идентичны по структуре, т. е. иметь одинаковые типы индексов и одинаковые типы компонентов.

После объявления массива каждый его элемент можно обработать, указав идентификатор (имя) массива и индекс элемента в квадратных скобках.

Индексированные элементы массива называются индексированными переменными и могут быть использованы так же, как и простые переменные. Например, они могут находиться в выражениях в качестве операндов, использоваться в операторах for, while, repeat, входить в качестве параметров в операторы Read, Readln, Write, Writeln; им можно присваивать любые значения, соответствующие их типу.

Двумерным называется массив, элемент которого зависит от его местоположения в строке и в столбце. В общем виде элемент матрицы обозначается как A(I,J), где А — имя массива, I — индекс (номер) строки, J — индекс (номер) столбца.

Матрицу на языке Паскаль можно задать двумя способами:

имя матрицы>: array [<количество строк>] of array [<количество столбцов>] of <тип переменной>;

<имя матрицы>: array [<количество строк >,<количество столбцов>] оf <тип переменной>].

 

Массивы в Паскале. Одномерные массивы

Предположим, что программа работает с большим количеством однотипных данных. Скажем около ста разных целых чисел нужно обработать, выполнив над ними те или иные вычисления. Как вы себе представляете 100 переменных в программе? И для каждой переменной нужно написать одно и тоже выражение вычисления значения? Это очень неэффективно.

 

Есть более простое решение. Это использование такой структуры (типа) данных как массив. Массив представляет собой последовательность ячеек памяти, в которых хранятся однотипные данные. При этом существует всего одно имя переменной связанной с массивом, а обращение к конкретной ячейке происходит по ее индексу (номеру) в массиве.

Нужно четко понимать, что индекс ячейки массива не является ее содержимым. Содержимым являются хранимые в ячейках данные, а индексы только указывают на них. Действия в программе над массивом осуществляются путем использования имени переменной, связанной с областью данных, отведенной под массив.

Итак, массив – это именованная группа однотипных данных, хранящихся в последовательных ячейках памяти. Каждая ячейка содержит элемент массива. Элементы нумеруются по порядку, но необязательно начиная с единицы (хотя в языке программирования Pascal чаще всего именно с нее). Порядковый номер элемента массива называется индексом этого элемента.

Помним, все элементы определенного массива имеют один и тот же тип. У разных массивов типы данных могут различаться. Например, один массив может состоять из чисел типа integer, а другой – из чисел типа real.

Индексы элементов массива обычно целые числа, однако могут быть и символами, а также описываться другими порядковыми типами. Т.е. для индекса можно использовать тип, в котором определена дискретная последовательность значений, и все эти значения можно пересчитать по порядку. Индексировать можно как константами и переменными, так и выражениями, результат вычисления которых дает значение перечислимого типа.

Если индекс массива может приобретать все допустимые значения определенного перечислимого типа, то при описании массива возможно задание имени типа вместо границ изменения индекса. При этом границами индекса будут первое и последнее значения в описании типа индекса. Границы изменения индексов могут задаваться с помощью ранее объявленных констант. Рекомендуется предварительно объявлять тип массива в разделе описания типов.

Массив можно создать несколькими способами.

 

const n = 200;

type

months = (jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec);

years = 1900..2100;

people = array[years] of longint;

var

growth: array[months] of real;

hum: people;

notes: array[1..n] of string;

 

Обращение к определенному элементу массива осуществляется путем указания имени переменной массива и в квадратных скобках индекса элемента.

Простой массив является одномерным. Он представляет собой линейную структуру.

var ch: array [1..11] of char;

h: char;

i: integer;

 

begin

for i := 1 to 11 do read (ch[i]);

 

for i := 1 to 11 do write (ch[i]:3);

 

readln

end.

В примере выделяется область памяти под массив из 11 символов. Их индексы от 1 до 11. В процессе выполнения программы пользователь вводит 11 любых символов (например, ‘q’, ’w’, ’e’, ’2’, ’t’, ’9’, ’u’, ’I’, ’I’, ’o’, ’p’), которые записываются в ячейки массива. Текущее значение переменной i в цикле for используется в качестве индекса массива. Второй цикл for отвечает за вывод элементов массива на экран.

Ввод массива Паскаля

Для того чтобы ввести значения элементов массива, необходимо последовательно изменять значение индекса, начиная с первого до последнего, и вводить соответствующий элемент. Для реализации этих действий удобно использовать цикл с заданным числом повторений, т.е. простой арифметический цикл, где параметром цикла будет выступать переменная – индекс массива Паскаля. Значения элементов могут быть введены с клавиатуры или определены с помощью оператора присваивания.

Пример фрагмента программы ввода массива Паскаля

Var A : array [1..10] of integer ;

I : byte ; {переменная I вводится как индекс массива}

Begin

For i:=1 to 10 do Readln (a[i]); { ввод i- го элемента производится с клавиатуры }

 

 

Рассмотрим теперь случай, когда массив Паскаля заполняется автоматически случайными числами, для этого будем использовать функцию random(N).

 

Пример фрагмента программы заполнения массива Паскаля случайными числами

Var A: array [1..10] of integer;

I : byte ; {переменная I вводится как индекс массива}

Begin

For i :=1 to 10 do A [ i ]:= random (10); { i -му элементу массива присваивается «случайное» целое число в диапазоне от 0 до 10}

Вывод массива Паскаля

Вывод массива в Паскале осуществляется также поэлементно, в цикле, где параметром выступает индекс массива, принимая последовательно все значения от первого до последнего.

Пример фрагмента программы вывода массива Паскаля

Var A: array [1..10] of integer;

I : byte ; {переменная I вводится как индекс массива}

Begin

For i :=1 to 10 do Write ( a [ i ],’ ‘); {вывод массива осуществляется в строку, после каждого элемента печатается пробел}

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

Пример программы вывода массива Паскаля в столбик

Var A: array [1..10] of integer;

I : byte ; {переменная I вводится как индекс массива}

Begin

For i:=1 to 10 do Writeln (‘a[‘, i,’]=’, a[i]); { вывод элементов массива в столбик }

На экране мы увидим, к примеру, следующие значения:

 

Пример

a[1]=2

a[2]=4

a[3]=1 и т.д.

Билет 28

Массив — это множество однотипных элементов, объединённых общим именем и занимающих в компьютере определённую область памяти.

Количество элементов в массиве всегда конечно.

В качестве элементов массива можно использовать любой тип данных, поэтому вполне правомерно существование массивов записей, массивов указателей, массивов строк, массивов и т.д. Элементами массива могут быть данные любого типа, включая структурированные. Для описания массива предназначено словосочетание array of (массив из).

Одномерным массивом называется совокупность данных, выполняющих аналогичные функции, и обозначаемая одним именем. Если за каждым элементом массива закреплен только один его порядковый номер, то такой массив называется линейным, или одномерным <имя массива>: = array [<количество элементов>] of <тип переменной>;

Каждый элемент массива в общем виде описывается как А [I], где А — имя массива, I — номер или индекс массива (0<=I<=N, но практически употребляется 1<=I<=N) A[I] - значение элемента массива.

Действия над массивами и его элементами

Для работы с массивом как единым целым используется идентификатор массива без указания индекса в квадратных скобках. Массив может участвовать только в операциях отношения "равно", "не равно" и в операторе присваивания. Массивы, участвующие в этих действиях, должны быть идентичны по структуре, т. е. иметь одинаковые типы индексов и одинаковые типы компонентов.

После объявления массива каждый его элемент можно обработать, указав идентификатор (имя) массива и индекс элемента в квадратных скобках.

Индексированные элементы массива называются индексированными переменными и могут быть использованы так же, как и простые переменные. Например, они могут находиться в выражениях в качестве операндов, использоваться в операторах for, while, repeat, входить в качестве параметров в операторы Read, Readln, Write, Writeln; им можно присваивать любые значения, соответствующие их типу.

Двумерным называется массив, элемент которого зависит от его местоположения в строке и в столбце. В общем виде элемент матрицы обозначается как A(I,J), где А — имя массива, I — индекс (номер) строки, J — индекс (номер) столбца.

Матрицу на языке Паскаль можно задать двумя способами:

имя матрицы>: array [<количество строк>] of array [<количество столбцов>] of <тип переменной>;

<имя матрицы>: array [<количество строк >,<количество столбцов>] оf <тип переменной>].

Одномерный массив можно представить как линейную структуру, в которой элементы следуют друг за другом. Однако бывают более сложные структуры данных. Например, двумерные массивы, которые можно описать как таблицу, в ячейках которой располагаются значения. Для обращения к данным массива указывается номера их строк и столбцов. Часто табличные массивы называют матрицами.

Обычно двумерные массивы на языке программирования Pascal описываются так:

array [1..m, 1..n] of базовый_тип

Однако можно их описывать и по-другому:

array [1..m] of array [1..n] of базовый_тип

При этом описание может быть в разделе type и тогда создается новый тип, который можно использовать при объявлении переменных. Или массив может быть описан непосредственно в разделе переменных. m и n – это константы, их можно опустить и вставить конкретные значения, но лучше так не делать. Обычно подразумевают, что в интервале от 1 до m определяется количество строк, а в интервале от 1 до n – количество столбцов массива.

1 вариант – описание массива через раздел type:

const

M = 10;

N = 5;

type

matrix = array [1..M, 1..N] of integer;

var

a: matrix;

 

2 вариант – описание массива в разделе переменных:

const

M = 10;

N = 5;

var

a: array [1..M, 1..N] of integer;

 

При использовании третьего варианта описания лучше сначала определить некоторый тип одномерного массива (строка двухмерного массива), который затем используется при описании двухмерного массива:

type a = array[1..10] of byte;

var b: array[1..100] of a;

 

Для обращения к элементу двухмерного массива необходимо указать имя массива и в квадратных скобках через запятую – значения двух индексов (первый указывает номер строки, а второй – номер столбца), на пересечение которых стоит элемент (например, a[i,2]:=6). В языке программирования Pascal допустимо разделение индексов с помощью квадратных скобок (например, a[i][5]:= 7).

Если описывается двумерный массив как типизированная константа, то при задании значений его элементов он рассматривается как массив массивов. При этом в общих круглых скобках через запятую перечисляются заключенные в круглые скобки значения элементов строк (каждая строка в своих скобках):

type

arr = array[1..4, 1..3] of integer;

const

cords: arr = ((1,-1,3), (0,0,0), (1,4,0), (4,-1,-1));

Рассмотрим простой пример работы с двумерным массивом. Сначала заполним его данными, а затем выведем их на экран в виде таблицы.

var

matrix: array[1..3,1..5] of integer;

i, j: integer;

begin

writeln ('Введите 15 чисел: ');

for i := 1 to 3 do

for j := 1 to 5 do

read (matrix[i,j]);

 

for i := 1 to 3 do begin

for j := 1 to 5 do

write (matrix[i,j], ' ');

writeln

end;

 

readln

end.

 

Размерность массива (т.е. количество содержащихся в нем значений) определяется произведением количества строк на количество столбцов. В примере выше в массив помещается 15 значений.

Когда пользователь вводит очередное число, то процедура read считывает его и помещает в ячейку с текущими индексами i и j. Когда i равна единице, значение j меняется пять раз, и, значит, заполняется первая строка таблицы. Когда i равна двум, значение j снова меняется пять раз и заполняется вторая строка таблицы. Аналогично заполняется третья строка таблицы. Внутренний цикл for в общей сложности совершает 15 итераций, внешний только 3.

Как пользователь вводит значения – не важно. Он может их разделять либо пробелом, либо переходом на новую строку.

Вывод значений двумерного массива организован в виде таблицы. Выводятся 3 строки по 5 чисел в каждой. Внутри строк числа разделяются пробелом.

На самом деле, это не совсем корректно написанная программа. Мы несколько раз используем цифры 3 и 5. А что если мы захотим поменять размерность массива? Придется просмотреть всю программу (представьте, что она очень большая) и исправить значения. Это неэффективно. Поэтому в программе следует использовать константы. В случае чего их значения можно поменять всего лишь в одном месте.

Вторая проблема – это «кривость» выводимой на экран таблицы значений матрицы, в случае если есть значения разной разрядности (однозначное, двузначное и т.д. числа). Неплохо бы под каждое число отводить равное количество знаков.

Вот так может выглядеть подправленный вариант программы:

const

M = 3;

N = 5;

var

matrix: array[1..M,1..N] of integer;

i, j: integer;

begin

writeln ('Введите 15 чисел: ');

for i := 1 to M do

for j := 1 to N do

read (matrix[i,j]);

 

for i := 1 to M do begin

for j := 1 to N do

write (matrix[i,j]:5);

writeln

end;

readln

end.

 

Билет 29

Многомерные массивытак же часто используются, как и одномерные. Вот примеры: в школьных журналах написаны Фамилия и класс; любые базы данных; Вообще, многомерные массивы - это массивы массивов. Т.е. каждый индексный номер содержит массив. Вот пример уже из языка Си:

int i[2][4] = {{1,2,3,4}, {5,6,7,8}};

Т.е. тут мы создаем двумерный массив размером 2х4. Т.е. 2 строчки по 4 элемента каждая.

В принципе, остальное тут так же. Давайте теперь рассмотрим, как в многомерном массиве вводить и выводить элементы:

#include <conio.h>

#include <stdio.h>

int main()

int arr[2][4];

for (int i = 0; i < 2; i++){

for (int j = 0; j < 4;j++ ){

scanf ("%d", &arr[i][j]);

for (int i = 0; i < 2; i++){

for (int j = 0; j < 4;j++ ){

printf ("%d ", arr[i][j]);

printf ("\n");

getch();

return 0;

Все очень похоже на одномерный массив. Только в многомерном массиве мы создаем двойной цикл, первый - это проход по столбцу, а второй - это проход по элементам массива (идем по строке).

Во всех моих примерах при изменении размера многомерного массива, например вместо arr[2][4], хочу сделать arr[7][6]. Так вот, что бы сделать такое изменения придется изменять абсолютно все циклы, так как они ориентируются по старым данным. Но есть способ исправить эту проблему.

Для этого в языке С/C++ есть директива предпроцессора define. Давайте рассмотрим его на примере:

#include <conio.h>

#include <stdio.h>

#define SIZE_A 2

#define SIZE_B 2

int main()

int arr[SIZE_A][SIZE_B];

for (int i = 0; i < SIZE_A; i++){

for (int j = 0; j < SIZE_B;j++ ){

scanf ("%d", &arr[i][j]);

for (int i = 0; i < SIZE_A; i++){

for (int j = 0; j < SIZE_B;j++ ){

printf ("%d ", arr[i][j]);

printf ("\n");

getch();

 

return 0;

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

Осталось научиться передавать многомерные массивы в функцию. Вот как это делается:

void printArr (int arr[][2]){ //тело; }

Тут обязательным условием является написание во втором индексе количества элементов, иначе компилятор выдаст ошибку. Ах да, вызывается функция из программы, так же как и одномерный массив:

printArr(arr);

Вот и все, что хотелось вам рассказать о многомерных массивах. Лучше всего любой материал по программированию запоминается на практике.

Задания:

попробуйте попробовать заполнить и вывести массив, но не при помощи индексов, а при помощи указателей. Это довольно сложно, но если долго мучиться, то точно получится

у нас есть массив 4х4. вычислите сумму элементов главной диагонали (1х1, ... , 4х4)

составьте функцию, которая принимает двумерный массив. Функция заменяет все простые числа в массиве нулями

Упакованные строки

Упакованные строки - это также массив из 4-ех байтовых ячеек, но схема размещения памяти другая, где вся память ячейки испольуется. В результате для размещения каждого символа необходим 1 байт (8 бит) вместо 4 байтов (32 битов) у распакованных строк. Когда вы используете упакованную строку, то в ячейки будет уже 4 символа, вместо одного у распакованных.

Примечание: Упакованная строка может хранить символы только одно-байтовой кодировки, такие как ASCII, или один из расширенных наборов ASCII.

Например:

Данный пример показывает представление 4-ех байтовой ячейки у упакованной строки. Каждый цветной байт хранит один символ строки. Вся память используется. Упакованный вариант слова "pack":

0111 0000 0110 0001 0110 0011 0110 1011

Когда нужно использовать упакованные строки, а когда распакованные?

Упакованные:

Хранение численных значений в диапозоне 0-255

Хранение ASCII текста

 

 

Распакованные:

Хранение численных значений больше 255

Хранение юникод текста или стандарта не ASCII

Как использовать упакованные строки в AMXX скриптинге?

Использование упакованных строк очень похоже на использование распакованных за исключением доступа к строке. Вы не можете выводить (печатать) или делать манипуляцию с упакованной строкой, как бы мы это делали с распакованной. Вы сначала должны ее распаковать, а затем уже выводить/форматировать и так далее.

Здесь приведены две простые функции для упаковки и распаковки строк:

public strpack(const s_Unpacked[], s_Packed[])

new i

while((s_Packed{i} = s_Unpacked[i++])) {}

public strunpack(const s_Packed[] , s_Unpacked[])

new i

while((s_Unpacked[i] = s_Packed{i++})) {}

При объявления переменной нужно указывать желательный размер и добавлять 'char' идентификатор после него. Вы также должны указывать символ '!' перед присвоением строки переменной.

Пример:

Код: Выделить всё

new s_String[11 char] = !"The string"

Доступ к ячейке строки похож на доступ к элементу распакованной строки, только вместо [] нужно использовать {}.

Пример:

 

Код: Выделить всё

Распакованная строка = s_String[5]

Упакованная строка = s_String{5}

Сколько памяти я съэкономлю при использовании упакованных строк?

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

Код: Выделить всё

#defined PACKED_STRINGS

Код: Выделить всё

#include <amxmodx>

#define PLUGIN "Packed vs Unpacked"

#define VERSION "1.0"

#define AUTHOR "bugsy"

#define PACK_STRINGS

#define NUM_STRINGS 20

#define MAX_STRING_SIZE 512

#if defined PACK_STRINGS

new g_szUnpackBuffer[MAX_STRING_SIZE];

new g_szStrings[NUM_STRINGS][MAX_STRING_SIZE char]

#else

new g_szStrings[NUM_STRINGS][MAX_STRING_SIZE]

#endif

public plugin_init()

register_plugin(PLUGIN, VERSION, AUTHOR)

public plugin_cfg()

for ( new iTest = 0 ; iTest < NUM_STRINGS ; iTest++ )

#if defined PACK_STRINGS

g_szStrings[iTest] = !"Packed strings"

strunpack( g_szStrings[iTest] , g_szUnpackBuffer );

server_print( "%d = %s" , iTest , g_szUnpackBuffer );

#else

g_szStrings[iTest] = "Unpacked strings";

server_print( "%d = %s" , iTest , g_szStrings[iTest] );

#endif

#if defined PACK_STRINGS

public strunpack( szPacked[] , szUnpacked[] )

new i;

while((szUnpacked[i] = szPacked{i++})){}

#endif

Билет 30

Структурное программирование - методология разработки программного обеспечения, предложенная в 70-х года XX века Дейкстрой и разработанная и дополненная Виртом.

В соответствии с данной методологией любая программа представляет собой структуру, построенную из трёх типов базовых конструкций:

последовательного исполнение — однократное выполнение операций в том порядке, в котором они записаны в тексте программы;

ветвление — однократное выполнение одной из двух или более операций, в зависимости от выполнения некоторого заданного условия;

цикл — многократное исполнение одной и той же операции до тех пор, пока выполняется некоторое заданное условие (условие продолжения цикла.

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

Повторяющиеся фрагменты программы (либо не повторяющиеся, но представляющие собой логически целостные вычислительные блоки) могут оформляться в виде так называемых подпрограмм (процедур или функций). В этом случае в тексте основной программы вместо помещённого в подпрограмму фрагмента вставляется инструкция вызова подпрограммы. При выполнении такой инструкции выполняется вызыванная подпрограмма, после чего исполнение программы продолжается со следующей за командой вызова подпрограммы инструкции.

Разработка программы ведётся пошагово, методом "сверху вниз". Сначала пишется текст основной программы, в котором вместо каждого связного логического фрагмента текста вставляется вызов подпрограммы, которая будет выполнять этот фрагмент. Вместо настоящих, работающих подпрограмм, в программу вставляются "затычки", которые ничего не делают. Полученная программа проверяется и отлаживается. После того, как программист убедится, что подпрограммы вызваются в правильной последовательности (то есть общая структура программы верна), подпрограммы-"затычки" последовательно заменяются на реально работающие, причём разработка каждой подпрограммы ведётся тем же методом, что и основной программы. Разработка заканчивается тогда, когда не останется ни одной "затычки", которая не была бы удалена. Такая последовательность гарантирует, что на каждом этапе разработки программист одновременно имеет дело с обозримым и понятным ему множеством фрагментов и может быть уверен, что общая структура всех более высоких уровней программы верна. При сопровождении и внесении изменений в программу выясняется, в какие именно процедуры нужно внести изменения, и они вносятся, не затрагивая непосредственно не связанные с ними части программы. Это позволяет гарантировать, что при внесении изменений и исправлении ошибок не выйдет из строя какая-то часть программы, находящаяся в данный момент вне зоны внимания программиста.

Подпрограмма - последовательность операторов языка, предназначенных для решения некоторой подзадачи. Каждая подпрограмма имеет имя, по которому можно к ней обратиться.

Использование подпрограмм:

позволяет сократить объем программы;

улучшает структуру программы с точки зрения ее читаемости и наглядности;

уменьшает вероятность ошибок и облегчает процесс отладки.

Подпрограммы в языке Паскаль реализованы посредством процедур и функций. Имея один и тот же смысл и аналогичную структуру, процедуры и функции различаются назначением и способом их использования.

Функция передает в точку вызова единственный результат как значение этой функции. Имя функции может входить в выражение как операнд.

Процедура может возвращать в вызывающую программу несколько значений или не одного. Процедура не может выступать как операнд в выражении.

Параметры процедур и функций

Для процедур и функций общим является наличие списка параметров, приводимого в скобках после имени процедуры или функции.

Подпрограмма реализует некоторый частный алгоритм, который вызывается в основной программе. Для реализации алгоритма подпрограмме могут понадобиться некоторые данные из основной программы. Обработав эти данные, подпрограмма возвращает результат основной программе, если в этом есть необходимость. Передавать информацию из основной программы в подпрограмму и наоборот мы можем только через переменные, которые носят специальное название - параметры.

Результат выполнения процедуры - это одно или несколько значений. Результат передается в основную программу через ее выходные параметры.

Схематично это можно изобразить следующим образом:

Pascal-Urok13-1

Переменные, с помощью которых передается информация из основной программы в подпрограмму, называются входными параметрами. Переменные, через которые информация поступает из подпрограммы в основную программу, называются выходными.

Передача параметров

Параметры, указываемые при описании подпрограммы, называются формальными. Параметры, указываемые при вызове подпрограммы, называются фактическими.

Если формальный параметр описан со служебным словом var, то его называют параметром-переменной и говорят, что он передается по ссылке. Если же параметр описан без слова var, то его называют параметром-значением и говорят, что он передается по значению.

Если параметр передается по значению, то при вызове подпрограммы значения фактических параметров (т. е. их копии) присваиваются соответствующим формальным параметрам. При этом подпрограмма работает не с объектом, а с его копией. Изменение формального параметра внутри подпрограммы никак не влияет на значение фактических параметров в основной программе.

Если параметр передается по ссылке, то при вызове подпрограммы фактический параметр заменяет собой в теле подпрограммы соответствующий ему формальный параметр (в подпрограмму передается адрес фактического параметра). В итоге любые изменения формального параметра- переменной внутри подпрограммы приводит к соответствующим изменениям фактического параметра.

В качестве фактического параметра-значения можно указать выражение. В качестве фактического параметра-переменной можно указать только переменную.

Глобальные и локальные переменные

В программе все переменные делятся на глобальные и локальные.

Глобальные переменные - это те переменные, которые объявляются в описании основной программы.

Локальные переменные - это те, которые описаны в процедурах и функциях. Эти переменные помещаются в стек при вызове подпрограммы и удаляются из него при возвращении в точку вызова. Таким образом, локальные переменные существуют только тогда, когда работает подпрограмма, появляются при вызове и исчезают при завершении работы.

Все процедуры и функции языка Паскаль делятся на две группы: встроенные (стандартные) и определенные пользователем. Первые входят в состав языка и вызываются по строго фиксированному имени. Вторые разрабатываются и именуются самим пользователем.

 

Процедура — это независимая именованная часть программы, которую можно вызвать по имени для выполнения определенных действий. Структура процедуры повторяет структуру программы. Процедура не может выступать как операнд в выражении. Упоминание имени процедуры в тексте программы приводит к активизации процедуры и называется ее вызовом. Например, Read(F) читает с клавиатуры некоторое значение и присваивает его переменной F, Delay(5) вызывает задержку выполнения программы на 5 мс.

Функция аналогична процедуре, но имеются два отличия: функция передает в точку вызова скалярное значение; имя функции может входить в выражение как операнд. Например, функция Chr(65) возвратит в точку вызова символ А (код ASCII — 65), Sqr(X) — возведет в квадрат значения целого или вещественного X и возвратит в точку вызова вычисленное значение квадрата числа X.

Итак, отличие подпрограмм-процедур от подпрограмм-функций состоит в том, что процедуры служат для задания совокупности действий, направленных на изменение внешней по отношению к ним программной обстановки, а функции, являясь частным случаем процедур, отличаются от них тем, что они обязательно возвращают в точку вызова основной программы единственный результат как значение имени этой функции.

Все процедуры и функции языка Турбо Паскаль делятся на две группы: встроенные (стандартные) и определенные пользователем. Первые входят в состав языка и вызываются для выполнения по строго фиксированному имени. Вторые разрабатываются и именуются самим пользователем. Все стандартные средства расположены в специализированных библиотечных модулях, которые имеют системные имена.