Программирование
DESCRIPTION
Программирование. Часть 4 Структуры данных. 4. Структурное программирование 4. 5 . Базовые структуры данных: структуры. Программа = Структуры данных + Алгоритмы. СТРУКТУРА ДАННЫХ – способ представления данных в программе для компьютера - PowerPoint PPT PresentationTRANSCRIPT
Программирование
Часть 4Структуры данных
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Программа = Структуры данных + Алгоритмы
СТРУКТУРА ДАННЫХ – способ представления данных в программе для компьютера
ПРОГРАММА - описание структур данных и алгоритма решения задачи на языке программирования, автоматически переводимое на язык машинных команд конкретной ЭВМ помощи транслятора (интерпретатора).
Задача:Спроектировать структуру данных для представления в памяти компьютера информации о членах университетского коллектива.
4. Структурное программирование 4.5. Базовые структуры данных: структуры
НАЧНЕМ С ДАННЫХ О ЧЛЕНЕ УНИВЕРСИТЕТСКОГО КОЛЛЕКТИВА. ПОСТАВЛЕНА ЗАДАЧА ХРАНИТЬ И ОБРАБАТЫВАТЬ СЛЕДУЮЩУЮ ИНФОРМАЦИЮ О НЕМ:
Идентификационный номер (студенческого билета или удостоверения) Фамилия Имя Отчество Дата рождения Домашний адрес Дата зачисления (на работу или учебу) Должность Является ли членом профсоюза
4. Структурное программирование 4.5. Базовые структуры данных: структуры
ВЫБЕРЕМ ТИПЫ ДАННЫХ И ИМЕНА ПЕРЕМЕННЫХ ДЛЯ ХРАНЕНИЯ ИНФОРМАЦИИ О КАЖДОМ ЧЕЛОВЕКЕ:
Идентификационный номер – int id Фамилия – char surname [80] Имя – char firstname [40] Отчество – char patronymic [60] Дата рождения – unsigned short birthyear, birthmonth, birthday Адрес – char address [80] Дата зачисления – unsigned short enteryear, entermonth, enterday Должность – char position [30] Является ли членом профсоюза – bool tradeunion
Структура – упорядоченное множество данных различного типа, которые называются полями или членами структуры.
Доступ к полю структуры осуществляется по имени структуры и имени поля.
Поля структуры могут иметь любой тип (кроме void). Структура может содержать только такие поля, длина которых
известна компилятору в момент определения структуры. Структурным типом данных или просто структурой называется тип,
описывающий структуру.Синтаксис объявления структурного типа:
struct Имя_структуры{
Тип_ поля_1 Имя_поля1;Тип_ поля_2 Имя_поля2;
… };
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Примеры объявления структурных типов :
struct Date struct Name{ { unsigned short year; char surname [80]; unsigned short month; char firstname [40]; unsigned short day; char patronymic [60]; }; };
struct Cmplx{ double re; double im;};
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Обратите внимание: описание структуры заканчивается точкой с
запятой
Размещение в памяти структурных типов :
struct Date{ unsigned short year; unsigned short month; unsigned short day;};
struct Cmplx{ double re; double im;};
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Внимание!Компилятор не гарантирует размещение элементов структуры в смежных ячейках памяти!
Объявление переменных структурного типа
Имя_типа Имя_переменной;Имя_типа Имя_переменной = {список значений};
Примеры объявления переменных структурных типов,
Cmplx c1, c2, c3;Date birth, enter, expel, graduate, death ;
struct // Совмещение объявлений типа и переменных { // в анонимной структуре double re; double im;} c1, c2, c3;
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Примеры объявления переменных структурных типов с инициализацией
Cmplx c1 = {0, 0};Date birth = {1991, 10, 7}, enter = {2009, 9 , 1}, graduate = {2014, 6, 30};
struct // Совмещение объявлений типа и переменных { double re; double im;} c1={0, 0}, c2={1, 0}, c3={1, 0};
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Доступ к элементам структуры: оператор . (точка)
Имя_переменной.Имя_поля
birth.year = 2002; birth.month=12;
c1.re = 12.5; c1.im = -24;c2.re = c1.re*c1.re + c1.im*c1.im;
Присваивание переменных – структур одного типа :
c1=c2; expel.year=enter.year;
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Структуры могут:объединять данные (поля) различных типов;быть вложенными друг в друга
4. Структурное программирование 4.5. Базовые структуры данных: структуры
struct Date{ unsigned short year; unsigned short month; unsigned short day;};
struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; //"student", "teacher", "scientist" …
bool tradeunion;};
struct Name{ char surname [80]; char firstname [40]; char patronymic [60]; };
Рассмотрим работу с вложенными структурами
4. Структурное программирование 4.5. Базовые структуры данных: структуры
struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; bool tradeunion;};
Member stud1 = {298678, “Сидорова”, “Анна”, “Ивановна”, 1991, 10, 7, “Минск, ул. Серова 23, кв. 1”, 2009, 9, 1, “student”, false};
Member prep4 = {129639, {“Попкец”, “Павел”, “Петрович”}, {1980, 6, 1}, “Минск, ул. Казинца 75, кв. 12”, {2003, 3, 18}, “teacher”, true}; Member temp = stud1;
stud1.cardno = 123456789; stud1.ownname.surname = “Попкец”;stud1.ownname.surname = prep4.ownname.surname;prep4=temp;
А как представить в памяти информацию обо всех членах коллектива, например, факультета?
4. Структурное программирование 4.5. Базовые структуры данных: структуры
Student stud1, stud2, stud3, stud4, stud5, … stud788, stud789, stud790;
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Массив – нумерованная последовательность данных одного типа, которые хранятся в непрерывной области памяти друг за другом. Члены последовательности данных называются элементами массива.
Доступ к элементу массива производится путем указания имени массива и номера элемента.
Нумерация элементов может выполняться одной или несколькими последовательностями целых чисел – индексными последовательностями.
Если нумерация выполняется одной последовательностью говорят, что массив является одномерным, в противном случае – многомерным.
Нумерация элементов массива всегда начинается с 0, а номер каждого следующего члена больше номера предыдущего на 1.
Размещение в памяти массивов:
int b [10]
short x [2][4]
4. Структурное программирование 4.5. Базовые структуры данных: структуры
0b
1 2 3 4 5 6 7 8 9
0,0x
0,1 0,2 0,3 1,0 1,1 1,2 1,3
Внимание!Компилятор гарантирует размещение элементов массива в смежных ячейках памяти!
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Массив определяется: именем (идентификатором); количеством размерностей - числом номеров, необходимых
для указания местонахождения элемента массива; размером (диапазоном изменения индексов) по каждой
размерности.
Конфигурация массива фиксирована. Все элементы массива принадлежат к одному и тому же
типу данных. Элементами массива могут быть как простые переменные
любых типов, так и переменные составных типов (массивов, структур, строк и т.д.).
В качестве индексов в С++ могут использоваться константы и переменные любых целых типов.
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Синтаксис описания одномерного массива
Имя_типа_элемента Имя_массива [Размер]; Имя_типа_элемента Имя_массива [Размер] = {список значений};
Примеры описаний массивов
float b[20] ;
const int n=4;int a[n] = {5, 6,7,8};
5 6 7 8
a
… a[0] a[1] a[2] a[3] …
4 байта
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Примеры описаний массивов
float x[20] = {0} ; Если список инициализации содержит меньше элементов, чем массив, оставшиеся
элементы инициализируются значением 0. Если список содержит больше элементов, чем массив, компилятор генерирует сообщение об ошибке.
double y [ ] = {5.5, 6.8, 8.8, 9.5, 10.3}Если значения элементов перечисляются явно, размер массива можно не
указывать (компилятор определит его по количеству элементов)
5.5 6.8 8.8 9.5 10.3
y
… y[0] y[1] y[2] y[3] y[4] …
8 байтов
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Операция индексирования
Имя_массива [Индекс];
Индекс – целочисленное выражение, значение которого изменяется между 0 и (Размер-1). Для переменной – индекса лучше выбирать тип целый со знаком, так как контроль выхода значений индекса за допустимый диапазон не ведется.
const int n=4;int a[n] = {5, 6,7,8};
int i = 3;a[1] = a[2]+a[i]-6;
5 9 7 8
a
… a[0] a[1] a[2] a[3] …
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Задача.Написать программу, осуществляющую ввод, сложение, вычитание, скалярное умножение двух n-мерных векторов и вывод результатов.
Структура данных для представления n-мерного вектора: одномерный массив размера n типа double.
Расчетные формулы:
....
);,...,,(
);,...,,(
).,...,,( );,...,,(
2211
2211
2211
2121
nn
nn
nn
nn
babababa
babababa
babababa
bbbbaaaa
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Решение задачи:
int main() { const int n=4; double a[n]={0}, b[n]={0}, res[n]={0};
cout << "Enter..." << endl; for (int i=1; i<=n; i++)
{ cout << endl << "a" << i << ": ";
cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}
Если список инициализации содержит меньше значений, чем число элементов массива, оставшиеся элементы будут инициализированы 0
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Решение задачи: for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";
for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;
_getch(); return 0;};
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Задача (Решето Эратосфена).Найти простые числа, меньшие наперед заданного n.
Идея алгоритма Эратосфена: из списка всех чисел от 2 до n последовательно вычеркивать числа, кратные уже известным простым числам.
Основная структура данных программы: одномерный массив размера 2..n типа boolean. Индексы массива соответствуют анализируемым числам. Элемент массива имеет значение true, если индекс этого элемента - простое число.
Алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до n
3.1. Если erato [ i ] == true , 3.1.1. Заменить на false значения элементов массива erato с индексами от i до n, кратными i 4. Вывести значения индексов элементов массива erato , принимающих значение true
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Оптимизируем и уточняем алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true , 3.1.1. Заменить на false значения элементов массива erato с индексами от i до n, равными i * j, где j изменяется от i до n 4. Вывести значения индексов элементов массива erato , принимающих значение true
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Уточняем алгоритм на псевдокоде Данные.Максимальное анализируемое число n Массив, хранящий информацию, простым ли является значение индекса каждого элемента: bool erato [n+1]Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
i = 2j =
erato[i] = true
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
1 1 1 0 1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14
i = 2j = 2
erato[i] = trueerato[4] = false
1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 3
erato[i] = trueerato[6] = false
1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 4
erato[i] = trueerato[8] = false
1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 5
erato[i] == trueerato[10] = false
1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 6
erato[i] == trueerato[12] = false
1 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 7
erato[i] == trueerato[14] = false
1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 8
erato[i] == trueerato[16] = false
1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 2j = 9
erato[i] == truei * j > n
1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 3j = 3
erato[i] == trueerato[9] = false
1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 3j = 4
erato[i] == trueerato[12] = false Повторное присваивание выгоднее проверки!
1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 3j = 5
erato[i] == trueerato[15] = false
1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 3j = 6
erato[i] == truei * j > n
1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = 4j =
erato[i] == false
1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Прокрутка алгоритма вручную Алгоритм.1.Инициализировать константу n2.Объявить массив erato и инициализировать его значениями true 3. Для всех i от 2 до целой части sqrt (n)
3.1. Если erato [ i ] == true, для всех j от i до n выполнять 3.1.1. Если i*j > n выйти из цикла 3.1.2. erato [i*j] = false 4. Вывести значения индексов элементов массива erato , принимающих значение true
i = j =
1 1 0 1 0 1 0 0 0 1 0 1 0 0 0 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Программа на С++ int main() // sieve of Eratosthenes{ const unsigned int n = 1000; const unsigned int size = n+1; bool erato [size]={0};
for (int i = 2; i <= n; i++) erato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (erato[i]) for (int j = i; j <= n; j++) {
if (i*j > n)break;erato [i*j]=false;
} } for(int i=2; i <= n; i++) if (erato[i]) cout << i << endl; _getch(); return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Строки символов в С++ В С++ есть несколько способов представления строк
символов: в виде одномерного массива символов (строки,
завершающиеся нулевым байтом); в виде объекта класса string; другие способы в зависимости от реализации.
Строки, завершающиеся нулевым байтом Описываются как одномерный массив, каждый элемент
которого имеет тип char. Символы строки последовательно располагаются в
элементах массива, начиная с нулевого. В элемент массива, следующий за последним символом
автоматически записывается элемент с ASCII кодом 0: ‘\0’
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Описание строк, завершающихся нулевым байтом Строка описывается как обычный массив символов char Размер массива должен быть на 1 больше длины самой
длинной строки, которую предполагается в этом массиве хранить
char s[10] = “Hello”;
Основные отличия строк от массивов: В процессе выполнения программы отслеживается текущая длина строки Строка в целом может быть проинициализирована значением строкового
литерала (а не только поэлементно символьными значениями) При помещении идентификатора символьного массива в поток cout
выводится не адрес массива, а его содержимое от 0-го элемента до последнего перед завершающим символом \0
H e l l 0 \0
0s
1 2 3 4 5 6 7 8 9
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Самые распространенные функции из <string.h>
Имя Предназначение
strcpy (s1,s2) Копирует строку s2 в строку s1
strcat (s1,s2) Приписывает строку s2 в конец строки s1
strlen (s1) Вычисляет текущую длину строки s1
strcmp (s1,s2) Возвращает 0, если строки совпадают, отрицательное значение, если s1 < s2 и положительное, если s1 > s2
strchr (s1, ch) Возвращает указатель на позицию первого вхождения символа ch в строку s1
strstr (s1, s2) Возвращает указатель на позицию первого вхождения строки s2 в строку s1
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Примерыchar st [20] = “ Good Morning”;
cout << st; // Good Morningstrcpy(st, “Hello”);
cout << st; // Hellostrcpy(st,“”);
G o o d M o r n i n g \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Мусор
H e l l o \0 o r n i n g \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
\0 e l l o \0 o r n i n g \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Основные ограничения на действия со строками, завершающимися нулевым байтомСтроки, как и обычные массивы, нельзя присваивать друг другу, используя оператор присваивания (включая присвоение строке строкового литерала где-либо, кроме начальной инициализации).К строкам, как к обычным массивам, нельзя применять операции сравненияДля строк нет перегруженных операций (например, + для операции конкатенации)Для выполнения операций копирования, конкатенации, сравнения строк и ряда других операций приходится использовать встроенные функции, описанные в заголовке <string.h>
int main() // Basic operations with strings{ char st [20] = "*******************"; // 19 '*‘ char st1 [20];
for (int i=0; i <=19; i++) cout << st[i]; // ******************* cout << endl<< st << " " << strlen (st) << endl; // ******************** 19 strcpy(st,"Good Morning"); for (int i=0; i <=19; i++) cout << st[i]; // Good Morning ****** cout << endl<< st << " " << strlen (st) << endl; // Good Morning 12 strcpy(st,"Hello"); for (int i=0; i <=19; i++) cout << st[i]; // Hello orning ****** cout << endl<< st << " " << strlen (st) << endl; // Hello 5 cout << endl; strcpy(st1, strchr(st, 'e')); cout << st1 << endl; // ello bool i = strchr(st, 'e'); cout << i << endl; // 1 if (strchr(st, 'e')) cout << "char e found"; // char e found _getch(); return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Ввод строк При вводе строки с клавиатуры (помещение в поток cin) следует контролировать длину вводимой строки (чтобы она не превышала длину массива, где будет храниться строка
char str [MAX];cin >> setw (MAX) >> str; // Ввод до MAX-1 символов При помещении строки в поток cin пробелы и символы новой строки конвертируются в завершающий нулевой байт
cin >> setw (MAX) >> str; // Введем строку “Good Morning”cout << str; // Получим GoodЧтобы ввести строку, содержащую пробелы, необходимо вызвать встроенную функцию getline для потока cin:
cin.getline(st, MAX); или char SEP=‘$’; cin.getline (st, MAX, SEP); // Задаем свой разделитель строк
int main() // Counting number of characters into string{ const int MAX = 80; // Maximum array dimension char buffer[MAX]=""; // Input buffer int count = 0; // Character counter
while (true) { cout << "Enter a string of less than 80 characters:\n"; cin.getline(buffer, MAX); if (! strcmp(buffer,"")) break; for(count=0; buffer[count] != '\0'; count++); // The same: count=strlen(buffer) cout << endl << "The string \"" << buffer
<< "\" has " << count << " characters." << endl; } return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Двумерные массивы
Одномерный массивint a[6];
a[0] a[1] a[2] a[3] a[4] a[5]
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Двумерные массивы
Построим массив, состоящий из четырех таких массивовint a[6];
a[0] a[1] a[2] a[3] a[4] a[5]
a[0] a[1] a[2] a[3] a[4] a[5]
a[0] a[1] a[2] a[3] a[4] a[5]
a[0] a[1] a[2] a[3] a[4] a[5]
0
1
2
3
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Двумерные массивы
Построим массив, состоящий из четырех таких массивовint a[6];Перенумеруем элементы, используя два индекса и соответственно опишем этот массив:int a[4][6]
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0][5]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1][5]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2][5]
a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[3][5]
0
1
2
3
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Двумерные массивы
Построим массив, состоящий из четырех таких массивовint a[6];Перенумеруем элементы, используя два индекса и соответственно опишем этот массив:int a[4][6]
В памяти двумерный массив вытянут по строкам
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0][5]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1][5]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2][5]
a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[3][5]
0
1
2
3
int main() // How to initialize two-dimensional arrays{ const int m=4, n =6; // maximum array dimensions int a[m][n] = {{0,1,2,3,4,5}, {10,11,12,13,14,15}, {20,21,22,23,24,25}, {30,31,32,33,34,35}};
int b[m][n] = {0,1,2,3,4,5,10,11,12,13,14,15}; // third & fourth rows are set to zero
int d[m][n] = {0}; // the whole array is set to zero
int c[][n]={{0,1,2,3,4,5}, // first dimension’s size will be calculated by compiler {10,11,12,13,14,15}, {20,21,22,23,24,25}, {30,31,32,33,34,35}};}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
ЗадачаПредставить целочисленную квадратную матрицу 4х4 в виде массива. Присвоить элементам на главной диагонали значение 1, выше главной диагонали - 2, ниже – 0.
44434241
34333231
24232221
14131211
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
a[3][0] a[3][1] a[3][2] a[3][3]
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]
a[3][0] a[3][1] a[3][2] a[3][3] a[3][4]
a[4][0] a[4][1] a[4][2] a[4][3] a[4][4]
]1][1[ jiaij
]][[ jiaij
int main() // working with two-dimensional arrays{ const int n=4; int a[n][n] = {0};
for (int i=0; i<=n-1; i++) for (int j=0; j<=n-1; j++) { if (i == j) a[i][j]=1; else if (i < j) a[i][j]=2; }
for (int i=0; i<=n-1; i++) { cout << endl; for (int j=0; j<=n-1; j++) cout << a[i][j]; } _getch(); return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
1a[0][0]
2a[0][1]
2a[0][2]
2a[0][3]
0a[1][0]
1a[1][1]
2a[1][2]
2a[1][3]
0a[2][0]
0a[2][1]
1a[2][2]
1a[2][3]
0a[3][0]
0a[3][1]
0a[3][2]
1a[3][3]
1 2 2 2
0 1 2 2
0 0 1 2
0 0 0 1
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Многомерные массивыТрехмерный массивfloat x[2][3][4];
x[0][0][0] x[0][0][1] x[0][0][[2] x[0][0][3] x[0][1][0] x[0][1][1]
x[0][1][2] x[0][1][3] x[0][2][[0] x[0][2][1] x[0][2][2] x[0][2][3]
x[1][0][0] x[1][0][1] x[1][0][[2] x[1][0][3] x[1][1][0] x[1][1][1]
x[1][1][2] x[1][1][3] x[1][2][[0] x[1][2][1] x[1][2][2] x[1][2][3]
int main() // sets elements of 3-D array to sin (i+j*k){ const int l=1, m=2, n=3; float x[l+1][m+1][n+1] = {0};
for (int i=0; i<=l; i++) for (int j=0; j<=m; j++) for (int k=0; k<=n; k++) { x[i][j][k] = sin(static_cast <double> (i+j*k)); cout << setw (10) << x [i][j][k]; if (k==n) cout << endl; if (k==n & j==m) cout << endl; }_getch(); return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Массив структур
rfe[0] rfe[1] rfe[2] rfe[3] … rfe[799]
struct Member{ int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; bool tradeunion;};
const int nmembers = 800Member rfe [nmembers];
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
int main() //working with the array of members { struct Date {unsigned short year, month, day;}; struct Name { char surname [80]; char firstname [40]; char patronymic [60]; }; struct Member { int id; Name ownname; Date birth; char address [80]; Date enter; char position [30]; //"student", "teacher", "scientist" or smth.else bool tradeunion; };
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
const int nmembers = 800; Member rfe [nmembers];
//init array rfe Date initdate = {1900,1,1};
for (int i = 0; i < nmembers; i++) { rfe[i].id=0; strcpy(rfe[i].ownname.surname,""); strcpy(rfe[i].ownname.firstname,""); strcpy(rfe[i].ownname.patronymic,""); rfe[i].birth=initdate; rfe[i].enter=initdate; strcpy (rfe[i].position,"student"); rfe[i].tradeunion=false; }
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
// ...
rfe[120].id = 123456; strcpy(rfe[120].ownname.surname,"Poupkin");
// let's admit all students to the trade union for (int i = 0; i < nmembers; i++) if (rfe[i].position == "student") rfe[i].tradeunion = true; //let's print surname for the student with card no 123456 for (int i = 0; i < nmembers; i++) if (rfe[i].id == 123456) cout << i << " " << rfe[i].id << " " << rfe[i].ownname.surname; _getch(); return 0;}
4. Структурное программирование 4.6. Базовые структуры данных: массивы и строки
Инструкция typedef
Позволяет назначить синоним некоторому типу данных.
Синтаксис инструкции
typedef Декларация_Типа Синоним;
Например ,
typedef double MyFloat;
const int nmembers = 800;typedef Member Array_members [nstudents];
Array_members rfe;… Array_memebers humanoids;
4. Структурное программирование 4.7. Сортировка массивов
Сортировка - процесс перестановки заданного множества нумерованных объектов в определенном порядке. Цель сортировки - облегчить последующий поиск элементов в отсортированном множестве.Две категории методов сортировки:
- сортировка массивов- сортировка файлов
a1, a2, … an ak1, ak2, … akn f(ak1) f(ak2) f(ak3) … f(akn)
struct item // typical element of array to be sorted { int key; … // specification of other members of the structure }const n=10;typedef item t_array [n];
4. Структурное программирование 4.7. Сортировка массивов
Принципы построения алгоритмов сортировки массивов:• сортировка на месте• произвольный доступ к элементам
Базовые алгоритмы сортировки массивов: сортировка вставкой (включениями) сортировка выбором (выделением) сортировка обменом (метод «пузырька»)
Базовые операции:- пересылки (присваивания)- сравнения
4. Структурное программирование 4.7. Сортировка массивов
Пусть все рассматриваемые программы начинаются так: int main() // The beginning of all arrays’ sorting programs {
struct item { unsigned int key; // add members you want}; const int n=9; // right boundary of the array to be sortedtypedef item t_array [n+1];t_array s;
srand( static_cast <unsigned int> (time(NULL)));for (int i=0; i<=n; i++) s[i].key = rand()%33;
for (int i=0; i<=n; i++) cout << setw (4) << s[i].key; … }
4. Структурное программирование 4.7. Сортировка массивов
Алгоритм сортировки вставкой массива [0…n]:
1. Для всех i от 1 до n выполнить:
1. 1. Взять очередной i-й неотсортированный элемент и сохранить его в рабочей переменной 1. 2. Найти позицию j в отсортированной (0…i-1) части массива, в которой присутствие взятого элемента не нарушит упорядоченности элементов 1.3. Сдвиг элементов массива от i-1 до j-1 вправо, чтобы освободить найденную позицию вставки 1.4. Вставка взятого элемента в найденную j-ю позицию.
4. Структурное программирование 4.7. Сортировка массивов
12 3 7 1 8 0
0 1 2 3 4 5
i = 1
3 work
j = 0
Сортировка вставкой : 1-й проход
4. Структурное программирование 4.7. Сортировка массивов
12 12 7 1 8 0
0 1 2 3 4 5
i = 1
3 work
j = 0
Сортировка вставкой : 1-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 12 7 1 8 0
0 1 2 3 4 5
i = 1
3 work
j = 0
Сортировка вставкой : 1-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 12 7 1 8 0
0 1 2 3 4 5
i = 2
7 work
j = 1
Сортировка вставкой : 2-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 12 12 1 8 0
0 1 2 3 4 5
i = 2
7 work
j = 1
Сортировка вставкой : 2-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 7 12 1 8 0
0 1 2 3 4 5
i = 2
7 work
j = 1
Сортировка вставкой : 2-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 7 12 1 8 0
0 1 2 3 4 5
i = 3
1 work
j = 0
Сортировка вставкой : 3-й проход
4. Структурное программирование 4.7. Сортировка массивов
3 3 7 12 8 0
0 1 2 3 4 5
1 work
i = 3j = 0
Сортировка вставкой : 3-й проход
4. Структурное программирование 4.7. Сортировка массивов
1 3 7 12 8 0
0 1 2 3 4 5
1 work
i = 3j = 0
Сортировка вставкой : 3-й проход
4. Структурное программирование 4.7. Сортировка массивов
Простейшая программа сортировки вставкой: int main() {
…
item work; int i=0, j=0, k=0;for(i=1; i<=n; i++){
work=s[i]; // taking first non-sorted element for (j=i-1; work.key < s [j].key; j++); // search insert position for (k=i-1; k>=j; k--) s[k+1]=s[k]; //shift s[j]=work; // insert
}cout << endl;for (int i=0; i<=n; i++) cout << setw (4) << s[i].key;_getch(); return 0;
}
4. Структурное программирование 4.7. Сортировка массивов
Оптимизированная программа сортировки вставкой: int main() { …
item work; int i=0, j=0;
for(i=1; i<=n; i++) {
work=s[i]; // taking first non-sorted elementfor (j = i-1; (work.key < s[j].key) && (j >= 0) ; j--) s[j+1] = s[j]; //search & shifts[j+1]=work; // insert
}
cout << endl; for (int i=0; i<=n; i++) cout << setw (4) << s[i].key; _getch(); }
4. Структурное программирование 4.7. Сортировка массивов
Алгоритм сортировки выбором массива [0…n]
1. Для всех i от 0 до n выполнять:
1.1. Найти в части массива от i-го до n-го элемента элемент с минимальным значением ключа и поменять его местами с i-м элементом.
4. Структурное программирование 4.7. Сортировка массивов
12 3 7 1 8 0
0 1 2 3 4 5
i = 0
0 min
j = 5
Сортировка выбором : 1-й проход
4. Структурное программирование 4.7. Сортировка массивов
0 3 7 1 8 12
0 1 2 3 4 5
i = 0
0 min
j = 5
Сортировка выбором : 1-й проход
4. Структурное программирование 4.7. Сортировка массивов
0 3 7 1 8 12
0 1 2 3 4 5
i = 1
1 min
j = 3
Сортировка выбором : 2-й проход
4. Структурное программирование 4.7. Сортировка массивов
0 1 7 3 8 12
0 1 2 3 4 5
i = 1
1 min
j = 3
Сортировка выбором : 2-й проход
4. Структурное программирование 4.7. Сортировка массивов
Программа сортировки выбором int main() { …
item min; int imin=0, i=0, j=0; for (i=0; i<=n-1; i++) {
for (j = i+1, min = s[i], imin = i; j <= n; j++) // search min element if (s[j].key < min.key) {
min = s[j]; imin = j; }
s[imin]=s[i]; s[i]=min; //change elements } … return 0; }
4. Структурное программирование 4.7. Сортировка массивов
Алгоритм сортировки обменом (метод «пузырька»)
1. Для всех k от n до 1 выполнять :
1.1. Слева направо поочередно сравнивать два соседних элемента и если их взаиморасположение не соответствует заданному условию упорядоченности, то менять их местами.
4. Структурное программирование 4.7. Сортировка массивов
12 3 7 1 8 4
0 1 2 3 4 5
i = 0 k = 5
Сортировка обменом: 1-й проход
i +1= 1
4. Структурное программирование 4.7. Сортировка массивов
3 12 7 1 8 4
0 1 2 3 4 5
i = 1 k = 5
Сортировка обменом: 1-й проход
i +1= 2
4. Структурное программирование 4.7. Сортировка массивов
3 7 12 1 8 4
0 1 2 3 4 5
i = 2 k = 5
Сортировка обменом: 1-й проход
i +1= 3
4. Структурное программирование 4.7. Сортировка массивов
3 7 1 12 8 4
0 1 2 3 4 5
i = 3 k = 5
Сортировка обменом: 1-й проход
i +1= 4
4. Структурное программирование 4.7. Сортировка массивов
3 7 1 8 12 4
0 1 2 3 4 5
i = 4 k = 5
Сортировка обменом: 1-й проход
i +1= 5
4. Структурное программирование 4.7. Сортировка массивов
3 7 1 8 4 12
0 1 2 3 4 5
Сортировка обменом: 2-й проход
i = 0 k = 4i +1= 1
4. Структурное программирование 4.7. Сортировка массивов
3 7 1 8 4 12
0 1 2 3 4 5
Сортировка обменом: 2-й проход
i = 1 k = 4i +1= 2
4. Структурное программирование 4.7. Сортировка массивов
3 1 7 8 4 12
0 1 2 3 4 5
Сортировка обменом: 2-й проход
i = 2 k = 4i +1= 3
4. Структурное программирование 4.7. Сортировка массивов
3 1 7 8 4 12
0 1 2 3 4 5
Сортировка обменом: 2-й проход
i = 3 k = 4
i +1= 4
4. Структурное программирование 4.7. Сортировка массивов
3 1 7 4 8 12
0 1 2 3 4 5
Сортировка обменом: 3-й проход
i = 0 k = 3i +1= 1
4. Структурное программирование 4.7. Сортировка массивов
1 3 7 4 8 12
0 1 2 3 4 5
Сортировка обменом: 3-й проход
i = 1 k = 3i +1= 2
4. Структурное программирование 4.7. Сортировка массивов
1 3 7 4 8 12
0 1 2 3 4 5
Сортировка обменом: 3-й проход
i = 2 k = 3
i +1= 3
4. Структурное программирование 4.7. Сортировка массивов
1 3 4 7 8 12
0 1 2 3 4 5
Сортировка обменом: 4-й проход ?
i = 0 k = 3i +1= 1
4. Структурное программирование 4.7. Сортировка массивов
Программа сортировки методом пузырька int main() { …
item work; for (int k=n; k>=1; k--) for (int i=0; i<=k-1; i++) if (s[i].key > s[i+1].key)
{ work=s[i]; s[i]=s[i+1]; s[i+1]=work;
} … return 0; }
4. Структурное программирование 4.7. Сортировка массивов
Усовершенствованный метод пузырька int main() { …
item work; bool flag = true;
for (int k=n; (k>=1) && flag; k--) { flag=false; for (int i=0; i<=k-1; i++) if ( s[i].key > s[i+1].key ) {
work=s[i]; s[i]=s[i+1]; s[i+1]=work; flag=true; } }return 0}
4. Структурное программирование 4.7. Сортировка массивов
Вычислительная сложность алгоритмов сортировки массивов
1.Сортировка вставкой for(i=1; i<=n; i++) { work=s[i]; // taking first non-sorted element for (j = i-1; (work.key < s[j].key) && (j >= 0) ; j--) s[j+1] = s[j]; //search & shift s[j+1]=work; // insert } Число сравнений при i-м просеивании Ci = 1 i-1,
в среднем Ci= i/2
Число присваиваний (пересылок) M i = (C i -1)+2 = = C i +1
Cmin= n = N-1 (где N – размер массива)
M min= 2*n = 2*(N-1)
4. Структурное программирование 4.7. Сортировка массивов
Cmin= N-1
M min= 2*(N-1)
N-1
Cср= i/2 = (1/2+1/2(N-1))*(N-1)/2= ¼(N2-N)
i=1N-1
Mср= (i/2+2) = (5/2 + ½(N-1)+2)*(N-1) / 2 = ¼(N2+7N-16)
i=1N-1
Cmax= (i-1) = (0 + N-1)*(N - 1) / 2 = ½ (N2-N)
i=1N-1
Mmax= (i+1) = (2 + N-1)*(N - 1) / 2 = ½(N2-1)
i=1
Число сравнений при i-м просеивании Ci = 1 i-1,
в среднем Ci= i/2
Число присваиваний (пересылок) M i = (C i -1)+2 = = C i +1
Cmin= n = N-1 (где N – размер массива)
M min= 2*n = 2*(N-1)
4. Структурное программирование 4.7. Сортировка массивов
2. Сортировка выборомЧисло сравнений не зависит от начального порядка ключейC = ½ (n2-n)M ср= n(ln n + ), =0,577216…
3. Сортировка обменом (метод «пузырька»)Число сравнений не зависит от начального порядка ключейC = ½ (n2-n)M ср= ¾ (n2-n)
4. Структурное программирование 4.7. Сортировка массивов
Алгоритм бинарного поиска в массиве размера n+1
1.Положить left=0, right=n;2.Пока left < right выполнять
3.1. Найти индекс среднего элемента в массиве mid = (left+right)/2
3.2. Если для элемента массива с индексом mid значение ключа > искомого, положить right =mid-1, иначе если значение ключа < искомого, положить left = mid+1, иначе выйти из цикла (элемент с индексом mid найден);
3.Если значение ключа элемента с индексом mid совпадает с заданным, поиск успешен, иначе – искомого элемента в массиве нет.
4. Структурное программирование 4.7. Сортировка массивов
int main() // Binary search in array {
struct item {unsigned int key;
// add members you want}; const int n=9; // right boundary of the array typedef item t_array [n+1];t_array s; unsigned int key_to_find=0;
for (int i=0; i<=n; i++) s[i].key = i+10;for (int i=0; i<=n; i++) cout << setw (4) << s[i].key;
4. Структурное программирование 4.7. Сортировка массивов
cout << "\nEnter your value of key: "; cin >> key_to_find;
int left = 0, right = n, mid = 0; while (left <= right){
mid = (left+right)/2;if (s[mid].key > key_to_find) right = mid-1;else if (s[mid].key < key_to_find)left = mid+1;else break;
}if (s[mid].key == key_to_find) cout << "\nOK, element no " << mid;else cout << "\nThere is no element with required value of key";cout << endl;
_getch(); return 0;}
4. Структурное программирование 4.8. Указатели
Что такое указателиКаждый байт в памяти ЭВМ имеет адрес по которому можно обратиться к определенному элементу данныхУказатель – это переменная, которая сохраняет адрес другой переменной определенного типа.
Содержимое указателя содержит адрес, начиная с которого размещается переменная, на которую ссылается указатель.
По описанию указателя компилятор получает информацию о том, какова длина области памяти, на которую ссылается указатель (которую занимает переменная, на которую он ссылается) и о том, как интерпретировать данные в этой области памяти.
Таким образом, переменная-указатель обладает именем и имеет тип, определяющий на какого рода данные она может ссылаться.
4. Структурное программирование 4.8. Указатели
Объявление указателя: Базовый_тип *Имя_Указателя;
int k = 0;short j=0;int *p_i = NULL;
NULL 0 0
0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A
2 байта
p_i k j
4. Структурное программирование 4.8. Указатели
Операция взятия адреса: &Имя_Переменной
p_i = &k
0013FF56 0 0
0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A
p_i k j
4. Структурное программирование 4.8. Указатели
Операция взятия адреса
нельзя p_i = &j; (p_i – указатель на int, a j объявлена как short)
0013FF56 0 0
0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A
p_i k j
4. Структурное программирование 4.8. Указатели
Операция разыменования: *Имя_Указателя
*p_i = 123; // k = 123
0013FF56 123 0
0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A
p_i k j
123
4. Структурное программирование 4.8. Указатели
Операция разыменования
j = *p_i; // j = k
0013FF56 123 123
0013FF50 0013FF52 0013FF54 0013FF56 0013FF58 0013FF5A
p_i k j
4. Структурное программирование 4.8. Указатели
Операция взятия адреса: как размещаются в памяти переменные и элементы массивов
int main() {
short c1 = '1', c2 = '2', c3 = '3';short c4[3] = {1,2,3};
cout << &c1 << endl; // 0013FF5С cout << &c2 << endl; // 0013FF50
cout << &c3 << endl; // 0013FF44 cout << endl;
cout << &c4[1] << endl; // 0013FF36cout << &c4[2] << endl; // 0013FF38
cout << &c4[3] << endl; // 0013FF40
return 0; }
Debug Mode
12 байт между адресами переменных
2 байта между адресами элементов массива, строго упорядочены
4. Структурное программирование 4.8. Указатели
Операция взятия адреса: как размещаются в памяти переменные и элементы массивов
int main() {
short c1 = '1', c2 = '2', c3 = '3';short c4[3] = {1,2,3};
cout << &c1 << endl; // 0013FF70 cout << &c2 << endl; // 0013FF68
cout << &c3 << endl; // 0013FF6C cout << endl;
cout << &c4[1] << endl; // 0013FF76cout << &c4[2] << endl; // 0013FF78
cout << &c4[3] << endl; // 0013FF7A
return 0; }
Release Mode
2 байта между адресами переменных, неупорядочены
2 байта между адресами элементов массива, строго упорядочены
4. Структурное программирование 4.8. Указатели
Особенности синтаксиса объявления указателейПервый способ записи:
Базовый_тип *Имя_Указателя;Нет проблем с объявлением нескольких указателей:
int *pa, *pb, *pc;Второй способ записи:
Базовый_тип* Имя_Указателя;Позволяет идентифицировать тип «указатель на базовый тип» как Базовый_тип* . Однако , эта форма записи вызывает проблемы при множественном объявлении перемненых:
int* pa, ib, ic;Во избежание путаницы, если Вы придерживаетесь второго способа, никогда не декларируйте в одном инструкции более одной (указательной) переменной. В качестве базового типа можно указать void: void *p; Указатель на void не может быть разыменован
4. Структурное программирование 4.8. Указатели
Инициализация указателейУказатель можно инициализировать адресом переменной, которая уже определена:double dvar = 0.0;double *pvar = &dvar;
Инициализация значением NULL гарантирует, что указатель не содержит адреса, который воспринимается как корректный, а значение можно проверить в инструкции if :int *pinteger = NULL;if (pinteger == NULL) cout << “pinteger is null”;
равнозначная альтернатива инициализировать указатель 0:int *pinteger = 0;if (!pinteger) cout << “pinteger is null”;
4. Структурное программирование 4.8. Указатели
Присваивание указателей. Неявное приведение типов.int main(){ int x=0; int *pi_1=NULL, *pi_2=NULL; double *pd_1=NULL; void *pv_1=NULL;
pi_1 = &x; pi_2 = pi_1;// pd_1=pi_1; prohibited !!! pv_1=pi_1; // pi_2=pv_1; prohibited !!!
return 0}
4. Структурное программирование 4.8. Указатели
Присваивание указателей. Явное приведение типов
int main() { int x=123; int *pi_1=NULL; float *pf_1=NULL; double *pd_1=NULL;
pi_1 = &x; cout << pi_1 << " " << *pi_1 << endl; // 0013FF60 123 pf_1=reinterpret_cast <float*> (pi_1); cout << pf_1 << " " << *pf_1 << endl; // 0013FF60 1.7236e-043 pd_1=reinterpret_cast <double*> (pi_1); cout << pd_1 << " " << *pd_1 << endl; // 0013FF60 -9.25596e+061 return 0}
Используйте reinterpret_cast только по большой нужде!!!
4. Структурное программирование 4.8. Указатели
Явное приведение типов. Почти катастрофа.
short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1); *pf = 12345e99;
0013FF34 1 3 2
0013FF30 0013FF32 0013FF34 0013FF36 0013FF38 0013FF3A 0013FF3C 0013FF3E
c1 c2c3pf
4. Структурное программирование 4.8. Указатели
Явное приведение типов. Почти катастрофа.
short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1); *pf = 12345e99;
0013FF34 1.2345e103 2
0013FF30 0013FF32 0013FF34 0013FF36 0013FF38 0013FF3A 0013FF3C 0013FF3E
c1 c2c3pf
4. Структурное программирование 4.8. Указатели
Явное приведение типов. Почти катастрофа.
int main() { short c1=1, c2=2, c3=3; double *pf = reinterpret_cast <double*> (&c1);
cout << &c1 << endl; // 0013FF34 cout << &c2 << endl; // 0013FF3C cout << &c3 << endl; // 0013FF38
cout << c1 << c2 << c3 << endl; // 1 2 3 *pf = 12345e99; cout << *pf << endl; // 1.2345e103 cout << c1 << c2 << c3 << endl; // 30764 2 3090 _getch(); return 0;}
4. Структурное программирование 4.8. Указатели
Адресная арифметикаК указателям можно применять только две арифметические операции: сложения и вычитания. При добавлении к указателю целого числа N значение указателя увеличивается на N*L, где L – длина базового типа на котороый ссылается указатель. При вычитании N значение указателя уменьшается на N*L. (Говоря другими словами, мы смещаемся в памяти на N длин элементов базового типа.Указатели можно вычитать. Результатом вычитания является количество объектов базового типа, которые можно расположить между указателями.Нельзя производить вычитание разнотипных указателей.Нельзя складывать указатели
Использовать арифметику указателей, как правило, имеет смысл только применительно к элементам массивов
4. Структурное программирование 4.8. Указатели
0013FF60 0 1 4 9 16 25
K[0] K[1] k[2] k[3] K[4] K[5]
F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B
36 49 64
k[6] K[7] K[8]
F6C F6D F6E F6F F70 F71 F72 F73 F74
p k
short k [10] = {0};short *p = k; // pointer to the first element, the same like *p=&k[0]for (int i=0; i<=8; i++) k[i]= i*i; cout << &p << endl; // 0013FF5C where the pointer p is placedcout << k << " " << &k << " " << p << endl; //0013FF60 0013FF60 0013FF60 cout << *k << " " <<*p << endl; // 0 0
Адресная арифметика: пример с одномерным массивом
Исходное состояние:
4. Структурное программирование 4.8. Указатели
0013FF64 0 1 4 9 16 25
k[0] k[1] k[2] k[3] k[4] k[5]
F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B
p k
p+=3; // k++; prohibited: can’t change address of arraycout << k+3 <<" "<< p << endl; // 0013FF66 //0013FF66 cout << *(k+3) << " " << *p; // 9 9
Адресная арифметика: пример с одномерным массивом
Исходное состояние: 36 49 64
K[6] K[7] K[8]
F6C F6D F6E F6F F70 F71 F72 F73 F74
k+3
4. Структурное программирование 4.8. Указатели
0013FF64 0 1 4 9 16 25
k[1] k[2] k[3] k[4] k[5] k[6]
F5С F5D F5E F5F F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F6A F6B
p k
cout << &k[6] - &k[2]; // 4 // cout << &p - & k[1]; prohibited: different basic types of pointers
Адресная арифметика: пример с одномерным массивом
Исходное состояние: 36 49 64
k[7] k[8] k[9]
F6C F6D F6E F6F F70 F71 F72 F73 F74
4. Структурное программирование 4.8. Указатели
Сравнение указателейУказатели можно сравнивать между собой. Как правило, указатели сравнивают, когда они ссылаются на один и тот же объект, например, массив. Сравнивать указатели, если их базовый тип различается, нельзя. Если это необходимо, следует воспользоваться операцией приведения типа reinterpret_cast. (Либо присвоить их значения указателям на void, что выглядит достаточно гнусно).
4. Структурное программирование 4.8. Указатели
Указатели и одномерные массивыПо сути, объявляя массив, мы объявляем имя массива как указатель на его первый элемент. Так, пусть объявлен массив m и указатель ps:short m [8];short *ps;Идентификатор m будет восприниматься как указатель на первый элемент, значение которого нельзя изменить (константный указатель).C именем массива можно работать как с указателем на первый элемент:ps = m;cout << m << ps; // 0013FEDC 0013FEDC
4. Структурное программирование 4.8. Указатели
Указатели и массивы : информация к размышлению int main() { typedef int t_array_int [4]; t_array_int a={1,2,3,4}, b={10,20,30,40}; int *pint, *pint1=NULL; t_array_int *parint=NULL;
cout << "a= " << a << endl; // 0013FF54 pint=a; cout << "pint=a " << pint << endl; // 0013FF54 pointer to the first element // parint=a; prohibited!!!// pint=&a; prohibited!!! parint=&a; cout<< "parint=&a " << parint << endl; // 0013FF54 pointer to the whole array// parint=&pint; prohibited!!! cout << "*pint " << *pint << endl; // 1 cout << "*parint " << *parint << endl; // 0013FF54 cout << "**parint " << **parint << endl; // 1// a=b; prohibited !!! pint1=b; pint=pint1; cout << "pint " << pint << endl; // 0013FF3C cout << "*pint+2 " << *(pint+2); // 30
4. Структурное программирование 4.8. Указатели
Указатели и одномерные массивыПрименяя к идентификатору одномерного массива операцию [n], мы смещаемся на n элементов относительно начала и разыменовываем полученный указатель на n-й элемент массива. То же можно сделать явно, используя адресную арифметику
short a [8] = {10,11,12,13,14,15,16,17};cout << a [3]; // 13cout << *(a+3); // 13
10 11 12 13 14 15 16 17
0 1 2 3 4 5 6 7
a[0]
a
a[3]
a+3
4. Структурное программирование 4.8. Указатели
Указатели и многомерные массивыВ случае многомерного массива смещение можно рассчитать вручную, учитывая, что в С++ многомерные массивы вытягиваются в памяти «по строкам» (вначале изменяется крайний правый индекс, потом второй справа и т.д.). const int m=3, n=4; int ai [m][n] = { {0, 1, 2, 3}, {10, 11, 12, 13} , {20, 21, 22, 23} };int *pi=&ai[0][0];int i=2, j=2;cout << ai [i][j] << endl; // 22cout << *(pi+(j+i*n)) << endl; // 22
0 1 2 3 10 11 12 13 20 21 22 23
[0][0] [0][1] [0][2] [0][3] [1][0] [1][1] [1][2] [1][3] [2][0] [2][1] [2][2] [2][3]
ai[0][0]
pi
ai[2][2]
pi+(j+i*n)
4. Структурное программирование 4.8. Указатели
Указатели и многомерные массивыИдентификатор многомерного массива трактуется как указатель на массив (для двумерного массива - указатель на первую строку). Исходя из этого, можно поступить и иначе:
const int m=3, n=4; int ai [m][n] = { {0, 1, 2, 3}, {10, 11, 12, 13} , {20, 21, 22, 23} };
int i=2, j=2;cout << ai [i][j] << endl; // 22cout << * (*(ai+i)+j) // 22
0 1 2 3 10 11 12 13
[0][0] [0][1] [0][2] [0][3] [1][0] [1][1] [1][2] [1][3] [2][0] [2][1] [2][2] [2][3]
aik+i
* (ai+i)
*(ai+i)+j
4. Структурное программирование 4.8. Указатели
Массивы указателейНикто не мешает нам описать не просто указатель на int, но и массив указателей на int:
int * pparint [10];
int a=0;int b=1;pparint [1]=&a;pparint [2]=&b;*pparint[1]= *pparint[2];cout << pparint[1] << pparint[2];cout << *pparint[1] << *pparint[2];
4. Структурное программирование 4.8. Указатели
Указатели и строки Имя массива элементов типа char трактуется, как и для любых других массивов как указатель на его первый (номер 0) элемент. Особенность: в контексте программы имя массива типа char автоматически разыменовывается, в результате чего мы получаем строку, начинающуюся с первого (номер 0) элемента и заканчивающуюся нулевым символом. Интересно, что указатель на char тоже автоматически разыменовывается по тем же правилам. То есть, в результате выполненияchar c=‘a’;char *pc=&c;cout << pc; // aивесьмусорвпамятидоближайшегонулевогоэлементаcout << *pc; // acout << &pc ; // 0013FF0C
4. Структурное программирование 4.8. Указатели
Указатели и строки : информация к размышлению
typedef char t_array_char [4];t_array_char c="abc";char *pchar=NULL;t_array_char *parchar=NULL;
cout << "c= " << c << endl; // abcpchar=c; cout << "pchar=c " << pchar << endl; // abc
// parchar=c; prohibited!!!// pchar=&c; prohibited!!!
parchar=&c; cout<< "parchar=&c " << parchar << endl; // 0013FF0C// parint=&pint; prohibited!!!
cout << "*pchar " << *pchar << endl; // acout << "*parchar " << *parchar << endl; // abc
cout << "**parchar " << **parchar << endl; // a// a=b; prohibited !!!
cout << "*pchar+2 " << *(pchar+2); // c
4. Структурное программирование 4.8. Указатели
Инициализация указателей на char Раньше мы инициализировали строкой массивы типа char.Указатель на символ !!! char* также можно инициализировать строковым литералом. В этом случае указатель будет содержать адрес, по которому в оперативной памяти, в т.н. «таблице строк», размещен строковый литерал – неименованная константа
char *pverb=“Hello”;
Изменение в программе значения такого указателя – весьма дурной тон. C формальной точки зрения в С++ строковый литерал имеет тип не char* , а const char*. Просто в языке С++ предусмотрено автоматическое преобразование типа const char* в тип char*. Хорошим стилем считается, если Вы пишете программу на С++ , строковый литерал считать константным и объявлять:
const char *pverb = “Hello”;
4. Структурное программирование 4.8. Указатели
Инициализация указателей на char . Пример
int main() // prints the string forward and backwards {
const char *p="Hello";cout << "*p= " <<*p << endl; // Hcout << "p = " << p << endl << endl; // Hello
for (int t = strlen(p)-1 ; t >= 0; t--) cout << p[t]; // olleH
cout << endl;_getch(); return 0;
}
4. Структурное программирование 4.8. Указатели
Указатели на структурыОбъявление указателя на структуру ничем не отличается от обычного:
struct cmplx{ double re; double im;};
cmplx c1, c2;cmplx *pc;pc = &c1;
4. Структурное программирование 4.8. Указатели
Указатели на структурыДля доступа к членам структуры по указателю на нее можно воспользоваться операцией разыменования:(*pc).re = 1; cout << c1.re; // 1
Однако, лучше использовать специальную операцию ссылки на член структуры (оператор «стрелка»):pc->re = 2; cout << c1.re; // 2pc->im = pc->re;pc=&c2;pc->re=c1.re;pc->im=c1.im;
Итак, оператор «.» используется для непосредственного обращения к членам структуры, а оператор «->» для доступа к членам структуры через указатель на нее.
4. Структурное программирование 4.8. Указатели
Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3
NULL NULL 3
F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55
ppshort pshort a
4. Структурное программирование 4.8. Указатели
Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3
NULL 0013FF52 3
F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55
ppshort pshort a
4. Структурное программирование 4.8. Указатели
Указатель на указательshort **ppshort=NULL;short *pshort=NULL;short a=3;pshort=&a;ppshort = &pshort;cout << ppshort << *ppshort << **ppshort // 0013FF4C 0013FF52 3
0013FF4C 0013FF52 3
F48 F49 F4A F4B F4C F4D F4E F4F F50 F51 F52 F53 F54 F55
ppshort pshort a
4. Структурное программирование 4.8. Указатели
Операция sizeof Операция sizeof будучи применена к какому-либо объекту возвращает целое число – количество байт, занимаемых ее операндом.
int m=0; double k=0;char *pchar;short l [6][5];
cout << sizeof m; // 4cout << sizeof k ; // 8cout << sizeof pchar; // 4cout << sizeof *pchar; // 1cout << sizeof l ; // 60 bytes cout << (sizeof l) / (sizeof l[0][0]) ; // 30 number of elementscout << (sizeof l) / (sizeof l[0]) ; // 6 number of rows
4. Структурное программирование 4.9. Ссылки
Ссылки Ссылка (reference) – псевдоним для другой переменной. Ссылка имеет имя, которое может использоваться вместо имени переменной. Так как ссылка – это псевдоним, а не указатель, переменная, для которой она определяется, должна быть объявлена ранее. В отличие от указателя ссылка не может быть изменена, чтобы представлять другую переменную Объявление и инициализация: Базовый_тип &Имя_Ссылки = Имя_Переменной;
int number = 0;int &rnumber = number; // ссылка int *pnumber = &number // указательСсылку, можно использовать вместо имени исходной переменной:
rnumber +=10;*pnumber +=10; // требуется разыменование Ссылка подобна указателю, который уже разыменован и значение которого нельзя изменить.
4. Структурное программирование 4.9. Ссылки
Ссылки чаще всего используют для передачи аргументов в функции, однако иногда их можно использовать в качестве синонимов для упрощения текста программы.
Например, вместо //init array rfe Date initdate = {1900,1,1}; for (int i = 0; i < nmembers; i++) { rfe[i].id=0; strcpy(rfe[i].ownname.surname,""); strcpy(rfe[i].ownname.firstname,""); strcpy(rfe[i].ownname.patronymic,""); rfe[i].birth=initdate; rfe[i].enter=initdate; strcpy (rfe[i].position,"student"); rfe[i].tradeunion=false; }
4. Структурное программирование 4.9. Ссылки
Можно записать
//init array rfe Date initdate = {1900,1,1}; for (int i = 0; i < nmembers; i++) { Member &t = rfe[i]; t.id=0; strcpy(t.ownname.surname,""); strcpy(t.ownname.firstname,""); strcpy(t.ownname.patronymic,""); t.birth=initdate; t.enter=initdate; strcpy (t.position,"student"); t.tradeunion=false; }
4. Структурное программирование 4.10. Динамическое распределение памяти
Память для глобальных переменных распределяется на этапе компиляции и выделяется при загрузке программы в память.
Память для локальных переменных выделяется в области стека в момент начала выполнения функции.
Мы не можем в процессе выполнения программы объявить новые локальные или глобальные переменные, хотя необходимость этого может выясниться только в процессе выполнения.
Мы не можем работать со структурами данных, размер которых может изменяться в процессе выполнения программы (списки, стеки, очереди, деревья)
Механизм динамического распределения памяти позволяет программе получать необходимую для хранения данных память в процессе своего выполнения.
Для получения доступа к динамически выделяемым областям памяти и их типизации служат указатели.
4. Структурное программирование 4.10. Динамическое распределение памяти
В языке С++ имеются два оператора динамического распределения памяти: new и delete. (В С используются функции malloc() и free()).
Выделение памяти:
Имя_Указателя = new Тип;
Имя_Указателя = new Тип (инициализирующее_значение);
Освобождение памяти:
delete Имя_Указателя;
Разумеется, перед использованием оператора new следует описать используемый указатель.
4. Структурное программирование 4.10. Динамическое распределение памяти
NULL NULL …
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
NULL 003B619D …
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
NULL 003B619D … 4.5
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
003B61A1 003B619D … 4.5 3
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
003B61A1 003B619D … 3.0 3
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
003B61A1 003B619D … 3.0
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
003B61A1 003B619D …
F5С F5D F5E F5F F60 F61 F62 F63 … 19D 19E 19F 1A0 1A1 1A2
float *pf=NULL;short *ps=NULL;pf = new float;*pf = 4.5;cout << &pf <<pf << *pf; // 0013FF60 003B619D 4.5ps= new short (3);*pf = *ps;delete ps;delete pf;
Динамическое выделение памяти для переменных
ps pf
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 …
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;
Динамическое выделение памяти для структур
pc
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 … 1.0 0.0
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;
Динамическое выделение памяти для структур
pc
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 …
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
struct cmplx{ double re; double im;};cmplx *pc = new cmplx;cout << &pc << endl; // 0013FF5Сcout << pc; // 003B6188pc->re=1.0;pc->im=0;cout <<pc->re; // 1delete pc;
Динамическое выделение памяти для структур
pc
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 …
pa[0] pa[1] pa[2] pa[3]
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;
Динамическое выделение памяти для одномерных массивов
pa
Обратите внимание на особенности выделения памяти для массива:
-указатель объявляется на базовый тип массива;- размер массива указывается в квадратных скобках после идентификатора типа в new -допустим неконстантный размер массива
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 … 0 1 4 9
pa[0] pa[1] pa[2] pa[3]
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;
Динамическое выделение памяти для одномерных массивов
pa
Обратите внимание: -для получения доступа к элементу массива разыменовывать указатель не надо! Операция [ ] вычисляет адрес элемента массива и разыменовывает соответствующий указатель
4. Структурное программирование 4.10. Динамическое распределение памяти
003B6188 …
F5С F5D F5E F5F … 188 189 19A 19B 19C 19D 19E 19F
int k=0; cin >> k; // 4short *pa = new short [k];cout << &pa << endl; // 0013FF5Сcout << pa; // 003B6188for (int i=0; i<=3; i++) pa[i]=i*i;cout << *pa; // 0cout << pa[2]; // 4delete [ ] pa;
Динамическое выделение памяти для одномерных массивов
pa
Обратите внимание на особенности освобождения
памяти от массива: - квадратные скобки после delete,- размер массива не указывается!
Ранее разработанная программа работы с n-мерными векторами
4. Структурное программирование 4.10. Динамическое распределение памяти
int main() { const int n=4; double a[n]={0}, b[n]={0}, res[n]={0};
cout << "Enter..." << endl; for (int i=1; i<=n; i++)
{ cout << endl << "a" << i << ": ";
cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}
Ранее разработанная программа работы с n-мерными векторами
4. Структурное программирование 4.10. Динамическое распределение памяти
for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";
for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;
_getch(); return 0;};
Новая версия программы работы с n-мерными векторами
4. Структурное программирование 4.10. Динамическое распределение памяти
int main() {int n=0; cout << "Enter dimension n: "; cin >> n; double* a = new double[n]; double* b = new double[n]; double* res = new double[n];
cout << "Enter..." << endl; for (int i=1; i<=n; i++)
{ cout << endl << "a" << i << ": ";
cin >> a[i-1]; cout << "b" << i << ": "; cin >> b[i-1];}
Новая версия программы работы с n-мерными векторами
4. Структурное программирование 4.10. Динамическое распределение памяти
for (int i=1; i<=n; i++) res[i-1]=a[i-1]+b[i-1]; //Sum cout << endl << "a + b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")";
for (int i=1; i<=n; i++) res[i-1]=a[i-1]-b[i-1]; //Difference cout << endl << "a - b = ( "; for (int i=1; i<=n; i++) cout << res[i-1] << " "; cout << ")"; double r=0; for (int i=1; i<=n; i++) r+=a[i-1]*b[i-1]; //Product cout << endl << "a * b = " << r;
_getch(); return 0;};
Ранее разработанная программа нахождения простых чисел
int main() // sieve of Eratosthenes{ const unsigned int n = 1000; const unsigned int size = n+1; bool erato [size]={0};
for (int i = 2; i <= n; i++) erato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (erato[i]) for (int j = i; j <= n; j++) {
if (i*j > n)break;erato [i*j]=false;
} } for(int i=2; i <= n; i++) if (erato[i]) cout << i << endl;return 0;}
4. Структурное программирование 4.10. Динамическое распределение памяти
Новая программа нахождения простых чисел int main() // sieve of Eratosthenes: dynamic store allocation{ int n = 0; cout << "Enter max number:"; cin >> n; if (n <= 0)return -1; bool *perato = new bool [n+1];
for (int i = 2; i <= n; i++) perato [i] = 1; for (int i = 2; i <= static_cast <int> (sqrt(static_cast <float> (n))); i++) { if (perato[i]) for (int j = i; j <= n; j++) {
if (i*j > n)break;perato [i*j]=false;
} } for(int i=2; i <= n; i++) if (perato[i]) cout << i << endl; delete [ ] perato; return 0;}
4. Структурное программирование 4.10. Динамическое распределение памяти
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr int * int
int **pr;
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]
int *
int *
int *
…
int *
0
1
2
n-1
int
int
int
int
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];
int *
int *
int *
…
int *
0
1
2
n-1
int int … int
int int … int
int int … int
int int … int
0 1 m-1
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];
int *
int *
int *
…
int *
0
1
2
n-1
int int … int
int int … int
int int … int
int int … int
0 1 m-1
pr
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];
int *
int *
int *
…
int *
0
1
2
n-1
int int … int
int int … int
int int … int
int int … int
0 1 m-1
pr *
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];
int *
int *
int *
…
int *
0
1
2
n-1
int int … int
int int … int
int int … int
int int … int
0 1 m-1
pr [2]
Эмуляция двумерного массива размером [n] [m]
4. Структурное программирование 4.10. Динамическое распределение памяти
int **pr
int **pr;pr = new int* [n]for (int i=0; i<=n-1; i++) pr[i] = new int [m];
int *
int *
int *
…
int *
0
1
2
n-1
int int … int
int int … int
int int … int
int int … int
0 1 m-1
pr [2][1]
Эмуляция двумерного массива
4. Структурное программирование 4.10. Динамическое распределение памяти
int main() // Dynamic store allocation for 2D array [n][m]{ int m = 0, n=0; cout << "Enter matrix size (n,m):"; cin >> n,m; if ((n <= 1)||(m<=1))return -1; cout << "m= " << m << " n= " << n << endl;
int* *pr = new int*[n]; // pointer to allocating array of pointers to rows for (int i=0; i<=n-1; i++) pr[i] = new int [m]; // allocating rows for (int i=0; i<=n-1; i++) for (int j=0; j<=m-1; j++) pr [i][j]=i*100+j; // init array
for (int i=0; i<=n-1; i++) delete [] pr[i]; // free memory of rows delete [ ]pr; // free memory of array of pointers to rows
_getch();return 0;}