- •Конспект лекций Часть 2 Оглавление
- •Часть 2 1
- •8. Указатели
- •8.1. Указатели Понятие указателя
- •Работа с указателями
- •Арифметика указателей
- •Ошибки при работе с указателями
- •If (p1) // Если указатель не равен 0, то все в порядке
- •8.2. Указатели и массивы
- •9. Функции и структура программы
- •9.1. Создание и использование функций Процедурный подход к разработке программ
- •Int Максимум_строки (int Строка)
- •Int Минимум_строки (int Строка)
- •Int Максимум_столбца (int Столбец)
- •Int Минимум_столбца (int Столбец)
- •Определение функций в программе
- •Завершение работы функции (инструкция return)
- •If ( Ошибка )
- •Список параметров функций
- •Обращение к функциям в программе
- •Передача данных по значению
- •Передача данных с помощью указателей
- •Передача данных по ссылке
- •Перегружаемые функции
- •Параметры по умолчанию
- •Функции с переменным числом параметров
- •Рекурсивное использование функций
- •Передача функций в качестве параметров
- •Встраиваемые функции (inline - функции)
- •Прототипы функций
- •9.2. Структура программы. Глобальные и локальные данные (области видимости и время жизни) Структура программы
- •Глобальные и локальные данные
- •Классы памяти
- •Многофайловые проекты
- •10. Структуры, объединения, перечисления
- •10.1. Структуры Определение структур
- •Доступ к полям структур
- •Указатели на структуры
- •Структурные параметры функций
- •Битовые поля структур
- •10.2. Объединения Обычные объединения
- •Анонимные объединения
- •10.3. Перечисления
- •Void WriteColor (тип_Спектр c )
- •11. Организация работы с файлами
- •11.1. Потоки для работы с файлами Общие сведения
- •Пример работы с файлом
- •11.2. Работа с файлами Создание потока, открытие и закрытие файла
- •Запись и чтение данных в текстовых файлах
- •Запись и чтение данных в двоичном режиме
- •If ( !File ) // Проверили удалось ли открыть файл
- •Как обнаружить конец файла?
- •Прямой доступ при работе с файлами
- •If ( !File ) // Проверили удалось ли открыть файл
- •Статус потоков ввода-вывода
- •Некоторые другие функции управления потоками ввода-вывода
- •Примеры по работе с файлами
- •12. Работа с динамической памятью Распределение памяти при работе программы
- •Динамическое выделение и освобождение памяти в стиле c
- •Возможные ошибки при работе с динамической памятью
- •Динамические массивы
- •Одномерные однонаправленные списки
- •Одномерные двунаправленные списки
- •Многомерные списки
9. Функции и структура программы
Создание и использование функций. Вызов функции (аргументы функции) и возврат значения. Передача параметров по значению, по ссылке. Глобальные и локальные переменные. Классы памяти и область действия. Автоматические переменные. Внешние переменные. Статические переменные. Внешние статические переменные. Регистровые переменные. Функции с переменным количеством аргументов. Использование функции как параметра другой функции. Рекурсия. Представление программы в виде набора функций. Многофайловая структура программы.
Использование функций позволяет:
значительно упростить разработку сложных программ;
сократить объем текста программы и генерируемого результирующего кода программы;
значительно упростить отладку и модификацию программ;
распределить работу над одной программой между различными исполнителями программистами.
Фактически разработка более-менее сложных программ практически невозможна без использования функций.
9.1. Создание и использование функций Процедурный подход к разработке программ
В качестве примера рассмотрим следующую задачу.
Имеется числовая матрица размера nнаm. Необходимо вывести на экран индексы всех седловых точек. Седловой точкой является элемент матрицы со значением минимальным в строке и максимальным в столбце, в котором находится элемент, или наоборот – максимальным в строке и минимальным в столбце.
Общий план решения этой задачи может быть, например, таким:
Подготовка данных для решения задачи.
Решение задачи и вывод результатов.
В соответствии с этим планом, разбиваем задачу на две соответствующие подзадачи, и для их реализации используем две соответствующие функции. И вот первый вариант будущей программы:
#include "stdafx.h"
#include <iostream>
using namespace std;
const int n = 5, m = 5; // n - количество строк, m - количество столбцов матрицы
int A[n][m]; // А - исходная матрица
void Подготовка_данных()
{
}
void Решение_и_вывод_результатов()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Подготовка_данных();
Решение_и_вывод_результатов();
system("Pause");
return 0;
}
Теперь можно перейти к последовательной реализации каждой из этих функций.
Для подготовки исходных данных необходимо:
заполнить массив Aнекоторыми данными и
вывести содержимое матрицы на экран, для того чтобы в дальнейшем проконтролировать правильность решения задачи.
Реализуем эти действия также с помощью соответствующих функций:
void Заполнение_массива()
{
}
void Вывод_массива()
{
}
void Подготовка_данных()
{
Заполнение_массива();
Вывод_массива();
}
Для заполнения данными матрицы воспользуемся датчиком случайных чисел, сама процедура заполнения двумерного массива значениями настолько проста, что дальнейшей детализации не требует:
void Заполнение_массива()
{
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
A[i][j] = rand() % 3; // Генерация сл. чисел в диапазоне [0, 2]
}
Здесь мы заполнили матрицу значениями 0, 1 и 2. При таких значениях элементов матрицы легче получить матрицу, содержащую седловые точки.
Вывод значений двумерного массива на экран также не должно вызывать затруднений:
void Вывод_массива()
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
cout << setw(4) << right << A[i][j];
cout << endl;
}
}
Вывод значений матрицы мы оформили в виде таблицы. Для задания ширины каждого столбца этой таблицы использован манипулятор вывода setw. Для использования этого манипулятора необходимо включить заготовочный файлiomanip.
Теперь мы получили следующую программу:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
const int n = 5, m = 5; // n - количество строк, m - количество столбцов матрицы
int A[n][m]; // А - исходная матрица
void Заполнение_массива()
{
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
A[i][j] = rand() % 3;
}
void Вывод_массива()
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
cout << setw(4) << right << A[i][j];
cout << endl;
}
}
void Подготовка_данных()
{
Заполнение_массива();
Вывод_массива();
}
void Решение_и_вывод_результатов()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Подготовка_данных();
Решение_и_вывод_результатов();
system("Pause");
return 0;
}
Если запустить эту программу на выполнение, на экран будет выведена матрица, содержащая 5 строк и 5 столбцов с элементами, значения которых принадлежат диапазону [0, 2] .
Переходим к реализации функции Решение_и_вывод_результатов(). Общий алгоритм работы этой функции: необходимо выполнить проверку каждого элемента исходной матрицы – является ли этот элемент седловой точкой. Если проверяемый элемент является седловой точкой, то вывести на экран значения индексов этого элемента. Если проверяемый элемент не является седловой точкой, то перейти к проверке следующего элемента.
Перебор элементов матрицы можно выполнить с помощью двух вложенных циклов.
Предположим, что имеется функция bool Это_седловая_точка(int i, int j), которая возвращает значениеtrue, если элемент матрицыА [i] [j]является седловой точкой. Тогда реализация функцииРешение_и_вывод_результатов() будет выглядеть так:
void Решение_и_вывод_результатов()
{
cout << endl;
int Счетчик = 0; // Счетчик седловых точек
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
if (Это_седловая_точка(i, j))
{
cout << setw(4) << i << setw(4) << j << endl;
++ Счетчик;
}
cout << "\nКоличество седловых точек: " << Счетчик << endl;
}
Реализуем функцию Это_седловая_точка. Для того чтобы определить является ли элемент матрицы с индексамиiиjседловой точкой, необходимо знать минимальное и максимальное значения в строке с индексомiзначения, а также минимальное и максимальное значения в столбце с индексомj. Допустим, что у нас имеются четыре функции: