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

[ Миронченко ] Императивное и объектно-ориентированное програмирование на Turbo Pascal и Delphi

.pdf
Скачиваний:
68
Добавлен:
25.04.2014
Размер:
3.16 Mб
Скачать

11

Благодарности

Прежде всего я благодарю моих родителей за терпение и уважение к моему труду, за справедливую критику и за дизайн обложки. Благодарю доцента кафедры математического обеспечения компьютерных систем ОНУ им. И.И. Мечникова Мазурка Игоря Евгеньевича, который прочитал рукопись книги и сделал ряд важных замечаний по её тексту. Его работа позволила улучшить изложение некоторых тем. Неоценимую помощь оказал мой друг Владимир Сергиевский, который дважды прочитал рукопись книги и дал множество советов, улучшивших содержание многих глав. Обмен мнениями с Володей позволил избавиться от однобокости освещения некоторых разделов.

12

 

 

 

 

Список условных обозначений

 

 

 

 

x A

элемент x принадлежит множеству A

x A

элемент x не принадлежит множеству A

A U B

объединение множеств A и B

A I B

пересечение множеств A и B

A B

A является подмножеством B

A / B

разность множеств A и B

aMb

a делится на b

/

 

a не делится на b

a M b

A B

выражение A верно тогда и только тогда, когда верно выражение B

A B

из A следует B

N

множество натуральных чисел

Z

множество целых чисел

Q

множество рациональных чисел

R

множество вещественных чисел

C

множество комплексных чисел

(!)

 

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

:

 

такое, что

 

существует (например: а Z существует целое число а ).

 

для любого (например: x R x2 0 для любого вещественного числа

 

 

 

x следует, что x2 0 ).

 

 

 

i пробегает целые числа от 1 до n

i = 1, n

 

 

 

l

ak

+ ak +1 + ... + al

ai

 

 

i =k

 

 

 

 

 

l

ak

ak +1 ... al

ai

 

 

i =k

13

Часть I Императивное программирование

Глава 0: Программистское введение

Первые программы мы начнем писать во второй главе. Но прежде мы должны ответить на ряд фундаментальных вопросов:

1.Что такое языки программирования и какими они бывают?

2.Как компьютер понимает, что написано в программном коде?

3.Где находится программа во время выполнения?

Введем несколько базовых определений:

Программирование – написание программ.

Алгоритм – упорядоченная последовательность действий.

Программный код – запись алгоритма на каком-то языке (не обязательно языке программирования).

Под программой будем временно понимать последовательность действий, которые должен выполнить персональный компьютер (ПК), чтобы реализовать некоторый алгоритм. Более точное определение программы будет дано позже в этой главе.

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

0.1. Какие бывают языки программирования

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

Программа на С++

#include <iostream> using namespace std;

void main()

{

int n;

cout<<"Enter quantity of numbers"<<endl; cin>>n;

14

int F1=1; int F2=1; int F3;

cout<<"The fibonacci's numbers"<<endl; cout<<1<<endl<<1<<endl;

for (int i=1;i<=n-2;i++)

{

F3=F1+F2;

F1=F2;

F2=F3;

cout<<F3<<endl;

}

}

Программа на Turbo Pascal

var i,F1,F2,F3,n:integer;

begin

writeln('Enter the quantity of numbers'); readln(n);

F1:=1;

F2:=1;

writeln('Fibonacci''s numbers'); writeln(F1);

writeln(F2);

for i:=1 to n-2 do begin

F3:=F1+F2;

F1:=F2;

F2:=F3;

writeln(F3);

end;

end.

Программа на машинном языке

10000

2

0000

40*(??)

3

0040

 

4

 

 

50000

6

0000

45

6E

74

65

72

20 51+

7

 

75

61

6E

74

69

74 79+

8

 

20

6F

66

20

6E

75 6D+

962 65 72 73 0D 0A 24

10001C 46 69 62 6F 6E 61 63+

1163 69 20 6E 75 6D 62+

1265 72 73 0D 0A 24

130030

14

15 0000

16

15

17

18

190000

200000 B8 0000s

210003 8E D8

230005 B4 09

240007 BA 0000r

25000A CD 21

27000C E8 0000e

28000F 8B C8

290011 B4 09

300013 BA 001Cr

310016 CD 21

330018 83 E9 02

34001B B8 0001

35001E E8 0000e

360021 B8 0001

370024 E8 0000e

380027 BB 0001

39002A BA 0001

41002D 8B C2

42002F 03 C3

430031 53 52 50

440034 E8 0000e

450037 58 5A 5B

47003A 8B DA

48003C 8B D0

49003E E2 ED

510040 B8 4C00

520043 CD 21

530045 CB

540046

550046

Программа на Prolog

predicates fibo(integer)

fibo(integer,integer,integer) clauses

fibo(FN):-write(1),nl,FN>1,write(1),nl,FN>2,N=FN-2,fibo(1,1,N). fibo(_,_,0):-!. fibo(F1,F2,N):-F3=F1+F2,write(F3),nl,NN=N-1,fibo(F2,F3,NN). goal write("Enter quantity of numbers"),nl,readint(X),

write("Fibonacci's numbers"),nl,fibo(X).

16

Программа на Java import javax.swing.JOptionPane;

public class Fibojava {

public static void main (String args[]){ String Numm;

Numm=JOptionPane.showInputDialog("Enter quantity of numbers"); int n=Integer.parseInt(Numm);

int F1=1; int F2=1; int F3;

System.out.println("The fibonacci's numbers"); System.out.println(1+"\n"+1);

for (int i=1;i<=n-2;i++)

{

F3=F1+F2;

F1=F2;

F2=F3;

System.out.println(F3);

}

}

}

