- •Основные понятия. Типы данных.
- •Выражения. Операторы.
- •Управляющие структуры
- •Функции. Нисходящее программирование
- •Void имя (список аргументов)
- •Рекурсия. Макросы. Условная компиляция
- •Указатели. Арифметические операции с указателями
- •Массивы указателей. Указатели на функцию. Динамические массивы
- •Динамические структуры данных
- •Режимы работы с файлами в с
Массивы указателей. Указатели на функцию. Динамические массивы
Массивы могут содержать указатели. Типичным использованием такой структуры является формирование массива строк. Поскольку в С++ строка по существу является указателем на её первый символ, таким образом каждый элемент массива в действительности будет указателем.
Например: char *suit[4]={“Черви”, “Бубны”, “Трефы”, “Пики”};
Такой способ записи позволяет в нефиксированном размере массива обеспечивать доступ к строкам разной длины, т.е. реализовать одну из возможностей С++ - гибкость.
Указатель на функцию содержит адрес функции в памяти. Указатели на функцию можно передавать в функцию, возвращать из функции, хранить в массивах и присваивать другим указателям на функцию. Типичным применением указателей на функцию является создание типичной системы меню: пользователю предлагается выбрать позицию, каждая из которых обслуживается определенно функцией. Указатели на функцию хранятся в массиве указателей. Выбор пользователя используется как индекс массива, а указатель в массиве для вызова соответствующей функции.
Пример:
void f1(int);
void f2(int);
void f3(int);
int main ()
{
void(*f[3])(int)={f1,f2,f3};
int ch;
cout<<"Выберите 0, 1, 2. 3 -окончания";
cin>>ch;
while (ch>=0 && ch<3)
{
(*f[ch])(ch);
cout<<"Выберите 0, 1, 2. 3 -окончания";
cin>>ch;
}
return 0;
}
void f1(int a)
{
cout<<"Вы ввели"<<a<<"Вызвана функция 1";
}
...
Определены три функции, каждая из которых принимает целый аргумент и ничего не возвращает. Указатели на эти функции хранятся в массиве f следующей структуры: void(*f[3])(int)={f1,f2,f3};
Если не известно, сколько элементов в массиве следует использовать динамические массивы. Память под элементы выделяется с помощью функции new или malloc. Адрес начала массива хранится в переменной, называемой указателем.
Например:
int n=10;
int *a=new int [n];
int *b=(int*) malloc (n*sizeof(int));
Если динамический массив в какой-то момент перестает быть нужным, то занимаемую им память нужно освободить с помощью оператора delete[] или calloc.
Например:
int **a=new int*[nrow];
for (i=0; i<nrow;i++)
a[i]=new int[ncol];
Задание 1: дана последовательность. В зависимости от выбора пользователя отсортировать по возрастанию или убыванию.
Задание 2: дана матрица размером nxn. Переставить элементы побочной диагонали в следующем порядке: первый поменять с предпоследним, второй с последним и т.д.
Динамические структуры данных
Динамические структуры данных делятся на: линейные (список, стек, очередь, дек) и нелинейные (графы, деревья).
Стек – разновидность связного линейного списка, работающий по принципу «последний пришел – первый ушел».
Основные операции:
- добавление элемента;
- удаление элемента.
Список – это линейный набор, ссылающихся на себя структур, называемых узлами и объединённых указателем-связкой. Доступ к связанному списку обеспечивается указателем на первый узел списка. Доступ к последующим элементам осуществляется через указатель-связку, который хранится в каждом элементе списка. По общему соглашению указатель последнего элемента списка указывает на NULL.
Основные операции:
- добавление элемента в указанное место;
- удаление из указанного места.
Списки могут быть: однонаправленными (односвязными), двунаправленными (двусвязными), кольцевыми.
Очередь – разновидность линейного списка, работающая по принципу «первый пришел – первый ушел».
Основные операции:
- постановка узла в очередь;
- удаление узла из очереди.
Деревья – нелинейная двумерная структура данных с особыми свойствами. Узлы дерева содержат две или более связей.
Первый узел дерева – корень. Каждая связь корневого узла ссылается на потомка. Левый потомок – это первый узел левого поддерева, правый потомок – правого поддерева. Потомки одного узла - сиблинги. Узел, не имеющий потомков – лист.
Значение в левом узле всегда меньше корневого, в правом – всегда больше.
Дерево можно обойти 3-мя способами:
-
Порядковая выборка (левое поддерево – узел – правое поддерево);
-
Предварительная выборка (узел – левое поддерево – правое поддерево);
-
Отложенная выборка (левое поддерево – правое поддерево – узел).
Файлы
Файл – группа связанных записей.
По способу доступа файлы делятся на: последовательные (чтение и запись производится сначала байт за байтом) и файлы с произвольным доступом (допускается чтение и запись с указанной позиции).
С и С++ рассматривают файл, как последовательность байтов, заканчивающаяся маркером конца файла. Когда файл открывается, ему ставится в соответствие поток.
Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику.
В начале исполнения программы автоматически открываются 3 файла и связанные с ними потоки – стандартный ввод, стандартный вывод и стандартная ошибка (ifstream, ofstream, fstream). Открытый файл возвращает указатель на структуру типа FILE, хранящуюся в библиотеке <stdlib.h>. Эта структура содержит дескриптор файла, т.е. индекс файла в массиве ОС.