Алгоритмическое (модульное) программирование

Алгоритмическое (модульное) программирование: Информатика: Базовый курс, Сергей Витальевич Симонович, 2003 читать онлайн, скачать pdf, djvu, fb2 скачать на телефон Рассмотрены основные категории аппаратных и программных средств вычислитель-ной техники. Указаны базовые принципы построения архитектур вычислительных систем. Обеспечено методическое обоснование процессов взаимодействия информации, данных и методов.

Алгоритмическое (модульное) программирование

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

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

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

Переменные и константы

Реальные данные, с которыми работает программа, — это числа, строки и логические величины (аналоги 1 и 0, «да» и «нет», «истина» и «ложь»). Эти типы данных называют базовыми.

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

Hello

_SumOfReal

xl

H8_G7_F6

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

Кроме имени и значения, переменная обычно имеет тип, определяющий, какая информация хранится в данной переменной (число, строка и т. д.). В зависимости от объема памяти, отведенного для хранения значения переменной, оно должно укладываться в допустимый диапазон. Например, значение типа «байт» имеет диапазон от 0 до 255.

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

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

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

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

123

2.87

"это строка"

или для удобства обозначать их идентификаторами. Например, число я, равное 3,1416, можно обозначить как pi и везде вместо числа применять идентификатор. Только изменять значение pi нельзя, так как это не переменная, а константа.

Числовые данные

Числа обычно бывают двух видов: целые и дробные. Если число отрицательное, перед ним ставится знак «-», если положительное, то знак «+» можно ставить, а можно и опускать. Вычисления над целыми числами выполняются точно, вычисления над дробными числами — приближенно. При записи дробных чисел в качестве десятичного разделителя используется точка:

1.28

3.333321

Очень большие или очень маленькие числа записываются специальным образом. Для них дополнительно указывается мантисса — число со знаком, являющееся степенью числа 10. Мантисса записывается справа от числа через букву е (или Е). Пробелы в такой записи не допускаются.

Например, число 100 (единица, умноженная на 10 во второй степени) запишется так:

1е+2

число 0,003 (тройка, умноженная на 10 в минус третьей степени) так:

Зе-3

число со 120 нулями — так:

1Е+120

Допускается дробная запись числа с мантиссой:

31.4е-1

Тип числа

Бейсик

Паскаль

Си++

целое

INTEGER

integer

int

дробное

DOUBLE

real

float

Арифметические операции

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

К основным арифметическим операциям относятся:

+ (сложение)

- (вычитание)

* (умножение)

/ (деление)

Такая форма записи отвечает общепринятым соглашениям и принята в большинстве языков программирования.

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

b*2 + с/3

b* (2 + с) 3

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

( (у+2)*3 + 1) / 2

Арифметические выражения

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

Выражение

i1 + 2

состоит из одной операции «+» и двух операндов — переменной И и числовой константы 2.

Каждое выражение имеет значение, которое определяется в момент выполнения оператора, содержащего это выражение. Если на момент вычисления выражения i1+2 в переменной i1 хранится число 3, то значение этого выражения будет равно 5 (3+2).

Логические выражения

При создании программ не обойтись без логических выражений. Они отличаются тем, что результат их вычислений может принимать только одно из двух допустимых значений — true (истина, да, включено) и false (ложь, нет, выключено). Чаще всего значение false ассоциируется с нулем, а значение true — с числом 1 или просто ненулевым значением.

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

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

Операция

Варианты написания

Бейсик, Паскаль

Си++

Равно

=

==

Не равно

<>

!=

Меньше

<

<

Меньше или равно

<=

<=

Больше

>

>

Больше или равно

>=

>=

Pi == 3.14

х > 0 al <> b1

В одном выражении может потребоваться проверка нескольких подобных условий. Например, надо определить, больше ли значение переменной X чем 0 и меньше ли чем 10. Условия могут быть связаны с помощью логических операций, наиболее активно используемые из которых — это И и ИЛИ. В компьютерной графике также часто применяется так называемое исключающее ИЛИ и операция отрицания НЕ. Для нее требуется только один операнд, указывающийся справа от знака операции. Эта операция просто меняет значение своего операнда на противоположное.

1 операнд

2 операнд

И

ИЛИ

исключающее ИЛИ

HE (только первый операнд)

true

true

true

true

