- •СОДЕРЖАНИЕ
- •ПРЕДИСЛОВИЕ
- •ГЛАВА 1. Введение в алгоритмы
- •1.1. Этапы решения задач на ЭВМ
- •1.2. Понятие алгоритма
- •1.3. Свойства алгоритмов
- •1.4. Сложность алгоритма
- •1.7. Пример простейшего линейного процесса
- •1.7. Пример циклического процесса
- •ГЛАВА 2. Базовые средства языка Си
- •2.1. Алфавит языка Си
- •2.2. Лексемы
- •2.3. Идентификаторы и ключевые слова
- •2.4. Комментарии
- •2.5. Простейшая программа
- •2.7. Декларация объектов
- •2.8. Данные целого типа (integer)
- •2.9. Данные символьного типа (char)
- •2.10. Данные вещественного типа (float, double)
- •ГЛАВА 3. Константы в программах
- •3.2. Константы вещественного типа
- •3.4. Строковые константы
- •ГЛАВА 4. Обзор операций
- •4.1. Операции, выражения
- •4.3. Операция присваивания
- •4.4. Сокращенная запись операции присваивания
- •4.7. Операции сравнения
- •4.8. Логические операции
- •4.10. Операция «,» (запятая)
- •ГЛАВА 5. Обзор базовых инструкций языка Си
- •5.2. Стандартные математические функции
- •5.3. Функции вывода данных на дисплей
- •5.4. Функции ввода информации
- •ГЛАВА 6. Составление разветвляющихся алгоритмов
- •6.1. Краткая характеристика операторов языка Си
- •ГЛАВА 7. Составление циклических алгоритмов
- •7.1. Понятие циклического кода
- •7.2. Оператор с предусловием while
- •7.4. Оператор цикла с предусловием и коррекцией for
- •ГЛАВА 8. Операторы и функции передачи управления
- •8.1. Оператор безусловного перехода goto
- •8.2. Операторы continue, break и return
- •8.3. Функции exit и abort
- •Советы по программированию
- •ГЛАВА 9. Указатели
- •9.1. Определение указателей
- •9.2. Операция sizeof
- •9.3. Инициализация указателей
- •9.4. Операции над указателями
- •ГЛАВА 10. Массивы
- •10.1. Понятие массива
- •10.2. Одномерные массивы
- •10.4. Строки как одномерные массивы данных типа char
- •10.5. Указатели на указатели
- •10.8. Работа с динамической памятью
- •10.9. Библиотечные функции
- •10.10. Пример создания одномерного динамического массива
- •ГЛАВА 11. Функции пользователя
- •11.1. Декларация функции
- •11.2. Вызов функции
- •11.3. Передача аргументов в функцию
- •11.4. Операция typedef
- •11.5. Указатели на функции
- •ГЛАВА 12. Классы памяти и область действия объектов
- •ЗАДАНИЕ 4. Обработка массивов
- •Первый уровень сложности
- •Второй уровень сложности
- •ЗАДАНИЕ 5. Функции пользователя
- •Первый уровень сложности
- •Второй уровень сложности
- •12.3. Статические и внешние переменные
- •12.4. Область действия переменных
- •Советы по программированию
- •13.1. Структуры
- •13.5. Вложенные структуры
- •13.6. Массивы структур
- •13.7. Размещение структурных переменных в памяти
- •13.8. Объединения
- •13.9. Перечисления
- •13.10. Битовые поля
- •ГЛАВА 14. Файлы в языке Си
- •14.1. Открытие файла
- •14.2. Закрытие файла
- •14.3. Запись-чтение информации
- •14.5. Дополнительные файловые функции
- •Советы по программированию
- •ЗАДАНИЕ 7. Создание и обработка файлов
- •Первый уровень сложности
- •Второй уровень сложности
- •ГЛАВА 15. Динамические структуры данных
- •15.1. Линейные списки
- •15.2.1. Алгоритм формирования стека
- •15.2.2. Алгоритм извлечения элемента из стека
- •15.2.3. Просмотр стека
- •15.2.4. Алгоритм освобождения памяти, занятой стеком
- •15.2.5. Алгоритм проверки правильности расстановки скобок
- •15.3.1. Формирование очереди
- •15.3.2. Алгоритм удаления первого элемента из очереди
- •15.4. Двунаправленный линейный список
- •15.4.1. Формирование первого элемента
- •15.4.3. Алгоритм просмотра списка
- •15.4.5. Алгоритм удаления элемента в списке по ключу
- •15.5. Нелинейные структуры данных
- •15.5.1. Бинарные деревья
- •15.5.2. Основные алгоритмы работы с бинарным деревом
- •15.5.4. Вставка нового элемента
- •15.6. Построение обратной польской записи
- •15.6.1. Алгоритм, использующий дерево
- •15.6.2. Алгоритм, использующий стек
- •15.6.3. Пример реализации
- •15.7. Понятие хеширования
- •15.7.2. Примеры хеш-функций
- •15.7.3. Схемы хеширования
- •15.7.4. Примеры реализации схем хеширования
- •Вариант 2. Двунаправленные списки
- •ГЛАВА 16. Переход к ООП
- •16.1. Потоковый ввод-вывод
- •16.3. Проблема ввода-вывода кириллицы в среде Visual C++
- •16.4. Операции new и delete
- •16.6. Шаблоны функций
- •Первый уровень сложности
- •Второй уровень сложности
- •6.1. Основные понятия
- •6.3. Примитивы GDI
- •6.5. Получение описателя контекста устройства
- •6.6. Основные инструменты графической подсистемы
- •6.7. Закрашивание пустот
- •6.8. Рисование линий и кривых
- •6.9. Пример изображения графика функции sin
- •6.10. Рисование замкнутых фигур
- •6.11. Функция Polygon и режим закрашивания многоугольника
- •6.13. Управление областями вывода и отсечением
- •ЗАДАНИЕ 11. Создание графических изображений
- •ЛИТЕРАТУРА
10.8. Работа с динамической памятью
Указатели чаще всего используют при работе с динамической памятью, которую иногда называют «куча» (перевод английского слова heap). Это свободная память, в которой можно во время выполнения программы выделять место в соответствии с потребностями. Доступ к выделенным участкам динамической памяти производится только через указатели. Время жизни динамических объектов – от точки создания до конца программы или
до явного освобождения памяти. |
Р |
|
|
С другой стороны, некоторые задачи исключают использование |
|
|
И |
структур данных фиксированного размера и требуют введения структур динамических, способных увеличивать или уменьшать свой размер уже в
|
У |
процессе работы программы. Основу таких структур составляют |
|
динамические переменные. |
|
Динамическая переменная хранится в некоторой области ОП, не |
обозначенной именем, и обращение к ней производится через переменную- |
|||
указатель. |
|
|
Б |
Но вначале рассмотрим еще одну операциюГязыка Си, основное |
|||
назначение которой – работа с участками оперативной памяти. |
|||
10.9. Библиотечные функции |
|||
|
е |
|
|
Функции для манипулирования динамической памятью в стандарте Си |
|||
следующие: |
т |
к |
|
void *calloc(unsigned |
n, unsigned size); – выделение памяти для |
размещения n объектов размером size байт и заполнение полученной области |
|||||
|
|
|
|
|
о |
нулями; возвращает указа ель на выделенную область памяти; |
|||||
|
void |
|
|
и |
|
|
*malloc (unsigned n) – выделение области памяти для размещения |
||||
блока размером |
n байт; в звращает указатель на выделенную область |
||||
памяти; |
|
ло |
|
||
|
|
|
|
||
|
void *realloc (void *b, unsigned n) – изменение размера размещенного по |
||||
адресу b |
б |
|
|
||
лока на новое значение n и копирование (при необходимости) |
|||||
соде |
ржи |
|
ка; возвращает указатель на перераспределенную область |
||
мого |
|
памяти; при возникновении ошибки, например, нехватке памяти, эти
функц |
возвращают |
значение NULL, что означает отсутствие адреса |
(нулевой адрес); |
|
|
coreleft (void) – получение размера свободной памяти в байтах только |
||
дляБMS DOS (используется в Borland C++), тип результата: unsigned – для |
||
моделей памяти tiny, small и medium; unsigned long – для моделей памяти |
||
compact, large и huge; |
|
|
void |
free (void |
*b) – освобождение блока памяти, адресуемого |
указателем b. |
|
|
Для использования этих функций требуется подключить к программе в |
зависимости от среды программирования заголовочный файл alloc.h или malloc.h.
81
__________________________________________________________________
В языке С++ введены операции захвата и освобождения памяти new и delete, рассматриваемые в разд. 16.4.
__________________________________________________________________
10.10.Пример создания одномерного динамического массива
Вязыке Си размерность массива при объявлении должна задаваться
константным выражением.
Если до выполнения программы неизвестно, сколько понадобитсяР элементов массива, нужно использовать динамические массивы, т.е. при необходимости работы с массивами переменной размерностиИвместо массива достаточно объявить указатель требуемого типа и присвоить ему адрес свободной области памяти (захватить память). У
Память под такие массивы выделяется с помощьюГфункций mallос и calloc (операцией new) во время выполнения программы. Адрес начала массива хранится в переменной-указателе. НапримерБ:
В примере значение переменной n |
з д но, но может быть |
получено и |
|||
программным путем. |
е |
а |
|
||
|
|
||||
Обнуления |
памяти |
выделении не |
происходит. |
||
при |
|||||
Инициализировать динамический массивкпри декларации нельзя. |
|
||||
|
ту |
|
|
||
Обращение к элемен |
динамич ского массива осуществляется так же, |
как и к элементу обыч го – например а[3]. Можно обратиться к элементу |
||
|
|
но |
массива и через косвен ую адресацию – *(а + 3). В любом случае происходят |
||
|
и |
|
те же действия, к т рые выполняются при обращении к элементу массива, |
||
декларированного бычным бразом. |
||
л |
|
|
Пос е работы захваченную под динамический массив память |
||
б |
|
|
необходимо освобод ть, для нашего примера free(b);
Таким о разом, время жизни динамического массива, как и любой динамической переменной – с момента выделения памяти до момента ее освобожден я. Область действия элементов массива зависит от места Бдекларац указателя, через который производится работа с его элементами. Область действия и время жизни указателей подчиняются общим правилам для остальных объектов программы.
Пример работы с динамическим массивом:
#include <alloc.h> void main()
{
double *x; int n;
printf("\nВведите размер массива – ");
82
// Захват памяти
} |
|
|
|
|
... |
|
|
|
|
// Работа с элементами массива |
|
|
|
|
... |
|
|
|
|
free(x); |
// Освобождение памяти |
|||
} |
|
|
|
Р |
|
|
|
|
|
__________________________________________________________________ |
||||
Примеры создания одномерного и двухмерного динамических |
||||
|
Г |
И |
||
массивов с использованием операций new и delete можно посмотреть в разд. |
||||
16.4. |
Б |
У |
|
|
|
|
__________________________________________________________________
10.11. Пример создания двухмерногоквадин мического массива
Напомним, что ID двухмерного масси – указатель на указатель. На рис. 10.1 приведена схема располож ния элементов, причем в данном случае
сначала выделяется память на указат ли, расположенные последовательно |
|||||
друг за другом, а затем каждомуеиз них выделяется соответствующий |
|||||
участок памяти под элемен ы. |
|
||||
|
. . . |
и |
т |
|
|
int **m, n1, n2, i, j; |
|
||||
|
|
л |
|
|
|
puts(" Введ те размерыомассива (строк, столбцов): "); |
|||||
scanf(“%d%d”, &n1, &n2); |
|
||||
// Захват памяти д я указателей – А (n1=3) |
|
||||
и |
|
|
|
|
|
m = (int**)calloc(n1, sizeof(int*)); |
|
||||
for (i=0; i<n1; i++) |
// Захват памяти для элементов – B (n2=4) |
||||
Б |
б*(m+i) = (int*)calloc(n2, sizeof(int)); |
|
|||
for ( i=0; i<n1; i++) |
|
|
|||
|
for ( j=0; j<n2; j++) |
|
|||
|
. . . |
m[i] [j] = i+j; |
// *(*(m+i)+j) = i+j; |
||
|
|
|
|
||
for(i=0; i<n; i++) free(m[i]); |
// Освобождение памяти |
||||
free(m); |
|
|
|
|
|
|
. . . |
|
|
|
83