Программа на LISP

(defun Fibo (f1 f2 n) (when (> n 0)

(print f1)

(Fibo f2 (+ f1 f2) (- n 1))

)

)

(Fibo 1 1 10)

 

 

Программа на Assembler

STK

SEGMENT

STACK

DB

64 DUP(?)

 

STK

ENDS

 

DATA SEGMENT

MES DB 'Enter Quantity of numbers',13,10,'$' MES2 DB 'Fibonacci numbers',13,10,'$'

DATA ENDS

CODE SEGMENT

ASSUME CS:code, DS:data, SS:stk extrn read:near

extrn write:near START proc far

mov ax,data mov ds, ax

17

 

mov

ah,9

 

mov

dx,OFFSET Mes

 

int 21h

 

call read

 

mov cx,ax

 

 

mov

ah,9

 

mov

dx,OFFSET Mes2

 

int 21h

 

sub cx,2

 

mov ax,1

 

call write

 

mov ax,1

 

call write

 

mov bx,1

 

mov dx,1

 

fiba:

mov ax,dx

add ax,bx push bx dx ax call write pop ax dx bx

mov bx,dx mov dx,ax loop fiba

mov ax,4c00h int 21h

ret start endp CODE ENDS END Start

Все программы делают одни и те же действия: печатают все числа Фибоначчи (эти числа описаны в главе 1) до номера, который вводит пользователь (либо до заранее заданного числа).

Большинство ребят, с которыми я занимался программированием, разбили языки на 5 групп:

1.Машинный язык

2.C++, Turbo Pascal, Java

3.Prolog

4.LISP

5.Assembler

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

18

0.2. Устройство ПК

МОЗГ

ЦП

Биохимические сигналы

Физические сигналы

Органы

Устройства

Рис 0.1: Сравнение работы организма животного и ПК

Давайте сравним ПК с организмом животного. Прежде, чем двинуть рукой, мозг вырабатывает множество нервных импульсов, а в кровь поступают определенные гормоны, которые дают указания клеткам тела, что и как им надо делать. То же самое происходит и в компьютере, только вместо биохимических процессов в его «теле» действуют физические: «мозг» компьютера, - его центральный процессор (ЦП), обменивается электрическими сигналами со своими «органами» (различными устройствами – монитором, принтером и т.д.), т.е. дает им некоторые команды.

Программа представляет собой последовательность элементарных (неделимых) команд процессора.

Нас будут интересовать прежде всего 2 «органа» компьютера: процессор и память.

Память – устройство для хранения информации.

В современных компьютерах память состоит из набора битов.

Бит – единица памяти, которая может находиться лишь в двух состояниях. Эти состояния мы будем в дальнейшем отождествлять с цифрами 0, 1.

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

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

Минимальной адресуемой единицей памяти является байт (8 битов). У каждого байта есть свой номер и у разных байтов номера не могут совпадать.

Также используются следующие единицы количества информации:

1Кб (килобайт) = 210 байт

1Мб (мегабайт) = 210 Кб

1Гб (гигабайт) = 210 Мб

1Тб (терабайт) = 210 Гб

Память компьютера можно разбить на несколько уровней (см. рис. 0.2). Скорость обмена информацией между процессором и памятью полностью

регулируется физическими законами. Электрический сигнал, как и любой другой, не

может двигаться быстрее скорости света (в вакууме 300000 км = 3 1010 см = 30 см ),

с с нс

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

19

Среднее время доступа

 

 

 

 

 

Средний объем

~ 1 нс

 

 

 

<1 Кбайт

 

Регистровая память

 

~ 2 нс

 

 

 

1 Мбайт

 

Кэш-память

 

 

~ 10 нс

 

 

 

 

 

0,1-4 Гбайт

 

 

Оперативная память

 

 

 

 

 

 

 

 

 

~ 10 мс

 

 

 

Жесткий диск

80 Гб -1 Тб

 

 

 

 

 

 

 

 

 

Рис 0.2 Структура памяти компьютера

Регистровая память находится в самом процессоре, поэтому доступ к ней наиболее быстрый. Кэш находится в непосредственной близости к процессору, поэтому обмен информацией также осуществляется довольно быстро. Оперативная память (ОП) находится дальше кэша, поэтому работа с ней ведется еще медленнее. То, что работа с жестким диском (ЖД) ведется намного медленнее, чем с ОП, зависит не от того, где он находится, а от структуры ЖД.

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

Значения, которые были записаны в регистрах, кэше и ОП при выключении компьютера стираются (вследствие технического строения этой памяти). Поэтому без жестких дисков, Flash-памяти или CD/DVD или других носителей информации, на которых можно записывать данные на долгое время, обойтись нельзя. Но почему не убрать, скажем, ОП, и вместо этого сделать огромный кэш? Ответ прост: 1 Мб кэша стоит на порядок дороже, чем 1 Мб ОП. Регистровая память стоит примерно в 10 раз дороже, чем кэш. Именно поэтому придерживаются такой многоуровневой структуры памяти (сейчас кэш тоже состоит из нескольких уровней, причем чем дальше уровень от ЦП, тем больше он по объему памяти и дешевле по стоимости).

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

Впервых компьютерах в оперативной памяти хранились только данные. Хранить

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

20

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

Теперь мы можем ввести важнейшее определение:

Программа – последовательность элементарных (неделимых) команд на машинном языке.

0.3. Классификация языков программирования

На заре развития компьютерных технологий программы писались только на машинном языке. Вы видели, что внешне такая программа представляет собой набор чисел, записанных в 16-ричной системе счисления (ее мы рассмотрим в главе 1). Разумеется, писать такие программы было очень утомительно, и заниматься этим могли лишь большие энтузиасты.

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

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

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