false

false

true

false

false

true

true

false

false

true

false

true

true

true

false

false

false

false

false

true

В следующей таблице приведен синтаксис записи логических операций.

Логическая операция

Бейсик

Паскаль

Си++

И

AND

and

&&

ИЛИ

OR

or

II

НЕ

NOT

not

!

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

Примеры логических выражений:

x1 >= 1 && x1 <= 10

(R > 3.14) and (R < 3.149)

(Value < Oldvalue) OR (Value <> 0)

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

Бейсик

Паскаль

Си++

Базового типа нет. Используется числовой тип INTEGER

boolean

bool

Строчные выражения

Строки в языках программирования всегда заключаются в кавычки. В Си++ и Бейсике для этого используются двойные кавычки, в Паскале — одинарные.

"это строка Бейсика или Си++"

'это строка Паскаля'

Строка может быть пустой — не содержать ни одного символа. Например:

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

Кроме того, часто допускается также операция сцепления строк, записываемая с помощью символа «+». Например:

"123" + "4567" -получится "1234567"

"абв " + "abc " + " эюя" —получится "абв abc эюя"

Тип «строка»

Бейсик

Паскаль

Си++

STRING

string

Базового типа «строка» нет

Указатели

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

Сложные данные

Структуры. До сих пор рассматривались базовые типы данных: числа, строки, логические величины — и операции над базовыми данными. Однако для повышения производительности труда программистов и повышения качества их работы необходимо, чтобы язык программирования имел средства, позволяющие описывать данные в виде, максимально приближенном к их реальным аналогам. Например, чтобы организовать обработку данных по студентам, в программе удобно не просто описать десяток различных переменных, а объединить их в структуру (или запись) «студент», состоящую из полей разного типа «имя», «пол», «год рождения», «группа» и т. д.

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

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

Синтаксис описания структуры

Бейсик

Паскаль

Си++

TYPE имя-структуры поле AS тип

END TYPE

record поле: тип;

end;

struct имя

{

тип поле;

};

Вот примеры описания структур.

Бейсик:

TYPE Student

Name AS STRING

Sex AS INTEGER

BirthYear AS INTEGER

END TYPE

Паскаль:

record

Name: string;

Sex: boolean;

BirthYear: integer;

end;

Си++:

struct Student {

bool Sex; int BirthYear; };

Доступ к содержимому структуры: Student.BirthYear = 1980;

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

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

Синтаксис описания массива

Бейсик

DIM имя (число элементов) AS тип

Паскаль

аггау[ нижняя_граница .. верхняя_граница ] of тип;

Си++

тип имя[ число-элементов ];

В Бейсике нижней границей считается 1, в Си++ — 0, в Паскале она указывается явно.

Вот примеры описания массивов.

Бейсик:

DIM IntArray(lOOO) AS INTEGER

Паскаль:

array[1..1000] of integer

Си++:

int IntArray[1000];

Доступ к элементу массива осуществляется по его номеру. Этот номер указывается в круглых (Бейсик) или квадратных (Паскаль, Си++) скобках сразу за именем массива (такое действие называется индексированием):

IntArray( 12 ) IntArray[ i+1 ]

Массивы, границы которых явно заданы в команде описания, называются статическими. Их размер известен заранее и не меняется на всем протяжении работы программы.

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

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

Правила работы со сложными типами

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

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

а[0].Items.Strings[4].value

Массив а состоит из структур, в описании которых есть поле Items, являющееся тоже структурой, имеющей поле Strings, которое, в свою очередь, представляет собой массив структур, имеющих поле value.

Описание переменных

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

Синтаксис команд описания данных

Бейсик

Паскаль

Си++

DIM имя AS тип

var имя: тип;

тип имя;

Вот примеры описания переменных.

Бейсик:

DIM X AS DOUBLE

Паскаль:

var x: real; var Str: record

PI: integer;

S: string;

end;

Си++:

float x; int a[20] ;

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

Паскаль:

var xx, z2: integer; Си++:

int xx, yy[10], z2;

Новые типы данных

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

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

Синтаксис описания нового типа

Бейсик

Паскаль

Си++

Аналогичен описанию структуры, которое уже является описанием нового типа

type имя = описание;

typedef struct имя-структуры

{

поля-структуры;

} имя;

