
- •Введение
- •1. Краткая история технологии программирования
- •2. Некоторые аспекты технологии программирования и внедрения по.
- •3. Технологические процессы и жизненный цикл программного обеспечения.
- •4. Блок-схемы и алгоритмы, программы и подпрограммы.
- •Как всё это выглядит на языках программирования.
- •5. Данные.
- •7. К вопросу технологических скачков в программировании.
- •8. Отладка.
- •9. Документация и отладка.
- •Список литературы
- •Содержание
Как всё это выглядит на языках программирования.
В Cи любая программа рассматривается как функция. При этом программа может вернуть только одно значение, а входные параметры передаются по значению. Массив вернуть невозможно, но структуру можно, причём по значению. Это приводит к некоторым нелогичностям, так как в структуру могут входить массив и прочие агрегаты. Для вызова подпрограммы достаточно указать имя её, а в списке параметров перечислить передаваемые переменные.
Например: MyFunction (A, Bd, 5, “ передача параметров”); или NoPara();
или, если функция возвращала значение: u = RetFunc (Clv);
функции, возвращающие значения можно использовать в вычислительных выражениях: X = RetFunc(Clv) + 10;
А.Я. Архангельский [2] обращает наше внимание на различие между Cи и Cи++. Если в Cи вы указываете пустой список параметров, то это означает, что проверки аргументов нет. В Cи++ пустой список параметров указывает на отсутствие аргументов.
массивы передаются по адресу или как теперь принято говорить по ссылке:
double A[34][34]; TransMatr (A); - то есть имя массива используется как указатель! А TransMatr должна быть описана как void TransMatr (double * * A); Это приводит к несколько неуклюжему синтаксису при работе со строками. Пример:
int strcmp(char * A, char * B); так может быть описана программа сравнения двух строк, а обращаться к ней можно
if (strcmp(“ первая строка “, “ вторая строка “)) ……… или
if (strcmp(A, B)) ……
Однако в Cи можно передать параметры и по ссылке:
Пусть подпрограмма описана как: void Ut (int * d, char * G);
Тогда обращаться к ней можно следующим образом Ut (&f, “ список “);
где f ::= int. & - операция взятия адреса.
В Cи++ существует аппарат передачи параметров по ссылке.
Вам можно описать функция следующим образом:
void Fun (int & D, double & F); & перед именами переменными указывает, что на вход передаются адресные ссылки на переменные. Транслятор, принимая такое описание функции, будет строить передачу параметров в неё по ссылке. При обращении к такой функции не надо выполнять операцию получения адреса переменной, а требуется просто указать имена переменных: Fun (Ha, Da);
Если необходимо передать переменное число параметров, то функция описывается следующим образом (например):
int DF (список постоянных параметров, …);
Все постоянные параметры обязательно предшествуют переменным. В объявлении функции необходимо указывать именно три точки, иначе транслятор выдаёт ошибку.
Возникает вопрос, каким образом обратиться к переменным параметрам, если в функции неизвестно имя и тип входного параметра.
В файле stdarg.h определён тип списка va_list и три макроса: va_start, va_arg и va_end.
Объявляем переменную типа va_list: va_list lp;
Макросом va_start начинаем работу со списком. Им мы указываем последний обязательный аргумент: va_start(lp, last_Argument);
Далее последовательно обращаемся к va_arg, которая нам возвращает аргумент и устанавливает указатель на следующий аргумент: va_arg(lp, тип)
S = va_arg(lp, double);
Мы сами так или иначе должны считать аргументы и следить за их типами. Тип, указываемый в списке аргументов, фактически, указывает тип переменной, которой присваивается значение.
Завершаем работу вызовом va_end(lp);
Пример программы:
/* передача в функцию переменного числа параметров.
Гатин Г.Н. 10.10.2002г. */
#include <vcl.h>
#pragma hdrstop
#include "Tu101022.h"
//-----------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
void TestVari (double & S, int & Si, int N, ...);
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
double Su;
int sI;
TestVari (Su, sI, 3, 1.1, 2, 3.3);
MessageDlg (" полученные суммы: "+FloatToStr(Su)+" "+IntToStr(sI), mtInformation, TMsgDlgButtons() << mbOK, NULL);
TestVari (Su, sI, 3, 1, 2.2, 3);
MessageDlg (" полученные суммы: "+FloatToStr(Su)+" "+IntToStr(sI), mtInformation, TMsgDlgButtons() << mbOK, NULL);
TestVari (Su, sI, 5, 1.1, 2, 3.3, 4, 5.5);
MessageDlg (" полученные суммы: "+FloatToStr(Su)+" "+IntToStr(sI), mtInformation, TMsgDlgButtons() << mbOK, NULL);
TestVari (Su, sI, 1, 1.1);
MessageDlg (" полученные суммы: "+FloatToStr(Su)+" "+IntToStr(sI), mtInformation, TMsgDlgButtons() << mbOK, NULL);
TestVari (Su, sI, 0);
MessageDlg (" полученные суммы: "+FloatToStr(Su)+" "+IntToStr(sI), mtInformation, TMsgDlgButtons() << mbOK, NULL);
Application -> Terminate();
}
//-----------------------------------------------------------------void TestVari (double & S, int & Si, int N, ...)
{
va_list lipa;
double p;
int v, i;
S = 0; Si = 0;
va_start(lipa, N);
for (i = 0; i < N; i++)
if (i%2 != 0) { v = va_arg (lipa, int);
Si += v;
}
else { p = va_arg (lipa, double);
S += p;
}
va_end(lipa);
}
Точно также эти макросы определены в Visual Cи++.
В Cи++ вы можете объявить входные параметры с умалчиваемым значением:
Для этого при определении функции вы задаёте их умалчиваемое значение:
Например: double MfYm (double A, int C, double My = 0, int Gi = 1); Параметры с умалчиваемыми значениями, как и опускаемые, все находятся после списка обязательных параметров.
В Cи++ можно объявить inline функцию: функция, текст которой встраивается непосредственно в текст программы, а затем программа транслируется. Это очень удобно с точки зрения разработки программы. Нет накладных расходов на вызов функции, но при корректировке не надо менять текст в нескольких местах, достаточно изменить текст определения функции. Однако, транслятор «сам» решает вставлять функцию в текст программы или оставить обычной вызываемой функцией. Это необходимо для того, чтобы значительные по величине inline-функции не вставлялись в текст.
Согласно общему правилу все переменные видны только в пределах того блока, внутри которого они объявлены. Если переменные объявлены вне текста программы (чаще всего до начала программы), то они автоматически становятся глобальными: то есть известными всем ниже встречающимся программам. В C мы не имеем права объявлять функцию внутри другой функции. Любая функция может иметь спецификатор класса памяти: static или extern. По умолчанию функция имеет класс памяти extern и будет видна из других модулей. Функция, объявленная с классом памяти static видна только в пределах модуля (файла) объявления. Если внутри функции объявлены переменные одноимённые глобальным, то внутри функции видны именно локальные переменные, а не глобальные. Однако можно обратиться и к глобальным, располагая перед именем переменной :: применив операцию разрешения области видимости.
Эти правила работают, если программист не будет сам управлять видимостью переменных, что возможно в Cи++.
Если переменные объявляются вне программы, то они автоматически становятся глобальными и видны всюду ниже объявления.
Как вопросы вызова и определения функций решены в Pascalе?
Первое отличие от Cи то, что в Pascale два вида подпрограмм: procedure и function. Отличие первой от второй только в том, что function возвращает значение, а procedure нет. В остальном объявление и определение процедуры и функции идентично:
procedure ИМЯ (входные параметры : тип);
function ИМЯ (входные параметры : тип) : тип функции;
Возвращая значение из функции, вам необходимо использовать либо специальную переменную либо имя функции:
Result = …. либо ИМЯ функции = ……
Поместив объявления наших подпрограмм в разделе interface, мы делаем нашу подпрограмму доступной для других модулей. Если нам требуется ограничить видимость нашей подпрограммы только текущим модулем, то следует поместить определение подпрограммы в разделе implementation.
В Pascale вы можете объявить подпрограмму в разделе var. Подпрограмма, объявленная таким образом называется локальной. Она становится невидимой для всех других единиц кода. Локальная подпрограмма «видит» все переменные, объявленные в этой единице кода и, конечно, может ими воспользоваться. Это очень важное отличие от Cи, где нельзя объявлять вложенных функций.
Управление типом передачи параметров в Pascale возложено на программиста.
Если просто перечислить входные параметры в объявлении функции, то параметры будут передаваться по значению. Если перед именем переменной указать ключевое слово var, то параметры будут передаваться по ссылке.
Точно так же, как в Cи, с поправкой на синтаксис Pascal, можно передавать параметры с умалчиваемыми значениями.
Visual Basic очень сильно разнится от версии к версии. Понятно стремление фирмы Microsoft не сделать, а хотя бы приблизить Basic к нормальным программистским инструментам, но родовые травмы очень тяжело лечатся и чаще всего остаются на всю жизнь. Тем не менее, рассмотрим кратко механизмы передачи и объявления подпрограмм в Visual Basic 6.
Visual Basic, как и большинство других языков рассматривает процедуры и функции. Процедура начинается ключевым словом Sub и заканчивается End Sub. Вызывается процедура оператором Call ИМЯ (список параметров). Функции описываются точно также как и процедуры, только вместо Sub вы пишете Function. Функция вызывается обычным способом. Но в Visual Basic функция может быть вызвана и оператором Call, как процедура, при этом теряется её значение. Синтаксис возвращения значения: присвоить имени функции возвращаемое значение. Особенность: функция может вернуть массив! Но только в Visual Basic 6. Кроме того, возвращение массива выполняется по другому синтаксису, который здесь рассматривать не требуется.
Параметры, по умолчанию, передаются по ссылке. Ранее это был единственный способ передачи параметров. В Visual Basic 6 параметры можно передавать по значению, добавляя перед именами передаваемых переменных ключевое слово ByVal. Передача необязательных параметров возможна; используется ключевое слово Optional. Но в Visual Basic возможен и другой способ передачи переменного числа входных параметров. Построение массива входных параметров по ключевому слову ParamArray.
Особенностью Basica будет передача параметров по имени. Это для чайников. То есть, при вызове подпрограммы вы перед параметрами можете указать их имена, поменяв при этом порядок входных параметров.
При межъязыковом программировании следует ещё учитывать порядок упаковки входных параметров в стек. Си первым в стек отправляет последний параметр, а Basic и Pascal всё делают наоборот: то есть в стек первым отправляется первый входной параметр. Поэтому существуют модификаторы доступа:
cdecl – параметры упаковываются как в Cи
pascal - параметры упаковываются как в Рascal
Модификаторы доступа используются перед объявлениями функций.
Мы видим, что в той или иной степени вопросы вызова подпрограмм и передачи параметров решены примерно одинаково во всех языках, даже в таком как Basic. Наличие аппарата подпрограмм позволило писать большие проекты в реальные сроки. Основные недостатки:
1. Как уже отмечалось невозможно вызвать напрямую модуль, оттранслированный другим транслятором. Принципиально этот вопрос решался тем, что разрабатывалась программа-переходник: она создавала среду выполнения для вызывающей подпрограммы и передавала управление подпрограмме. Так можно было подключить объектный модуль, написанный на другом языке. Однако, уже из вышесказанного видно, что лучше всего было иметь текст программы и переписать его на языке вызывающей программы.
2. Поскольку типы данных, чаще всего, обязательно задавались заранее, то необходимо было писать несколько функций с разными типами и разными именами, хотя делали они одно и то же: int abs(int), long int labs(long int), double fabs (double): все эти функции возвращают абсолютное значение. Хотелось бы хотя бы в тексте программы иметь только одну функции – abs.
Вторая проблема решается перегрузкой функций. Дело в то, что транслятор всё равно даёт внутренние имена всем объявленным переменным и функциям в том числе. Следовательно, если транслятор будет различать функции по входным параметрам, то он может сгенерировать для каждой из функций своё внутреннее имя, после чего возможна идентификация каждого экземпляра функции. Другими словами, можно объявить несколько функций с одним именем, но разным списком входных параметров и, возможно разными типами выходных значений.
Например в Cи++: int abs (int);
float abs (float);
char MyF (char, int);
char MyF (char, char, float);
Таким образом, появляется возможность иметь функцию с одним названием для разных типов и количества входных параметров и разных типов выходных параметров. Предполагается, что функции, имеющие одинаковые названия делают одно и то же, только с разными типами входных параметров. Программист должен очень внимательно использовать перегруженные функции. Дело в том, что транслятор должен иметь возможность однозначно различить такие функции. Г. Шилдт [ 10 ] приводит примеры, в общем, правильно объявленных перегруженных функций, тем не менее, употребление их может привести к неоднозначности:
имеем: float Func (float);
double Func (double);
Какую функцию использовать для следующего обращения:
j = Func (10); где int j;
В Pascale вы также можете перегружать функции, указывая сзади описания overload:
function MyFu (N, A, B : Integer) : Integer; overload;
function MyFu (N, A, B : Double) : Double; overload;
В обоих языках нельзя перегрузить функцию у которой различаются только тип выходного параметра. Обязательно должен различаться список входных параметров.
Конечно, нам всё равно приходится писать несколько экземпляров одной и той же программы, но, во-первых, очень часто это только смена заголовка, так как в остальном программа выглядит совершенно одинаково. Во-вторых, программа использующая перегруженные функции намного легче читается, она становится более проста для понимания, а следовательно и для отладки: в ней сохраняется концептуальное единство, что очень важно при отладке больших программных сред.
Возможно другое решение проблемы одной функции, работающей со многими типами данных, - написание так называемых «шаблонов функций», но это мы рассмотрим ниже.
По ходу дела мы не рассмотрели очень важный вопрос: как всё-таки включать необходимые нам подпрограммы в нашу программу? Другими словами, мы не рассмотрели вопросы компоновки программ.
В пакетных системах и в DOS, как мы ранее рассмотрели, включение можно было сделать на уровне исходного модуля и на уровне объектного модуля. Обычно у грамотных программистов существовали библиотеки исходных, объектных и загрузочных модулей. Отметим, что всё сказанное может касаться и DOSa, но там уже было большее разнообразие вариантов. Кроме того, библиотеки существовали системные, библиотеки транслятора и личные. Считалось крайне неприличным что-нибудь своё помещать в системные библиотеки или библиотеки транслятора, если, конечно, у вас не было специального задания. Личные библиотеки программным средам необходимо было указывать. Трансляторы, редакторы, загрузчики были построены так (только не в DOS), что поиск необходимых модулей выполнялся сначала в личных библиотеках, затем в библиотеках транслятора и, наконец, в системных библиотеках.
Исходные модули можно было либо «сцепить» вместе, указав имена библиотек и исходных модулей, либо включить исходный модуль по директиве препроцессора, но последнее возможно было не во всех языках.
Препроцессор: часть транслятора, вызываемая на нулевой фазе трансляции (то есть первой) и меняющая заданным образом транслируемый текст и опции трансляции. Отметим, что препроцессор меняет текст, подаваемый на трансляцию. Собственно директивы препроцессора не являются элементами языка и зависят от реализации, а в частности от возможностей конкретного транслятора. Однако основная масса директив препроцессора одинакова для всех трансляторов языка.
Появились препроцессоры рано. Уже, фактически, Fortran имел некоторые директивы препроцессора, но там это не было систематизировано. Но уже такой язык, как PL/1 имел понятие препроцессора и его директив. В частности этот язык имел директиву # include ИМЯ, по которой в текст транслируемой программы вставлялся другой исходный текст. Имя библиотек или, в совремённой трактовке, пути не указывались по вышеперечисленным причинам. Что интересно, что PL/1, это язык- оболочка и согласно идеи в нём было всё! Тем не менее, лучше всего было включить общие для программы переменные и описания в некий исходный текст и подавать его в необходимые модули. Единственный недостаток этого решения, что вставляемый текст всегда транслировался, что несколько замедляло время трансляции.
Язык Cи – язык-ядро. В самом Cи нет даже ввода/вывода, математических функций и т.д. На самом деле всё это есть, иначе было б невозможно работать, но указанные модули расположены по библиотекам, поставляемым с транслятором, а значит, сильно зависят от реализации. Безусловно, есть часть реализованная одинаково во всех трансляторах, но, во-первых, имеются разночтения, а во-вторых, есть существенно по-разному реализованные части.
Программа на Cи состоит из двух частей: заголовка программы и текста программы. Заголовки имеют расширение .h и помещаются в текст программы по директиве препроцессора #include ИМЯ. Все директивы препроцессора начинаются с «решётки» (#) в первой позиции и, обычно, помещаются перед началом текста программы. Запрета на помещение директив в любое место программы нет, но чаще всего вышеуказанное размещение.
#include может быть в двух вариантах:
#include < имя > исходный текст ищется в стандартной библиотеке INCLUDE, где хранятся все стандартные заголовки. Обычно эта библиотека находится в директории установки транслятора.
#include “путь\имя” исходный текст ищется в указанной директории.
В обоих случаях имя – имя включаемого заголовка.
Предполагается, что в заголовке размещены объявления всех наиболее часто используемых функций и констант, а также определены используемые объявленными функциями структуры данных. Тексты очень коротких функций также могут быть помещены в заголовок. Опять-таки, нет запрета на помещение в заголовки какого-либо текста, есть негласное практическое правило, что может содержать заголовок. Рекомендуем посмотреть Бьёрна Срауструпа [8] стр.246
Такая система приводит к тому, что программисту, а очень часто и пользователю, необходимо знать, в каких заголовочных файлах помещены необходимые ему функции. При этом следует иметь в виду, что от транслятора к транслятору имена заголовочных файлов могут меняться, тем не менее:
stdio.h – основные функции ввода/вывода
stdlib.h – форматные преобразования данных
math.h – математические функции
string.h – операции со строками
malloc.h & alloc.h – запросы памяти у операционной системы.
Разумеется в Cи++ эти заголовочные файлы можно использовать, но тут имеются и собственные заголовочные файлы. Таким образом, включая в свою программу стандартную функцию вам необходимо, прежде всего, указать её заголовочный файл.
В Cи++ заголовочный файл может иметь расширение .hpp. Cи++Builder разработан так, что сам включает основные заголовочные файлы, но иногда программисту приходится самому заботиться о заголовочных файлах.
Тексты программ хранятся в файлах, имеющие расширения .c; в Cи++ - .cpp Тексты программ также можно включить по директиве #include. Вставляя все заголовки вверху программы, программист задаёт все необходимые ему описания, а помещая в нужное место программы файлы .c и .cpp, программист вставляет все необходимые ему тексты. Всё это достаточно удобно и просто, почему и получило раcпространение.
Недостатки: все тексты транслируются при каждом проходе программы. Это неудобство частично устранено директивой #pragma hdrstop. Некоторые трансляторы, в частности Cи++Builder, создают так называемые предварительно откомпилированные заголовки (расширение .csm). Это часть общих файлов, которые всегда включены по директиве #include. Указанные заголовки предварительно оттранслированы в некоторую промежуточную между исходным и объектным кодом форму и помещены в рабочую библиотеку. Все заголовки (тексты), включённые в исходный модуль выше pragmы, не транслируются. Вся необходимая информация выбирается из файлов .csm.
Второй серьёзный недостаток: программист, в общем-то, должен знать, где находится описание применяемой им функции, хотя она и описана, как стандартная. Среды визуального программирования сделаны так, что сами вставляют все необходимые заголовки, но иногда приходится работать вне визуальной среды, кроме того, при нестандартной работе также приходится о некоторых заголовках заботиться самому. Конечно, совремённые средства поиска информации на компьютере существенно сглаживают это неудобство, но представьте, что средства поиска дали вам несколько заголовков, в которые входят необходимые вам описания – какой вставлять вам в текст?
Третье: такая система, а именно – язык-ядро, провоцирует различия от транслятора к транслятору и даже от версии к версии одного транслятора.
Таким образом, система подключения текстов на уровне «исходников» при пользовании требует наличия исходного модуля или текста программы. Кроме того, как уже ранее отмечалось, при вставке исходного модуля необходимо всякий раз его транслировать. Существует другая схема компоновки: программа подключается на уровне объектного модуля. Выполняется это редактором связей. У редактора связей существует свой язык описания входных данных. На этом языке программист может указать, какой объектный файл ему необходимо включить при редактировании. Таким образом, подпрограмма может быть заранее оттранслирована, сохранена в библиотеке объектных модулей, а во время редактирования подключена к компонуемой программе. Все модули, вставляемые транслятором, поставляются именно на уровне объектных модулей. При этом достигается две цели: исходный текст скрывается от пользователя, а время трансляции не зависит от величины программы, так как все стандартные функции и подпрограммы уже оттранслированы. В связи с особенностями функционирования DOSa объектные модули редко хранятся «поодиночке». Обычно они собраны в библиотеки программ и хранятся в заданном месте. Библиотеки программ имеют расширение .lib и чаще всего хранятся в библиотеке транслятора LIB. Тем не менее, программист имеет возможность подключить одинокий объектный модуль к своей программе. В Cи++Buildere это можно выполнить с помощью Project Manager (меню View), указав включаемый объектный модуль. Также можно в свойствах проекта указать дополнительную библиотеку lib. Для получения объектного модуля в Cи++Buildere необходимо транслировать исходный текст в любом проекте.
На совремённом этапе, всё чаще идёт речь о подключении подпрограмм на уровне загрузочных модулей. Рассмотрение этого вопроса требует предварительного обзора функционирования самой операционной системы. Хотим мы того или нет, но принципы работы Windows существенно отличаются от работы Unix – подобных систем. Поэтому эту тему мы будем изучать позже, после обзора данных и их структур, используемых в программировании.
Последнее замечание по теме подпрограммы: мы нигде никоим образом не рассмотрели, каким же всё-таки образом разбивать программу на составные части. Ясно, что здесь нет общих правил. Мы не можем указать единого алгоритма разбиения программы на модули, хотя можно указать, что может повлиять на разбиение программа:
1. Прежде всего, сама задача. Задача может быть исследовательской или технической; формализованной – не формализованной; эпизодической, требующей однократной реализации, или регулярно «считаемой»; простой или сложной; разрабатываемой для использования самим программистом или разрабатываемой на продажу и т.д. Всё это в какой-то мере влияет на разбивку задачи на подзадачи, но, прежде всего, возможность разбиения задачи на подзадачи определяется самой сутью задачи и тут нет общих готовых рецептов.
Кроме того, все задачи в программировании условно делятся на следующие категории: вычислительные, “асушные”, системные, управляющие и смешанные.
Вычислительные, обычно, характеризуются большим объёмом вычислений и незначительным объёмом ввода/вывода. В вычислительных задачах, как правило, используется достаточно серьёзная математика и программисту специализирующемуся на вычислительных задачах (методах) просто необходимы знания математики в объёмах превышающих общеинженерные курсы математики.
В “асушных” задачах относительно незначительные объёмы простых вычислений, но со значительным объёмом ввода/вывода. Основные используемые технологии работа с базами данных. В большинстве случаев, это преобразование одного множества таблиц в другое множество таблиц с тем или иным объёмом ввода данных и вывода. Задачи, почти всегда простые, но критичные ко времени выполнения.
Системные: реализация модулей операционной системы, трансляторов, программ СУБД (системы управления базами данных), программы взаимодействия в сети и т.д. Как правило, требуются серьёзные знания вычислительной техники и особенностей её функционирования, а также операционных сред.
Управляющие: программы управляющие работой технических устройств или технологией протекания технических процессов. Почти всегда работают в режиме реального времени, чаще всего реализуются на Assemblere (в последнее время используется и Cи++). Высокие требования по надёжности функционирования.
Смешанные: задачи, обладающие характеристиками нескольких ранее выделенных групп, например – реализация серьёзной графической среды требует значительных объёмов непростых вычислений и значительного объёма операций по вводу/выводу или реализация операционной системы реального времени.
2. Программист. Обычно при рассмотрении абстракций выполняется абстрагирование не только от данных, например, или действий, но и от самого программиста. С одной стороны это понятно, поскольку строится некая формальная схема абстракции, где нет места такому глубоко неформальному элементу, как программист. Однако, в техническом задании алгоритм решения может быть определён достаточно отвлечённо, сортировать данные, например, а конкретный выбор алгоритма переложен на плечи программиста. Не надо объяснять, что программисты бывают разные и соответственно они по-разному сделают выбор алгоритма и разбиение задачи. Очень важно учитывать тип задачи и склонность программиста к решению именно этого типа задач.
3. Объёмом данных и соответственно выбираемым алгоритмом.
4. Технической и программной средой решения. Структура программы будет существенно разной в последовательной системе или в системе управляемой событиями (Unix или Windows). Вы можете работать в многопроцессорной среде с параллельными вычислениями или в однопроцессорной системе; в сети, используемой только для передачи данных или в существенно распределённой среде. Выбранный алгоритм может допускать параллельную обработку или нет.
5. Условиями конфиденциальности.
Обратите внимание, что формализованной частью в указанных феноменах будет только пункт № 3 – объём данных и алгоритм, и тот грешит неформальным определением алгоритма.
Вопросы к главе 4.
1. Формы представления постановки.
2. Блок-схема программы.
3. Алгоритм. Что такое алгоритм? Привести пример.
4. Пять основных свойств алгоритма.
5. Продемонстрируйте на примерах свойства мощности, особенности и красоты алгоритма.
6. Влияние объёма данных на используемый алгоритм.
7. Сущность алгоритмизации.
8. Необходимые соглашения для реализации библиотеки стандартных программ.
9. Основные различия между программой и подпрограммой.
10. Достоинства разбиения программ на подпрограммы.
11. Глобальные переменные; достоинства и недостатки.
12. Общая используемая область памяти; достоинства и недостатки.
13. Процедурная абстракция: что это такое?
14. Схемы запуска других процессов.
15. Вызов подпрограмм: передача параметров.
16. Вызов в Си++ программ с переменным числом параметров.
17. Передача в подпрограммы параметров с умалчиваемыми значениями.
18. Перегрузка функций?
19. Схема включения подпрограмм в программу.
20. Что такое препроцессор? Зачем он нужен?
21. Достоинства и недостатки схемы язык-ядро.
22. Достоинства и недостатки схемы язык-оболочка.
23. Что влияет на разбиения программы на модули?