14-es / ЭС - Информатика (ИСФ) / умк_Спиридонов_Информатика_ч.1_2013
.pdf2.8.3. Выборка элементов массива
Составить программу подсчета количества положительных элемен- тов массива, состоящего из 10 элементов.
Текст программы:
program mas3;
var k, i : integer;
a: array[1..10] of integer; begin
for i:=1 to 10 do begin
writeln(' Введите элемент массива'); readln(a[i]);
end;
writeln(' Элементы исходного массива'); for i:=1 tо 10 do
write (a[i],' '); writeln;
k:=0;
for i:=1 to 10 do
if a[i]>0 then k:=k+1; writeln(' Количество равно',k);
end.
Найти значение и номер наибольшего элемента в массиве из 10 це- лочисленных элементов.
Текст программы:
program mas4;
var n, m, i : integer;
a: array[1..10] of integer; begin
for i:=1 to 10 do begin
writeln('Введите элемент массива'); readln(a[i]);
end;
writeln('Элеметы исходного массива');
for i:=1 to 10 do |
|
|
write(a[i]), ' '); |
|
|
writeln; |
|
|
m:=a[1]; n:= 1; |
|
|
for i:=2 to 10 do |
|
|
if a[i]>m then |
|
|
begin |
m:= a[i]; |
n:= i; end; |
writeln('Максимальный элемент равен', m, 'и имеет порядковый номер', n);
end.
51
2.8.4. Сортировка массива
Под сортировкой массива подразумевается процесс перестановки его элементов с целью упорядочивания их в соответствии с каким-либо крите- рием. Сортировка проводится на основании сравнения значений элементов массива друг с другом. Можно сравнивать значения целых, вещественных, символьных, строчных и производных от них типов.
Сортировка методом прямого выбора. Алгоритм сортировки мас-
сива по возрастанию методом прямого выбора:
1.Просматривая массив от первого элемента, найти минимальный и поместить его на место первого элемента, а первый – на место минимального.
2.Просматривая массив от второго элемента, найти минимальный и поместить его на место второго элемента, а второй – на место минимального.
3.И так далее до последнего элемента.
Для демонстрации рассмотрим программу сортировки массива це- лых чисел по возрастанию (для контроля выполнения алгоритма програм- ма выводит массив после каждого обмена элементами).
program sort1;
Const size=5;
Var
a: array[1..size] of integer;
i: integer; {номер элемента, от которого ведется по-
иск минимального элемента}
min: integer; {номер минимального элемента в части массива от i до верхней границы массива}
j: integer; {номер элемента сравниваемого с минимальным} buf: integer; {буфер, используемый при обмене элемен-
тов массива}
k: integer;
begin
writeln(‘Сортировка массива’);
write(‘Введите через пробел’, size:3,’целых в одной строке и нажмите клавишу ввод’);
for k:=1 to size do read(a[k]); writeln(‘Сортировка’);
for i:=1 to size-1 do begin
min:=i;
for j:=i+1 to size do begin
52
if a[j]<a[min] then min:=j;
end;
buf:=a[i]; a[i]:=a[min]; a[min]:=buf;
for k:=1 to size do write(a[k],’ ‘);
writeln;
end; end.
Сортировка методом прямого обмена. В основе алгоритма лежит обмен соседних элементов массива. Каждый элемент массива, начиная с первого, сравнивается со следующим, и если он больше следующего, то элементы меняются местами. Таким образом, элементы с меньшим значе- нием подвигаются к началу массива (всплывают), а элементы с большим значением – к концу массива (тонут), поэтому этот метод иногда называют «пузырьковым». Этот процесс повторяется на единицу меньше раз, чем элементов в массиве. Ниже представлена программа сортировки массива целых чисел по возрастанию. Для демонстрации процесса сортировки про- грамма выводит массив после каждого цикла обменов.
program sort2; const size=5; Var
a: array[1..size] of integer; i: integer; {счетчик циклов} buf: integer;
k: integer; {текущий индекс элемента массива} begin
writeln(‘Сортировка массива методом пузырька’); write(‘Введите через пробел’, size:3,’целых в одной
строке и нажмите клавишу ввод’);
for k:=1 to size do read(a[k]); writeln(‘Сортировка’);
for i:=1 to size-1 do begin
for k:=1 to size-1 do begin
if a[k]>a[k+1] then begin buf:=a[k]; a[k]:=a[k+1]; a[k+1]:=buf; end;
end;
53
for k:=1 to size do write(a[k],’ ‘);
writeln;
end;
end.
2.8.5. Поиск в массиве
Поиск осуществляется последовательным сравнением элементов массива с образцом до тех пор, пока не будет найден элемент, равный об- разцу, или не будут проверены все элементы. Алгоритм простого перебора применяется, если элементы массива не упорядочены.
Рассмотрим программу поиска в массиве целых чисел. Перебор эле- ментов массива осуществляет инструкция REPEAT, в теле которой инст- рукция IF сравнивает текущий элемент массива с образцом и присваивает переменной naiden значение true, если текущий элемент равен образцу. Цикл завершается, если в массиве обнаружен элемент равный образцу, или если проверены все элементы массива. По завершении цикла по значению переменной found можно определить, успешен поиск или нет.
program poisk; var
massiv: array[1..10] of integer; {массив целых} obrazec: integer; {образец для поиска}
naiden: boolean; {признак совпадения с образцом} i: integer;
begin
writeln('Введите через пробел 10 целых элементов мас-
сива и нажмите клавишу ввода'); for i:=1 to 10 do read(massiv[i]);
write('Введите образец для поиска’); readln(obrazec);
naiden:=false;
i:=1; {проверяем с первого элемента массива} repeat
if massiv[i]=obrazec then naiden:=true else i:=i+1; until (i>10)or(naiden);
if naiden then writeln('Совпадение с элементом',i:3,'поиск завершен')
else writeln('Совпадений с образцом нет');
end.
54
2.9. Подпрограммы, пользовательские процедуры и функции
Структура описания процедур и функций до некоторой степени по- хожа на структуру Паскаль-программы: у них также имеются заголовок, раздел описаний и исполняемая часть. Раздел описаний содержит те же подразделы, что и раздел описаний программы: описания констант, типов, меток, процедур, функций, переменных. Исполняемая часть содержит собственно операторы процедур.
Формат описания процедуры имеет вид:
procedure имя процедуры (формальные параметры) ;
раздел описаний процедуры
begin
исполняемая часть процедуры
end;
Формат описания функции:
function имя функции (формальные параметры): тип результата; раздел описаний функции
begin
исполняемая часть функции имя функции:=результат;
end;
Формальные параметры в заголовке процедур и функций записыва- ются в виде:
var имя параметра: имя типа;
и отделяются друг от друга точкой с запятой. Ключевое слово var может отсутствовать для входных параметров, а для выходных должен быть обя- зательно. Если параметры однотипны, то их имена можно перечислять че- рез запятую, указывая общее для них имя типа. При описании параметров можно использовать только стандартные имена типов либо имена типов, определенные с помощью команды type, вызывающей программы. Список формальных параметров может отсутствовать.
Вызов процедуры производится оператором, имеющим следующий формат:
имя процедуры (список фактических параметров);
Список фактических параметров – это их перечисление через запя-
тую. При вызове фактические параметры как бы подставляются вместо
55
формальных, стоящих на тех же местах в заголовке. Таким образом, про- исходит передача входных параметров, затем выполняются операторы ис- полняемой части процедуры, после чего происходит возврат в вызываю- щий блок. Передача выходных параметров происходит непосредственно во время работы исполняемой части.
Вызов функции в Паскаль может производиться аналогичным спосо- бом, кроме того, имеется возможность осуществить вызов внутри какого- либо выражения. В частности, имя функции может стоять в правой части оператора присваивании, в разделе условий оператора if и т.д.
Для передачи в вызывающий блок выходного значения функции в исполняемой части функции перед возвратом в вызывающий блок необ- ходимо поместить следующую команду:
имя функции : = результат;
При вызове процедур и функций необходимо соблюдать следующие правила:
–количество фактических параметров должно совпадать с количе- ством формальных;
–соответствующие фактические и формальные параметры должны совпадать по порядку следования и по типу.
Процедуры и функции должны обладать определенной независимо- стью в смысле использования переменных, типов и констант. В связи
сэтим возникает необходимость разделять данные на глобальные и ло- кальные по их доступности из других подпрограмм.
Глобальные – это те константы, типы и переменные, которые объяв- лены в программе вне описания процедуры и функции и до их описания. Они доступны вызывающей программе и вызываемой подпрограмме.
Локальные константы, типы и переменные существуют только внут- ри подпрограммы, в которой они описаны через разделы объявлений или через список формальных параметров. Они доступны только подпрограм- ме, в которой они описаны.
Рассмотрим использование процедуры на примере программы поис- ка максимума из двух целых чисел.
var x,y,m,n : integer;
procedure MaxNumber (a,b: integer; var max: integer);
{в заголовке процедуры a,b – входные параметры, max – выход-
ной параметр};
begin {начало процедуры}
if a>b then max := a еlse max := b;
56
end;{конец процедуры}
begin {начало основной программы}
write ('Введите х,у ');
readln(x,y); |
|
MaxNumber(x,y,m); |
{формальный параметр a получает |
значение х, b – значение y при вызове процедуры, m – значение результата из процедуры через параметр max};
MaxNumber(2,x+y,n);
writeln('m=',m,'n=',n);
end. {Конец основной программы}
Аналогично задачу, но уже с использованием функций, можно ре- шить так:
var |
x,y,m,n : |
integer; |
|
function MaxNumber(a,b: |
integer) : integer; |
||
var |
max: integer; |
|
|
begin |
{начало функции} |
||
if a>b then |
max := a |
else max := b; |
MaxNumber := max;
{имя функции получает значение результата целого типа}; end; {конец функции}
begin {начало основной программы} write('Введите х,у '); readln(x,y);
m := MaxNumber(x,y);
{в основной программе результат функции копируется в перемен- ную m};
n := MaxNumber(2, x+y);
writeln('m=',m,'n=',n);
end.
Рекурсивные подпрограммы. Рекурсия – это способ организации вычислительного процесса, при котором подпрограмма обращается сама к себе, но с более «простыми» параметрами (измененными). Пример вычис- ления факториала числа (N! = N (N-1)!) c рекурсивным вызовом функции:
program rec1;
function fact (n : word) : word;
begin if n = 0 then fact := 1 else fact := n * fact (n- 1); end;
begin
write(‘Введите число ‘); readln(n); write(‘ Фасториал чис- ла ‘,n,’равен: ‘,fact(n))
end.
57
В практических задачах глубина рекурсивных вызовов должна быть конечна и невелика. Большая глубина рекурсивных вызовов приводит к переполнению стека. Кроме того, подобно операторам цикла, рекурсив- ные вызовы могут приводить к «зацикливанию». Для того чтобы избежать этого, в теле процедуры или функции должно быть некоторое управляю- щее условие с ветвью не содержащей рекурсивный вызов. Эта ветвь будет определять ограничение рекурсии (граничное условие).
Рекурсивные процедуры эффективны при работе со сложными дина- мическими структурами данных: списками, деревьями, графами.
2.10.Работа с двумерными массивами
2.10.1.Действия над элементами массива
При работе с двумерным массивом указываются два индекса, напри- мер B[4,4]. Индексированные элементы массива называются индексными переменными и могут быть использованы так же, как и простые перемен- ные. Например, они могут находиться в выражениях в качестве операндов, использоваться в операторах for, while, repeat, входить в качестве па- раметров в операторы read, readln, write, writeln; им можно при- сваивать любые значения, соответствующие их типу.
Копированием массивов называется присвоение значений всех эле- ментов одного массива всем соответствующим элементам другого масси- ва. Копирование можно выполнить одним оператором присваивания, на- пример A:=B, если массивы идентичны по структуре, или с помощью оператора for поэлементно:
For i:=1 to 5 do
For j:=1 to 7 do
A[i,j]:=В[i,j];
2.10.2. Действия над идентичными двумерными массивами
Выражение |
Результат |
А=В |
True, если значение каждого элемента массива А равно со- |
|
ответствующему значению элемента массива В. |
А<>В |
True, если хотя бы одно значение элемента массива А не |
|
равно значению соответствующего элемента массива В. |
А:=В |
Все значения элементов В присваиваются соответствующим |
|
элементам массива А. Значения элементов массива В оста- |
|
ются неизменны. |
58
2.10.3. Использование процедуры ввода и процедуры вывода элементов двухмерного массива
program |
P_r_i_m_e_r_2; |
|
|
const M = 2; { Количество строк в массиве |
} |
||
|
N = |
3; { Количество столбцов в массиве } |
|
type |
T = Array [1..M,1..N] of Integer; |
|
|
var |
A : T; |
|
|
procedure Wwod_Mass |
(var S: T); |
|
{Процедура ввода с клавиатуры элементов массива }
{процедура с параметрами}
{S - параметр, вызываемый по адресу}
var i,j: Integer; begin
WriteLn ('Введите массив: ');
For i:=1 to M do
For j:=1 to N do
begin Write ('Введите S[',i,',',j, ']: '); ReadLn (S[i,j]) end
END;
procedure Wywod_Mass (S: |
T); |
|
|
{ Процедура |
вывода на |
экран элементов массива } |
|
{ процедура |
с параметрами |
} |
|
{ S - параметр, вызываемый по значению |
} |
||
var i,j: Integer; |
|
|
|
BEGIN |
|
|
|
WriteLn ('Вот Ваш массив: '); |
|
||
For i:=1 |
to M do |
|
|
begin |
For j:=1 |
to N do Write (S[i,j],' '); |
WriteLn end end;
BEGIN
Wwod_Mass (A);{Вызов процедуры ввода элементов массива} Wywod_Mass(A){Вызов процедуры вывода элементов массива}
end.
2.11. Файловый тип данных
Описание типа Var <имя файловой переменной>: file of <Имя базо- вого типа (типа элементов файла)>
Имя переменной файлового типа принято называть логическим именем файла. Именно это имя используется в программе при обращении к его элементам. Кроме того, у файла есть имя, под которым он фигурирует
59
в ОС, – физическое имя. Установление связи «логическое имя – физиче- ское имя» выполняется специальной процедурой (Assign). Одно логиче- ское имя можно связывать в разное время с разными физическими, а это означает, что программу можно написать так, что ее не надо будет переде- лывать при смене имени файла в ОС или при работе с другим файлом.
Операции с файлами реализуются обращением к стандартным про- цедурам:
Assign(F, Связывает логическое имя файла F с его физическим именем
FName) FName
Reset(F) Открывает файл F для ввода Rewrite(F) Открывает файл F для вывода Close(F) Закрывает файл F
Read(F,R) Чтение элемента файла F в переменную R Write(F,R) Запись элемента файла А из переменной R Eof(F) Возвращает булевское значение "Конец файла"
Eof(F) Возвращает булевское значение "Конец файла" для файла F Eoln(F) Возвращает булевское значение "Конец строки" для файла F
Рассмотрим пример, иллюстрирующий работу с текстовым файлом. Пусть требуется оценить объем текста рукописи, записанного на диск в так называемых издательских листах, которые вмещают по 40 000 символов. В программе реализуем идею подсчета общего количества символов в тек- сте рукописи, пока не дойдем до конца файла, а затем при выводе ответа накопленное количество поделим на 40 000.
program Rukopis; var FTxt: Text;
s: String; sum: LongInt;
begin
Write('Введите имя файла: '); Readln(s); Assign(FTxt, s); Reset(FTxt);
Sum := 0;
while not Eof(FTxt) do begin
Readln(FTxt, s); Inc(sum, Length(s));
end;
Close(FTxt);
WriteLn('Объем = ', sum/40000:6:2,' издат. листов'); end.
60