Имя структуры надо указывать только из-за требований синтаксиса. Реально оно

нигде не применяется

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

Паскаль:

type TMyArray = array[0..99] of integer;

type TMyRecord = record

Iteml: integer;

Item2: string;

end;

var MyArray: TMyArray;

var R: TMyRecord;

Си++:

typedef struct namel

{

int i;

float x;

} TNewStruct;

TNewStruct NewStruct

Разделение операторов

Если записать подряд несколько операторов и не указать, где кончается один и начинается другой, то в процессе компиляции возникнет множество проблем с выделением отдельных операторов. Поэтому операторы в Паскале и Си++ отделяются друг от друга точкой с запятой «;» (каждый оператор в этих языках должен заканчиваться таким символом), а в Бейсике — двоеточием «> или переходом на новую строку.

Блок операторов

Часто в программе возникает необходимость выполнить группу операторов (например, в зависимости от какого-либо условия). Такая группа объединяется в блок с помощью специальных скобок начала и конца блока, называемых логическими скобками.

В Бейсике явного понятия «блок операторов» нет, в Паскале для этого используются ключевые слова begin и end, а в Си++ — фигурные скобки «{» и «}».

Область действия переменных

Команды описания переменных могут встречаться в разных местах программы. При этом считается, что объявленные в них переменные являются локальными и их область действия — текущий блок, в котором они описаны. Как только встречается логическая скобка, закрывающая блок (например,«}»), соответствующая переменная перестает существовать, а выделенная для нее память освобождается.

Некоторые переменные описываются вне блоков и доступны из любого места программы.

Оператор присваивания

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

Сам оператор присваивания записывается знаком «=» в Бейсике и Си++ и комбинацией двух знаков «:=» в Паскале (пробел между ними не допускается).

Например:

Result = 5

В переменную Result запишется число 5. Знак «=» означает именно присваивание, а не сравнение, которое может использоваться только в логических выражениях.

Другой пример:

X = X + 1

Сначала вычисляется значение выражения Х+1, и затем оно заносится в переменную X. Допустима и такая запись:

X = X = X

Прежде всего выполняется сравнение в правой части (X = X), его значение всегда будет true, и значением переменной X, соответственно, тоже станет true. Для повышения наглядности оператора присваивания в Паскале принята специальная форма его записи:

X. := X = X

Примеры.

Бейсик:

а23 = а22(12) + 1: b1 = b1 1

Паскаль:

а := b*2 + с; d := (е[8] f)*2.2;

Си++:

х[5] = у/3.33; у = z[0] 0.001;

Комментарии

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

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

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

Синтаксис комментария

Бейсик

Паскаль

Си++

Однострочный комментарий

REM или '

II

//

Многострочный комментарий

нет

{ } или (* *)

/**/

X = 5 'комментарий до конца строки

X : = 5; // комментарий до конца строки

/*

это комментарий

языка Си++

*/

{

это комментарий

языка Паскаль

(* а это вложенный комментарий *)

}

Условный оператор (условные вычисления)

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

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

если условие истинно

то выполнить оператор-1

иначе выполнить оператор-2

После ключевого слова IF (если) следует условие, и если оно истинно, то выполняется оператор или блок операторов, следующих за ключевым словом THEN (mo), если же оно ложно, то выполняется оператор или блок операторов, следующих за ключевым словом ELSE (иначе).

Синтаксис условного оператора

Бейсик

Паскаль

Си++

IF условие THEN

оператор1

ELSE

оператор-2 END IF

if условие then

оператор1

else

оператор-2;

if( условие )

оператор1

else

оператор-2;

Примеры.

Бейсик:

IF А < > THEN

А = О

ELSE

А = -1

END IF

Паскаль:

if а <> 0 then a := О

 else a := -1;

Си++:

if(

Информатика: Базовый курс

Информатика: Базовый курс

Обсуждение Информатика: Базовый курс

Комментарии, рецензии и отзывы

Алгоритмическое (модульное) программирование: Информатика: Базовый курс, Сергей Витальевич Симонович, 2003 читать онлайн, скачать pdf, djvu, fb2 скачать на телефон Рассмотрены основные категории аппаратных и программных средств вычислитель-ной техники. Указаны базовые принципы построения архитектур вычислительных систем. Обеспечено методическое обоснование процессов взаимодействия информации, данных и методов.