- •Предисловие
- •Глава 1. Основные понятия
- •1.1. Элементы языка программирования
- •1.2. Процесс создания программы
- •1.3. Первая программа
- •1.4. Состав программы
- •Глава 2. Средства разработки на C++
- •2.1. Системы Turbo C++ 3.0/Borland C++ 3.1
- •2.2. Система C++ Builder
- •Глава 3. Работа с числовыми данными
- •3.1. Целые типы
- •3.2. Числа с плавающей точкой
- •3.3. Ввод и вывод чисел
- •3.4. Логический тип и логические операции
- •3.5. Математические функции
- •Глава 4. Операторы. Ключевые слова
- •4.1. Операторы
- •4.2. Приоритеты операторов
- •4.3. Ключевые слова
- •4.4. Структура программы
- •4.5. Константы
- •Задачи - . Простейшие вычисления
- •Глава 5. Управление и циклы
- •5.1. Условный оператор
- •5.2. Операторы цикла
- •5.3. Переключатель
- •5.4. Операторы break и continue
- •Задачи -. Выбор и циклы
- •Глава 6. Массивы
- •6.1. Одномерные массивы
- •6.2. Двумерные массивы
- •Задачи -. Одно- и двумерные массивы
- •Глава 7. Функции
- •7.1. Определение функции
- •7.2. Формальные параметры и фактические аргументы
- •7.3. Автоматические и статические переменные
- •7.4. Прототипы функций
- •7.5. Массивы как аргументы функций
- •7.6. Внешние переменные
- •7.7. Рекурсия
- •7.8. Перегруженные имена функций
- •7.9. Аргументы функций по умолчанию
- •Задачи -. Функции
- •Глава 8. Символы и строки
- •8.1. Символы
- •8.2. Строки символов
- •Задачи -. Символы и строки
- •Глава 9. Препроцессор
- •9.1. Директивы препроцессора
- •9.2. Макросы
- •Задачи -. Макросы
- •Глава 10. Указатели и ссылки
- •10.1. Указатели и адреса
- •10.2. Указатели и массивы
- •10.3. Адресная арифметика
- •10.4. Символьные указатели
- •10.5. Массивы указателей
- •10.6. Указатели на функции
- •10.7. Ссылки
- •10.8. Операторы new и delete
- •Задачи -. Указатели и ссылки
- •Глава 11. О файлах и командной строке
- •11.1. Знакомство с файлами
- •11.2. Командная строка
- •11.3. Перенаправление стандартного ввода и вывода на файл
- •11.4. Аргументы командной строки
- •Задачи -. Файлы и командная строка
- •Глава 12. Работа с экраном дисплея
- •12.1. Текстовый режим
- •12.2. Графический режим
- •Задачи -. Работа с экраном
- •Глава 13. Внутреннее представление чисел
- •13.1. Двоичная система счисления
- •13.2. Беззнаковые целые
- •13.3. Двоичный дополнительный код
- •13.4. Двоичный код с избытком
- •13.5. Побитовые операторы
- •13.6. Дробные числа в двоичной системе
- •13.7. Внутреннее представление плавающих типов
- •13.8. Преобразование типов
- •Задачи -. Побитовые операторы
- •Глава 14. Структуры, перечисления, объединения
- •14.1. Объявление структур
- •14.2. Структуры и функции
- •14.3. Указатели на структуры
- •14.4. Массивы структур
- •14.5. Перечисления
- •14.6. Объединения
- •14.7. Битовые поля
- •14.8. О бинарных файлах
- •Задачи -. Структуры
- •Глава 15. Классы
- •15.1. Структуры в C++. Инкапсуляция
- •15.2. Встроенные функции
- •15.3. Классы. Скрытие данных
- •15.4. Конструкторы
- •15.5. Статические члены класса
- •15.6. Друзья класса
- •15.7. Копирование объектов класса
- •15.8. Управление доступом
- •15.9. Ссылка на себя
- •15.10. Деструкторы
- •Задачи -. Работа с классами
- •Глава 16. Программы из нескольких файлов
- •16.1. Работа с проектами
- •16.2. Область действия имен
- •16.3. Заголовочные файлы
- •16.4. Пространства имен
- •Задачи -. Работа со стеком
- •Глава 17. Перегрузка операторов
- •17.1. Правила перегрузки операторов
- •Задачи -. Перегрузка операторов
- •Глава 18. Конструктор копирования и оператор присваивания
- •18.1. Проблемы при копировании
- •Задачи -. Конструктор копирования
- •Глава 19. Ввод и вывод
- •19.1. Вывод
- •19.2. Ввод
- •19.3. Ввод и вывод определяемых пользователем типов
- •19.4. Работа с файлами
- •Глава 20. Взаимоотношения классов
- •20.1. Объекты как члены класса
- •20.2. Конструкторы встроенных типов
- •20.3. Наследование
- •20.4. Виртуальные функции
- •20.5. Абстрактные классы
- •20.6. Совместимость типов
- •20.7. Множественное наследование
- •Задачи -. Наследование классов
- •Глава 21. Шаблоны, исключения
- •21.1. Шаблоны
- •21.2. Шаблоны функций
- •21.3. Классы и шаблоны
- •21.4. Обработка исключений
- •21.5. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
887
7.3.Автоматические и статические переменные
Переменные, определенные в теле функции, являются локальными внутри этой функции и недоступны для других функций. Существуют два вида локальных переменных: автоматические и статические. Автоматические переменные возникают только в момент обращения к функции и исчезают при завершении ее работы. Память под автоматические переменные выделяется, когда функция начинает работать, и освобождается при выходе из функции, поэтому автоматические переменные не сохраняют своих значений между вызовами функции и должны устанавливаться заново при каждом новом обращении к функции.
Если необходимо сохранить значения локальных переменных внутри функции, их следует объявить статическими с использованием ключевого слова static. В программе 15 функции fauto и fstat увеличивают на 1 свою локальную переменную k и возвращают ее значение.
Программа 15. Автоматические и статические переменные
// Файл AutoStat.cpp |
|
int fauto () |
|
{ |
|
int k = 0; |
// Автоматическая локальная переменная |
return ++k; |
|
} |
|
int fstat () |
|
{ |
|
static int k = 0; |
// Статическая локальная переменная |
return ++k; |
|
} |
|
#include <iostream.h> |
|
#include <conio.h> |
|
void main() |
|
{ |
|
for(int i = 0; i < 10; i++) |
// 10 раз вызываем fauto |
cout << fauto() << ” ”; |
|
cout << "\n"; |
|
for(int i = 0; i < 10; i++) |
// 10 раз вызываем fstat |
cout << fstat() << ” ”; |
|
getch(); |
|
} |
|
Функции 89
Программа выводит:
1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9 10
Память под статические переменные выделяется в самом начале работы программы. Тогда же производится и их инициализация, то есть. статическая переменная инициализируется только один раз при первом вызове функции. Так как статическим переменным выделяется постоянная память, они сохраняют свои значения между вызовами функции. Статическая переменная остается локальной, то есть она доступна только внутри своей функции.
Все переменные внутри функции являются автоматическими по умолчанию, но можно явно указать на это, используя ключевое слово
auto:
auto int k = 0; |
// Автоматическая переменная |
Параметры функции также создаются заново при каждом вызове функции и инициализируются значениями фактических аргументов, поэтому они также являются локальными автоматическими переменными. Параметры функции можно произвольно изменять внутри функции, причем это никак не повлияет на значения фактических аргументов. Например, функцию power можно переписать в виде:
int power(int m, int n) |
// Возведение m в степень n |
{ |
|
int p = 1; |
|
while(n-- > 0) |
|
p = p * m; |
|
return p; |
|
} |
|
Здесь в заголовке цикла while текущее значение n сравнивается с нулем и затем уменьшается на 1. Но изменение параметра n внутри функции никак не повлияет на фактический аргумент. Инструкция
cout << power(3, 2);
напечатает 9.
Использование параметров функции позволяет обойтись меньшим числом переменных.
907
7.4.Прототипы функций
Прототипом функции называется ее предварительное объявление. Прототип имеет вид:
тип-результата имя-функции(объявления аргументов);
то есть состоит из заголовка функции и точки с запятой. Например, для функции возведения в степень прототип имеет вид:
int power(int m, int n);
Имена аргументов в объявлении (прототипе) функции можно не указывать и писать:
int power(int , int);
После объявления функцию можно вызывать из других функций, расположенных ниже по тексту программы. Вызовы функции должны быть согласованы с прототипом. Компилятор проверяет соответствие типов фактических и формальных параметров, и если они не согласованы, выдает ошибку. Проверяется также тип результата, возвращаемого функцией. Если обращение к функции соответствует ее прототипу, будет сгенерирован правильный код вызова функции, так как объявление сообщает компилятору все необходимое: имя функции, количество и тип аргументов, тип возвращаемого значения.
Прототипы полезны при разработке больших сложных программ, так как позволяют быстро набросать скелет программы, отложив реализацию деталей.
Компилятору достаточно объявления функции, но редактор связей должен иметь код функции, поэтому объявленная функция должна быть где-то определена.
7.5. Массивы как аргументы функций
Как было сказано, аргументы в функции передаются по значению, поэтому нельзя изменить значения аргументов внутри функции. Сказанное не относится к массивам. В случае с массивами в функцию передается адрес первого элемента массива. Элементы массива не копируются внутрь функции. Используя адрес первого элемента массива, можно внутри функции получить доступ к любому его элементу и изменить его.
Итак, запомним, если массив является аргументом функции, его элементы можно изменить внутри функции.
Функции 91
7.6. Внешние переменные
Внешние переменные определяются вне любой функции, благодаря чему они могут быть доступны любой функции программы. Память под внешние переменные выделяется в момент начала выполнения программы, поэтому они существуют в течение всего времени ее работы. Внешние переменные могут быть доступны по именам из любой функции. Чтобы внешняя переменная была доступна внутри функции, она должна быть в ней объявлена. Объявление начинается ключевым словом extern. Внешняя переменная доступна без дополнительных описаний во всех функциях, расположенных после ее объявления ниже по тексту программы. Пример использования внешних переменных приведен в программе 16.
Программа 16. Сортировка массива
Сортировкой называется упорядочение массива по возрастанию или убыванию. Массивы часто используются для хранения и обработки больших объемов информации, а работа с упорядоченными массивами выполняется, как правило, быстрее, поэтому сортировка массивов – это очень важная задача.
Впрограмме надо выполнить действия:
1)заполнить массив значениями;
2)распечатать исходный массив;
3)отсортировать массив;
4)распечатать упорядоченный массив.
Заполнение, печать и сортировку массива реализуем в виде отдельных функций.
Массив для сортировки и его максимальный размер объявляются в начале программы как внешние переменные, а определяются в ее конце. Размер массива задается константой SIZEARR достаточно большого размера, чтобы выделенной под массив памяти хватило в большинстве случаев использования программы. Конкретный размер массива вводится пользователем и проверяется на допустимость. При вводе недопустимого размера массива вызывается функция
void exit(int k),
которая завершает работу программы и возвращает в вызывающую программу значение своего аргумента. Эта функция объявлена в stdlib.h.
Для заполнения массива числами в программе предусмотрена функция
void get_array(int x[], int n);
92 7
В ней элементам массива x присваиваются случайные целые значения, генерируемые функцией стандартной библиотеки
int rand(),
объявленной в stdlib.h. Функция rand возвращает псевдослучайное число в диапазоне от 0 до RAND_MAX. Величина RAND_MAX определяется в файле stdlib.h. Обычно это 32767.
Чтобы обеспечить получение при каждом запуске программы новой последовательности случайных чисел, вызывается функция:
void randomize(void);
которая инициализирует генератор случайных чисел, связывая первое случайное число с показаниями системных часов. Эта функция объявлена также в stdlib.h.
Для сортировки массива по возрастанию написана функция: void bubble_sort(int x[], int n);
использующая алгоритм «пузырька», состоящий в следующем. Организуется проход по массиву, в котором сравниваются соседние элементы и, если предшествующий элемент оказывается больше следующего, они меняются местами. В результате первого прохода наибольший элемент оказывается на своем, последнем месте («всплывает»). Затем проход по массиву повторяется до предпоследнего элемента, затем до третьего с конца массива и т.д. В последнем проходе по массиву сравниваются только первый и второй элементы.
//Файл SortArr.cpp
//Сортировка массива #include <iostream.h> #include <conio.h>
//Объявление внешних переменных
extern int x[]; |
// Объявление массива |
extern const int SIZEARR; |
// Объявление размера массива |
// Объявления функций |
|
void get_array(int[], int n); |
// Заполнение массива из n элементов |
void bubble_sort(int[], int n); |
// Сортировка массива методом пузырька |
void prn_array(int[], int n); |
// Вывод массива |
#include <stdlib.h> |
// Для exit, rand и randomize |
int main() |
|
{ |
|
int n; |
// Размер массива |
|
Функции |
93 |
|
|
|
cout << "\nВведите размер массива < " << SIZEARR << ": "; |
|
|
cin >> n; |
|
|
if(n > SIZEARR || n<=0){ |
// Проверка размера |
|
cout << "Размер массива " << n << "не подходит \n"; |
|
|
exit(1); |
// Завершение программы |
|
} |
|
|
get_array(x, n); |
// Заполнение массива |
|
cout << "Исходный массив: \n"; |
|
|
prn_array(x, n); |
// Вывод исходного массива |
|
bubble_sort(x, n); |
// Сортировка |
|
cout << "\nОтсортированный массив: \n"; |
|
|
prn_array(x, n); |
// Вывод упорядоченного массива |
|
getch(); |
|
|
return 0; |
|
|
}
//Определение функций
//get_array: заполняет массив x случайными числами void get_array(int x[], int n)
{
int i; |
// Локальная переменная |
randomize(); |
// Инициализация генератора случайных чисел |
for(i = 0; i < n; i++) |
|
x[i] = rand(); |
// rand генерирует целое случайное число |
}
//prn_array: вывод массива void prn_array(int x[], int n)
{
int i;
for(i = 0; i < n; i++) cout << x[i] << ", ";
}
//bubble_sort: сортировка массива x методом пузырька void bubble_sort(int x[], int n)
{
int i, j, tmp;
for(i = n - 1; i > 0; i--) |
// i задает верхнюю границу |
for(j = 0; j < i; j++) |
// Цикл сравнений соседних элементов |
if(x[j] > x[j + 1]){ |
// Если нет порядка, |
tmp = x[j]; |
// перестановка местами |
x[j] = x[j + 1]; |
// соседних |
x[j + 1] = tmp; |
// элементов |
} |
|
}
// Определение внешних переменных