Алгоритмические языки и программирование. Учебное пособие
.pdf
else{
cout << "Roots: "
<<(-b - sqrt(D))/ (2 * a) << " " // sqrt(D) – square root of D
<<(-b + sqrt(D))/ (2 * a) << endl;
}
}
}
Повтор
Повтор используется, если по алгоритму требуется осуществить одну инструкцию или блок инструкций несколько раз. В языке C++ повторы называются циклами. Существует три вида циклов: цикл «Пока» (ключевое слово while), цикл «Для» (ключевое слово for) и цикл «Делай пока» (ключевые слова do/while).
Циклы «Пока» и «Для» изображаются на схеме следующим образом:
Соответствующая запись на языке C++:
while(условие_продолжения){ инструкции;
}
Блок инструкций после условия продолжения называется телом цикла. Условие продолжения – это логическое выражение, которое проверяется каждый раз перед выполнением тела цикла. Самые распространенные ошибки при записи цикла:
21
1)условие продолжения при первом выполнении ложно. При этом цикл не будет выполняться ни разу;
2)условие продолжения всегда истинно. Цикл выполняется, пока принудительно не будет завершена работа программы. Эта ошибка называется вечным циклом или зацикливанием;
3)условие продолжения не меняется при выполнении тела цикла. Эта ошибка сводится к первой или второй.
Тело цикла «Пока» или «Для» выполняется после проверки условия продолжения. Поэтому эти циклы называются циклами с предусловием. Цикл «Пока» может использоваться для работы со счетчиком и с меткой. В качестве счетчика выступает целочисленная переменная, увеличивающаяся при выполнении некоторого условия. Меткой может служить условие четности, делимости и т. п.
Цикл «Для» предназначен только для работы со счетчиком. Он записывается так:
for (инициализация счетчика; условие продолжения; изменение счетчика){ инструкции;
}
Например:
for (int i = 0; i < 10; ++i){ cout << i << “ ”;
}
При первом выполнении цикла создается и инициализируется счетчик i, проверяется условие продолжения, выполняется тело цикла. При повторном выполнении счетчик увеличивается на единицу и проверяется условие продолжения и т. д.
Цикл «Для» можно записать в виде цикла «Пока» со счетчиком, и наоборот:
22
for( |
<=> |
выражение_1; |
выражение_1; |
|
while(выражение_2){ |
выражение_2; |
|
инструкции; |
выражение_3 |
|
выражение_3 |
){ |
|
} |
инструкции; |
|
|
} |
|
|
Цикл «Делай пока» изображается так:
Проверка условия продолжения осуществляется после выполнения тела цикла. Цикл «Делай пока» называется циклом с постусловием.
Массив
Для работы с большими объемами данных в программах используются массивы. Массив представляет собой большой непрерывный блок памяти. Массив – сложный или составной тип. Массив состоит из набора переменных одного типа, который называется базовым, расположенных одна рядом с другой. Базовым типом массива может быть один из элементарных типов: int, double,
23
char, bool. Переменные внутри массива называются элементами массива. Каждый элемент пронумерован, и вместо имени к нему нужно обращаться по номеру.
Массив предназначен для хранения большого объема данных во время работы программы. По завершении программы массивы, так же как и обычные переменные, удаляются. Для постоянного хранения данных нужно записывать их на жесткий диск в виде файла.
Основными этапами работы с массивами являются инициализация, заполнение, обработка и вывод. Наиболее часто к массивам применяются следующие алгоритмы: сравнение элементов массива, суммирование и произведение элементов массива, поиск заданной величины в массиве, нахождение минимального и максимального элемента.
Для работы с массивом сначала его нужно описать. Пример:
int Array[10];
Описан массив целых чисел размера 10, т. е. переменная Array состоит из десяти переменных типа int – элементов массива. Размер массива обязательно должен быть константой, поскольку память для размещения массива выделяется на этапе компиляции. Если в качестве размера массива передается переменная, возникает ошибка компиляции.
Для инициализации массивов используется следующая запись:
int Array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
В фигурных скобках через запятую записываются значения, которые присваиваются очередному элементу. Если значений меньше, чем размер массива, оставшиеся заполняются нулями. Потому, чтобы проинициализировать массив нулями, достаточно записать:
int Array[10] = {0};
24
Если значений больше, чем размер, – при компиляции произойдет синтаксическая ошибка.
Для обращения к элементу массива используется запись Array[номер_элемента]. Номер элемента также называется индексом. Индекс должен быть целым числом от нуля до размера массива. Но компилятор не проверяет индекс на выход за пределы массива. Это является одной из самых распространенных ошибок при работе с массивами.
При передаче в функцию массив всегда передается по ссылке. Важно отметить, что, работая с массивом, часто важно знать его размер. Поэтому в функцию обычно передается не только массив, но и его размер.
Пример. Дан набор чисел. Найти среднее арифметическое число.
#include<iostream> using namespace std;
void Input(int A[], int Size); //input array
double Sum(int A[], int Size); //calculate sum of all elements double CalcMean(int A[], int Size); //calculate mean value int main(){
int Array[10] = {}; Input(Array, 10);
cout <<"Mean value: " << CalcMean(Array, 10); return 0;
}
void Input(int A[], int Size){ //input array for(int i = 0; i < Size; ++i){
cin >> A[i];
}
}
double Sum(int A[], int Size){ //calculate sum of all elements double S = 0;
for(int i = 0; i < Size; ++i){ S += A[i];
25
}
return S;
}
double CalcMean(int A[], int Size){ //calculate mean value return Sum(A, Size) / Size;
}
Строка
Строка представляет из себя набор символов и предназначена для обработки текстовой информации (например, фамилий или названий кампаний). Строковая константа записывается в двойных кавычках, например ”Tokmantsev”. В памяти строка хранится в виде массива строкового типа с последним элементом '\0'. Этот символ называется завершающим симоволом и обозначает конец строки.
Переменная типа строка описывается как массив символов: char String[10]. Инициализация возможна двумя способами:
1.char String[10] = {'i', 'n', 'i', 't'};
2.char String[10] = “init”;
При задании размера строки нужно учитывать место для завершающего символа.
В отличие от массивов, строки можно выводить на экран и вводить с клавиатуры удобным способом:
cout << String; cin >> String;
Для работы со строками используется библиотека cstring. Самые полезные функции:
1)strlen(имя_строка) – возвращает длину строки;
2)strcpy(имя_строки_1, имя_строки_2) – копирует строку_2 в строку_1;
3)strcat(имя_строки_1, имя_строки_2) – добавляет строку_2 в конец строки_1 (строка_1 должна иметь достаточный размер);
26
4)strcmp(имя_строки_1, имя_строки_2) – возвращает 0, если строки равны и не ноль в обратном случае.
Пример. Требуется в заданной строке найти, сколько раз встречается заданный символ. Для решения задачи требуется перебрать по очереди каждый символ строки и сравнить его с заданным символом. При совпадении увеличиваем число вхождений на единицу.
#include<iostream>
#include<cstring> using namespace std;
void Input(char S[], char &Symbol); //input string
int CalcPresence(char S[], char Symbol); //calculate symbol presence int main(){
char String[100] = ""; char Symbol; Input(String, Symbol);
cout << "The symbol " << Symbol
<<" is presented "
<<CalcPresence(String, Symbol)
<<" times.\n";
return 0;
}
void Input(char S[], char &Symbol){ //input string cout << "Input string: ";
cin >> S;
cout << "\nInput symbol: "; cin >> Symbol;
cout << endl;
}
int CalcPresence(char S[], char Symbol){ //calculate symbol presence int Pres = 0;
int Size = strlen(S);
27
for(int i = 0; i < Size; ++i){ if (S[i] == Symbol){
++Pres;
}
}
return Pres;
}
Основные понятия ООП
Парадигмы программирования
Основными парадигмами программирования являются процедурное программирование, модульное программирование, объектно-ориентированное программирование и обобщенное программирование.
Процедурное программирование
Исторически самая первая парадигма гласит, что программа должна быть разбита на процедуры, каждая из которых должна быть написана в соответствии с принципами структурного программирования, иметь один вход и один выход. Основная программа реализована как вызов процедур.
Модульное программирование
Развивает идеи процедурного программирования. Программа разбивается на модули, реализованные в виде открытого для внешнего доступа интерфейса, содержащего процедуры-сервисы, и закрытой части – реализации, содержащей служебные процедуры.
ООП
Основной целью программирования является написание программы, решающей требуемую задачу. В настоящее время характерными чертами решаемых задач являются сложные предметные области и постоянное
28
изменение требований. Сложность области в основном заключается в наличии большого количества объектов и активном их взаимодействии. Объекты понимаются как некоторые сущности, обладающие состоянием и поведением. Взаимодействие объектов между собой заключается в посылке друг другу сообщений и использовании предоставляемых сервисов. Основными проблемами, связанными с решением задач, являются изменение постановки задачи и сложность.
Для решения проблем был предложен подход, названный объектноориентированным программированием. Сущность подхода состоит в выделении в постановке задачи объектов и способов их взаимодействия. Затем создается программный код, в котором создаются программные реализации объектов и моделируются их отношения. Этот подход позволяет снять проблемы, связанные с решением задач: благодаря тому, что объекты из предметной области имеют аналоги в программе, легче менять программу соответственно изменениям в требованиях. Использование ранее описанных объектов и сервисов уменьшает дублирование кода. Разбиение программы на объекты и модули уменьшает связи, что делает программу более гибкой и прозрачной.
Для того чтобы разработать программу в рамках объектноориентированного подхода, нужно придерживаться основных принципов проектирования.
Первым принципом является принцип абстракции: при написании программы из постановки задачи извлекаются объекты, формулируются только необходимое состояние и поведение, объекты описываются в виде классов.
Второй принцип – инкапсуляция. Внутри класса должны быть выделены открытые сервисы (интерфейс); поля (состояние) и служебные методы (реализация) должны быть скрыты.
Третий принцип – наследование. Из классов, имеющих общий интерфейс, должен быть выделен абстрактный базовый класс, фиксирующий интерфейс.
Для классов, образующих естественную иерархию, должна быть построена иерархия наследования.
29
При создании классов, отличающихся друг от друга специализированными деталями, должен быть выделен общий базовый класс, содержащий общие части.
Последний принцип – полиморфизм. Он дополняет принцип наследования и гласит, что классы, отделяющие интерфейс и реализацию с помощью наследования, должны работать на основе принципа подстановки: любые методы и функции, принимающие указатель или ссылку на базовый класс, должны работать при подстановке туда производного класса.
Класс
Выделенные объекты предметной области должны быть перенесены в программу и реализованы в виде структуры или класса. Структура используется для простых объектов, не обладающих существенным поведением.
Классы содержат в себе данные, описывающие состояние объекта, и методы, реализующие поведение. В силу принципа инкапсуляции поля должны быть закрыты для внешнего доступа, в случае крайней необходимости можно предоставить методы для чтения полей или для записи новых значений, при этом обязательно нужно реализовать проверку корректности новых значений.
Методы класса делятся на интерфейс и реализацию. К реализации относятся служебные, вспомогательные методы. Они также должны быть закрыты.
Интерфейс представляет собой сервисы, обеспечиваемые классом. Он должен быть открыт для внешнего доступа. Интерфейс должен быть кратким и ясным, имена методов должны носить описательный характер, чтобы по ним можно было понять предоставляемые сервисы, не читая код.
Кроме объектов, предметная область также содержит отношения, различные формы взаимодействия между ними. При написании программы самые существенные отношения должны быть промоделированы в коде программы. Основные виды взаимодействия: «использование» (один класс использует сервисы другого), «является» (существует иерархия объектов, один класс в ней
30
