Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2771
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

3. Управляющие операторы языка

Вывод

/

/"Элемент /

/

/

1 / ненайдену'

X, у

а

 

б

Рис. 3.23. Варианты организации поискового цикла для реализации: д - с использованием процедуры break; б- структурный вариант

ходе ИЗ цикла, чтобы вывести сообщение о том, что элемент не найден, толь­ ко в том случае, если он действительно не найден (рис. 3.23, а)

Для построения структурного варианта алгоритма меняем вид цикла: вместо счетного цикла будем использовать цикл-до со сложным условием, объединяющим оба условия выхода. После выхода из цикла неизвестно, по какому из условий цикл завершился, поэтому в данном варианте алгоритма также приходится проверять, найден нужный элемент или нет (рис. 3.23, б). Рассмотрим соответствующие варианты программ.

Вариант с использованием о п е р а т о р а g o t o :

Program ex;

Var /, n:integer; x,y, a, b, h:real;

Label konec;

{объявляем метку}

Begin

 

Write(*Введите

a,b,h:');

Readln(a,b,h);

 

n:=round((b'a)/h-^I.5); {определяем количество элементов} x:=a;

for i:=l to n do begin

y:=sin(x);

71

Часть 1. Основы алгоритмизации и процедурное программирование

ify<0 then begin

WnteLn(y== \y:8:6,' при л:= \x:6:3);

goto копес; {управление передаем на конец программы по­ сле вывода сообщения о том, что элемент не найден}

end;

x:=x+h;

end;

WriteLnCЭлемент не найден,');

копес: {место, куда передается управление}

End

Вариант с использованием п р о ц е д у р ы break:

Program ex;

var in:integer; x,y,a,b,h:real; Begin

Write(*Введите a,b,h:'); Readln(a,b,h);

n:=round((b-a)/h-^J.5); {определяем количество элементов} x:=a;

for i:=l to n do begin

y:=sin(x); ify<0 then begin

WriteLn(y= ',y:8:6,' при x= \x:6:3);

break; {осуществляем досрочный выход из цикла} end;

end;

{место, куда будет передано управление при выполнении break} ify>-0 then WriteLn('Элемент не найден,');

End.

С т р у к т у р н ы й в а р и а н т :

Program ex;

var х,у, а, 6, h:real; Begin

WriteСВведите a,b,h: *); Readln(a,b,h);

x:=a'h; repeat

72

J. Управляющие операторы языка

x:=x+h; y:=-sm(x);

until (x+h>b) or (y<0); {комбинированное условие выхода из цикла} ify<0 then WnteLn(y= \ у:8:б, ' при л:=', х:6:3)

else WriteLn(*Элемент не найден. *);

End

Разрабатывая структурный вариант цикла, мы были вынуждены одно­ значно сформулировать условие выхода из цикла и точно определить при­ знак, по которому делается вывод о том, найдено ли решение. В то время как реализация «естественного» варианта алгоритма с использованием goto или break требует учета всех возможных последствий неструктурной передачи управления. Кроме того, при структурном варианте получена самая простая программа, что в соответствии с рекомендациями структурного программи­ рования существенно сокращает количество возможных ошибок.

Рассмотрим еще один пример, при разработке программы которо­ го теоретически можно использо­ вать оператор continue.

Пример 3.9. Разработать про­ грамму, которая должна вводить и суммировать 10 целых чисел, не превышающих 50. При вводе отри­ цательного числа она должна выда­ вать предупреждение, игнориро­ вать число и ожидать ввода пра­ вильного значения.

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

пользуем итерационный цикл,

 

конкретно цикл-пока. Алгоритм ре­

 

шения задачи представлен на

 

рис. 3.24. Этот алгоритм может

 

быть реализован с использованием

 

оператора goto, процедуры continue

 

или оператора ветвления if. По­

Рис. 3.24. Схема алгоритма определения

следний вариант является структур-

ным.

суммы 10 чисел, не превышающих 50

73

Часть I, Основы алгоритмизации и процедурное программирование

Рассмотрим эти варианты.

 

Вариант с использованием

о п е р а т о р а g o t o :

Program ex; Var i,s,a:integer;

Label cycl;

Begin i:=J; s:=0;

while i<=10 do begin

Read(a); ifa>50 then

begin

WriteLn('Число не должно превышать 50 *);

goto cycl; {передача управления на конец цикла} end;

s:=s-^a; {операторы, которые необходимо обойти}

cycl: end; WriteLn(s);

End

Вариант с использованием п р о ц е д у р ы c o n t i n u e :

Program ex; Uses crt;

Var i,s,a:integer; Begin

i:^l;

S:=0;

while i<=10 do begin Read(a); ifa>50 then

begin

WriteLn('Число не долэюно превышать 50*);

continue; {передаем управление на следующую итерацию} end;

s:^s^a; i:=i-^l;

end;

WriteLn(s); End

74

3, Управляющие операторы языка

С т р у к т у р н ы й в а р и а н т :

Program ex; Uses crt;

Var hs,a:integer; Begin

i:-l; S:^0;

while i<=10 do begin

Read(a); ifa>50 then

WriteLn('Число не должно превышать 50*)

else begin

s:=s-\ra; i:=^i+I;

end end;

WriteLn(s); End

Структурная реализация алгоритма в данном случае является самой про­ стой. Использование вариантов.с оператором goto и процедурой continue не целесообразно. Примен(ение continue в аналогичных ситуациях может быть оправдано только при большом количестве пропускаемых операторов.

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

Пример ЗЛО. Разработать программу, которая многократно вычисляет значение функции по вводимому пользователем значению аргумента. После выдачи результата программа должна спрашивать, нужно ли продолжить ра­ боту. Если необходимость продолжения работы существует, пользователь вводит «у», иначе - «п». Соответственно в первом случае работа с програм­ мой продолжается, а во втором - программа завершает работу.

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

75

Часть L Основы алгоритмизации и процедурное программирование

(

Начало

j

Ниже представлена реализация алгоритма

с ис­

пользованием цикла-до.

 

/ г /

 

Program ex;

 

Var x:real;ch:char;

 

Begin

 

 

Вывод

/

repeat

 

/

sin(x)

/

Write('Введите x: ');

 

 

 

ReadLn(x); {ни в коем случае не Read, так как

/иродолжитьУ

далее идет ввод символа (см. параграф 2.6)}

/

у^"

/

WriteLn(*Результат \ sin(x):8:4);

 

 

 

 

 

/

Ввод

7

WriteLn(*Пpoдoлэ^cumь? (у/п)

*);

/__t—/

ReadLn(ch);

 

until ch= *п V

 

End.

Окончательно можно сделать следующие выводы.

 

1. Оператор безусловной передачи управления

 

goto в программах на Borland Pascal желательно вооб­

Рис. 3.25. Схема

ще не использовать. Если у вас получился неструктур­

ный алгоритм, при реализации требующий goto, по­

алгоритма

пробуйте преобразовать его в структурный. Такое ог­

вычисления

раничение связано с тем, что использование goto, как

значения функции

правило, приводит к появлению в программе большо­

 

го количества ошибок [3, 4, 9].

2. Процедуры неструктурной передачи управления break и continue мо­ гут быть полезны, однако при их использовании необходимо четко представ­ лять себе, куда будет передано управление. Цикл, в котором использованы эти процедуры - это место повышенной вероятности наличия ошибок. Он должен специально тестироваться.

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

Задания для самопроверки

Задание 1. Разработайте профамму, которая определяет сумму первых трех отрицательных чисел последовательности значений, рассчитанных по формуле у^ = = X - sin X при заданных диапазоне [а,Ь] изменения х и шаге h.

Задание 2, Разработайте программу, которая строит таблицу значений функции у = (in х) / tg X при заданных диапазоне [а, Ь] изменения х и шаге h. Если значение функции в очередной точке не существует, то в соответствующей строке таблицы выведите сообщение «значение не существует».

76

4. СТРУКТУРНЫЕ ТИПЫ ДАННЫХ

Достаточно часто возникает необходимость программирования обработки одно­ типных данных: таблиц, текстов, множеств и т.д. Для их представления используют структурные типы данных. В Borland Pascal определены следующие структурные типы данных:

массивы - для представления однотипных или табличных данных;

строки-для представления символьной (текстовой) информации;

множества - для представления абстрактных математических множеств;

записи - для представления таблиц с данными различных типов.

4.1. Массивы

Массив - это упорядоченная совокупность однотипных данных. Каждо­ му элементу массива соответствует один или несколько индексов^ определя­ ющих положение элемента в массиве. Индексы образуют упорядоченные по­ следовательности. Синтаксическая диаграмма объявления массива представ­ лена на рис. 4.1.

Тип индекса определяет его допустимые значения. В качестве типа ин­ декса может быть указан любой порядковый тип (boolean, char, integer, пере­ числяемый тип, а также диапазоны этих типов), кроме типа longint и его про­ изводных.

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

<^>0гС&ОЧНЯ Тип

элемента

Рис. 4.1. Синтаксическая диаграмма <Объявление массива>

77

Часть I. Основы алгоритмизации и процедурное программирование

 

ГЗ" 0

12

54

-8 1

 

 

 

 

 

 

 

 

 

 

-5

-4

-3

 

 

 

 

 

А

-5

0

"ii'l

ГА"

N D

0

R

т

В

46

83

[Т]

С

54

0

"93]

О

1

 

 

255

 

 

 

 

б

Рис. 4.2. Одномерный массив из 5 целых чисел (л), одномерный массив из 256 символов (б), матрица из 9 чисел (в)

Тип элементов массива - любой допустимый в Borland Pascal тип (в том числе и массив), кроме файла..

Объявление переменных типа массив выполняется двумя способами:

• в операторе объявления переменных, например:

Var a:array[L.10] of integer; {массив из 5 целых чисел, см. рис. 4.2, а) Ь:array[byte] of char; {массив из 256 символов, индекс элемента

массива изменяется от О до 255, см. рис. 4.2, 6} с:аггау['А\, 'C\-5„'3J of byte; {матрица из 9 чисел, см. рис. 4.2, в} d:array[*А\. V*] of array[-5..-3] of byte; {матрица из 9 чисел, по

структуре эквивалентная предыдущей}

• с предварительным объявлением типа, например:

Туре mas=array[l.JO] ofinteger; {объявляем тип}

Var a:mas; {объявляем переменную}

Ограничения на количество индексов в Borland Pascal нет. Однако сум­ марная длина массива не должна превышать 65537 байт.

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

Инициализация массивов. Для объявления инициализированных мас­ сивов в Borland Pascal используют типизированные константы. При этом со­ ответствующие значения указывают в скобках через запятую. Значения эле­ ментов многомерных массивов перечисляют в порядке возрастания индексов

78

4, Структурные типы данных

справа налево, заключая в скобки каждый подмассив. Для матриц такой по­ рядок соответствует построчному указанию значений. Например:

Const а: arrayfl..5Jo/real = (0,-3,6,7.8,3.789,5.0);

b: arrayfboolean, L.5,]ofreal = ((0,-3.6,7.8,3.789,5.0), (6.1,0,-4.56,8.9,3.0));

{массив будет инициализирован следующим образом:

Ь false,! " О' bfaise,2= "3.6, bfaise,3 = 7.8, ..., b ^^ue,! = 6.1, и Т.д.}

c:array[1..3,0..1,-2..1]ofbyte = (((3,6,9,6),(0,4,3,9)),

((5,7,3,1),(45,8,0,2)), ((5,9,2,3),(1,5,8,4)));...

Операции над массивами. Над массивом в целом определена единст­ венная операция ~ операция присваивания.

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

Массивы считаются совпадающими по типу, если они объявлены через запятую в одной строке, например:

Var а, Ь:array[boolean] ofreal;

... a:-b;...

или, если вначале объявлен тип массива, а затем массивы этого типа:

Туре mas=аггау[boolean] ofreal; Const a:mas=(3.6, -5.1);

Var b:mas;

... b-a;...

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

Vara:array[char,boolean]ofreal; {объявляем матрицу}

... a[^A\true]:=5.1;... {присваиваем значение элементу адд^ц^}

Значения индексов можно указать непосредственно литералом, напри­ мер а[3], или косвенно, указав идентификатор переменной, которая содержит, значение индекса, например a[i] (рис. 4.3).

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

79

Часть I. Основы алгоритмизации и процедурное программирование

а 1

2

3

4

5

6

а 1

2

3

4

5

6

1 3.5

-5.1

0

8.4

-0.3

4.9

3.5

-5.1

0

8.4

|-0.3

1 ^^

 

 

 

 

 

 

 

 

 

 

i

 

а[3]

 

 

 

 

 

a[i]

-

 

 

^Ъ \

 

 

 

 

 

 

 

 

 

 

 

Рис. 4.3. Прямая (а) и косвенная (б) адресация элементов массива

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

Var a:array[L.6] of integer;...

for /V=7 to б do a[i]:=i;... {при i=l a| присваивается 1, при i=2 a2 присваивается 2

при i=3 аз присваивается З'и т.д.}

Количество переменных, необходимых для косвенной адресации масси­ вов, совпадает с размерностью массива. Так, для работы с матрицами ис­ пользуют две переменные, хранящие индексы: одну-для хранения номеров строк, а вторую - номеров столбцов.

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

Туре mas=array[boolean] of real; {массив из двух вещественных чисел}

Const a:array[L.2]ofmas^((3.6,-5,l),(7.0,-4.2)); {матрица из четырех вещественных чисел}

Var b:mas;

Begin b:=a[IJ;... {в массив b скопирована первая строка матрицы а}

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

Var a:array[L.5] of real; Begin

for i:-l to 5 do Read(afiJ); {осуществляем ввод массива}

ReadLn; {очищаем буфер ввода, чтобы далее значения вводились со следующей строки (см. параграф 2.6)}

Значения элементов массива вводят в порядке обращения к ним из цик­ ла, например для цикла, показанного выше: а|, а2, аз, а4, азЭти значения мо­ гут задаваться в одной строке через пробел или с нажатием клавиши Enter после ввода одного или нескольких чисел.

80