Принципы программирования.
Стиль программирования.
Принципы программирования:
Функции обозначают модификацию программ.
Именованные константы облегчают модификацию программ.
int scores[202];
for (index = 0 through 201)
Обработка оценок.
const int NUMBER_OF_MAJORS = 202;
int scores[NUMBER_OF_MAJORS];
for (index = 0 through NUMBER_OF_MAJORS - 1)
Обработка оценок.
typedef float RealType;
typedef long double RealType;
Приглашение к вводу данных.
Эхо ввода.
Разметка вывода.
18:00 б 1
Джонс, К. 223 2234.00 1088.19 Н, О Смит, Т. 111
110.23 3, Харрис, У. 44 44000.000 22222.22
Счета вкладчиков по состоянию на 18:00 1 июня
Состояние счёта: Н - новый, О- общий, 3 - закрыт
| Имя | Номер | Снятие | Вклады | Состояние |
| Джонс, К. | 223 | $2234.00 | $1088.19 | Н, 0 |
| Смит, Т. | 111 | $110.23 | ------------ | 3 |
| Харрис, У. | 44 | $44000.00 | $22222.22 | ------------ |
Хороший пользовательский интерфейс имеет большое значение.
Проверка ошибок при вводе данных.
Проверка логики программы.
Предотвращение неверного ввода.
const mt LOW_END = 10;
// Нижняя граница доходов.
const int HIGH_END = 10; // Верхняя граница доходов .
const int TABLE_SIZE = HIGH_END - LOW__END + 1;
typedef int TableType[TABLE_SIZE];
int index(int group)
// Возвращает индекс массива, соответствующий номеру группы.
{
return group - LOW_END;
} // Конец функции — «index».
void readData(TableType incomeData)
// Считывает и организовывает статистические данные о доходах. Предусловие: вызываемый модуль выдает инструкции и предлагает пользователю ввести данные. Входные данные не должны содержать ошибки. Каждая строка имеет вид — «G» (количество), «N» (количество людей, чей годовой доход равен тысячам долларов со значением — «G» (LOW_END <= G <= HIGH_END)). Ввод данных завершается после считывания строки, в которой числа — «G», «N» — равны нулю. Постусловие: число — «incomeData[G-LOW__END]» — равно общему количеству людей, чей доход равен значению — «G» — тысяч долларов для каждого данного считанного значения. Считанные значения выводятся на экран.
{
int group, number; // Входные значения.
// Очищаем массив.
for (group = LOW__END; group <= HIGH_END; ++group)
incomeData[index(group)] = 0;
for (cin >> group >> number; (group != 0) II (number 1= 0))
cin >> group >> number;
{ // Инвариант: переменные — «group», «member» — не равны нулю.
cout << "Количество людей в группе" << group << " равно " << number << ".\n";
incomeData[index(group)] += number;
} // Конец цикла — «for».
}
// Конец функции — «readData».
bool readData(TableType incomeData)
// Считывает и организовывает статистические данные. Предусловие: вызываемый модуль выдает инструкции и предлагает пользователю ввести данные. Каждая строка содержит два целых числа в виде — «G» (количество), «N» (количество людей, чей годовой доход равен значению — «G» — тысяч долларов). LOW_END <= G <= HIGH_END. Ввод данных завершается после считывания строки, в которой данные числа равны нулю. Постусловие: число — «incomeData[G-LOW_END]» — равно общему количеству людей, чей доход равен значению — «G» — тысяч долларов для каждого данного считанного значения. Считанные значения выводятся на экран. Числа — «G» «N» — неверны (не равны нулю и G < LOW_END, G > HIGH_END или N < 0) — функция игнорирует строку ввода, задаёт возвращаемое значение, равным значению — «false» — и продолжает работу. Решение о продолжении выполнения программы принимает вызывающий модуль. Если входные данные не содержат ошибок, функция возвращает значение — «true».
{
int group, number; // Входные значения.
bool dataCorrect = true; // Ошибок пока нет.
for (group = LOW_END; group <= HIGH_END; ++group)
incomeData[index(group)] = 0;
for (сin >> group >> number; (group != 0) II (number != 0))
сin >> group >> number;
{ // Инвариант: переменные — «group», «number» — не равны нулюcout << "Количество людей в группе" << group << " равно " << number << ".\n";
if ((group >= LOW_end) && (group <= HIGH_END) && (number >= 0))
// Входные данные корректны — добавляем их в счётчик.
incomeData[index(group)] += number;
else
// Ошибка при вводе данных: устанавливаем признак ошибки, игнорируя строку.
dataCorrect = false;
} // Конец цикла — «for».
return dataCorrect;
} // Конец функции — «readData».
Функции должны проверять свои инварианты.
Функции должны проверять предусловия.
int factorial(int n)
// Вычисляет факториал целого числа. Предусловие: значение — «n» — >= 0. Постусловие: если значение — «n» — > 0, возвращает значение — «n * (n-1) * ... * 1». Если значение — «n» = 0, возвращает число — 1.
{
int fact = 1;
for (int i = n; i > 1; —i)
fact *= i;
return fact;
} // Конец функции — «factorial».
Широкое использование функций.
Использование закрытых данных-членов.
Избегание глобальных переменных в функциях.
Правильное применение аргументов, передаваемых по ссылке.
Правильное применение функций.
Обработка ошибок.
Читабельность.
Документация.
Комментарии в начале программы должны содержать пункты:
В комментариях, помещённых в начале каждого класса, указывается его предназначение и описываются данные, содержащиеся в нём (константы и переменные).
В комментариях, помещённых в начале каждой функции, указываются её предназначение, предусловия, постусловия и вызываемые функции.
Комментарии, размещённые в теле каждой функции, должны пояснять её основные свойства и особенности логики.
Технология программирования — это область компьютерных наук, изучающая способы разработки компьютерных программ.
Жизненный цикл программного обеспечения состоит из нескольких этапов:
Инвариант цикла — это свойство алгоритма, которое должно выполняться до и после каждой итерации цикла. Инварианты цикла позволяют разрабатывать итерационные алгоритмы и проверять их правильность.
Оценивая качество решения, необходимо учитывать большое количество факторов:
Сочетание объектно-ориентированного подхода и проектирования — «сверху вниз» приводит к модульному решению. Данные и операции над ними инкапсулируются в классах. Классы можно идентифицировать, анализируя имена существительные, употреблённые при постановке задачи. Алгоритмы следует разбивать на независимые подзадачи, постепенно уточняя их. В любом случае применяется абстракция данных — внимание сосредоточивается на том, что делает модуль, а не на том, как он это делает.
Язык — «UML» — это язык моделирования, используемый для описания объектно-ориентированных проектов. Он предоставляет функциональные возможности для описания данных и операций и применяет диаграммы для выявления отношений между классами.
Стремитесь к тому, чтобы окончательное решение можно было легко модифицировать. Обычно модульные программы модифицируются легко, поскольку изменения в одном модуле не затрагивают остальных. Программы не должны зависеть от конкретной реализации своих модулей.
Функции должны быть как можно более независимыми и выполнять одну точно поставленную задачу
Функции всегда должны сопровождаться комментариями, которые помещаются в их начало, формулируют их предназначение, а также предусловие, которое должно выполняться в начале модуля, и постусловие, которое должно выполняться в конце модуля.
Программа должна быть максимально надежной — например, программа должна иметь защиту от ошибок при вводе данных и логических ошибок. С помощью проверки инвариантов — условий, которые должны выполняться в определенных точках программы — можно отслеживать правильность выполнения программы.
Эффективное использование доступных диагностических средств — ключ к успешной отладке программ. Для проверки значений переменных в ключевых точках следует применять средства наблюдения и операторы промежуточного вывода — «cout». Их нужно размещать в начале и в конце функций и циклов, а также внутри ветвей условных операторов.
int index = 0;
int sum = item[0];
while (index < n)
{
++index;
sum += item[index];
} // Конец цикла — «while».
0 < index < n
sum = item[0] + ... + item[index]
sum(in anArray: аrrауТуре, in n: integer): elementType
// Вычисляет сумму первых пяти положительных элементов массива — «anArray». Предусловие: массив — «anArray» — состоит из элементов с количеством — «n» — n >= 5, по крайней мере 5 элементов массива являются положительными. Постусловие: возвращает сумму первых пяти положительных элементов массива — «anArray», массив остаётся неизменным.
computeSum(in аnАrrау: аrrауТуре, in n: integer, out sum: elementType, out success: boolean)
Вычисляет сумму первых пяти положительных элементов массива — «anArray». Предусловие: массив — «anArray» — состоит из элементов с количеством — «n». Постусловие: по крайней мере 5 элементов массива являются положительными — параметр — «sum» — равен сумме первых пяти положительных элементов, а параметр — «succes» — имеет значение — «true» — противном случае параметр — «sum» — равен 0, а параметр — «success» — имеет значение — «false» — массив остаётся неизменным.
Стоимость вещи, которую вы хотите купить, выражается в рублях и копейках. Вы платите наличными, отдавая продавцу рубли с количеством — «d» — и копейки — «c».
Напишите спецификацию функции, вычисляющей сдачу, если она вам полагается.
Обязательно укажите ее предназначение, пред- и постусловия, а также приведите описание её аргументов.
Дата состоит из месяца, дня и года. Часто она выражается целым числом — например, для даты — 4 июля 1776 — количество месяцев равно 7, дней — 4 и лет — 1776.
Напишите спецификации для функции, получающей на вход произвольную дату. Обязательно укажите ее предназначение, пред- и постусловия, а также приведите описание её аргументов.
Напишите реализацию этой функции на языке — «С++». Включите в неё комментарии, позволяющие эксплуатировать её в будущем.