- •Предисловие
- •Глава 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. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
23416
Вфайл SumNumb.cpp необходимо поместить объявления используемых в main функций strtof и readline, иначе при компиляции данного файла будет выдана ошибка вида:
•Error LECTC_~1\SUMNUMB.CPP 18: Function 'readline' should have a prototype
Ниже приведен пример работы программы
33.21
33.21 -10.12 23.09 65.66 88.75 ^Z
Часто кажется удобным делать переменные внешними потому, что в этом случае становятся короче списки аргументов функций, так как переменные видны везде. Например, в программе 51 массив для вводимой строки и его размер не передаются в функцию readline потому, что они доступны в этой функции как внешние переменные. Однако чрезмерное использование внешних переменных приводит к программам, в которых связи по данным не очевидны, поэтому такие программы трудны для понимания и модификации, их трудно отлаживать, так как сложно следить за изменениями внешних переменных.
Кроме того, функции, в которые данные передаются с помощью внешних переменных, являются менее общими, так как в них используются конкретные имена. Это относится, например, к функции readline, в которой использовано имя конкретного внешнего массива line. При изменении имени массива придется переписывать и функцию
readline.
16.3. Заголовочные файлы
При написании программы 51 нужно было заботиться об объявлениях внешних функций и переменных в файлах программы. Для облегчения этого, принято размещать необходимые объявления в отдельных файлах с расширениями .h, которые называют заголовочными (от header – заголовок), так как их основное содержание составляют объявления или заголовки функций.
Программы из нескольких файлов 235
Страж включения
Заголовочные файлы вставляются в другие файлы директивами препроцессора #include, причем делать это надо однократно, так как при повторном включении возможны ошибки из-за дублирования определения какого-либо объекта. Чтобы не было повторного включения заголовочных файлов, используется прием, называемый
стражем включения.
Заголовочный файл оформляется в виде
// Файл HEADER.H |
|
#ifndef HEADERH |
// Страж |
#define HEADERH |
// включения |
//Содержимое HEADER.H
//…
#endif
Условная директива препроцессора #ifndef проверяет, определен или нет макрос HEADERH. Если этот макрос не определен, то в текст программы включаются все строки, вплоть до строки #endif, при этом определяется макрос HEADERH. Если же обнаружится, что макрос HEADERH определен, то в обработанный препроцессором текст не включаются все строки, расположенные между строками
#ifndef HEADERH
и
#endif
благодаря чему не будет повторного включения файла HEADER.H.
Имя макроса, который фигурирует в страже включения, совершенно произвольно, но принято выбирать его похожим на имя заголовочного файла.
Таким образом, если в некотором файле будут две директивы:
// Файл File1.cpp #include HEADER.H #include HEADER.H
то файл HEADER.H будет вставлен только одной первой директивой, а вторая будет фактически проигнорирована благодаря стражу включения.
Понятие стека
Стеком называется набор элементов одного типа, организованный по принципу “последний пришел – первый вышел” или LIFO (last infirst out). Английское слово stack переводится как копна сена, стопа
236 16
бумаги. Для стопы бумаги действительно легче всего взять верхний лист, который попадает в стопу последним. Место, куда помещаются и из которого извлекаются элементы стека, называется вершиной.
Для работы со стеком определяют два основных действия или операции:
push – поместить новый элемент в стек и
pop – извлечь последний элемент, помещенный в стек.
Для наглядности стек можно представлять себе как вертикальную стопку книг или кирпичей, положенных друг на друга. Очередной кирпич кладется на верх стопки, извлекается же из стопки проще всего самый верхний кирпич. Таким образом, LIFO – это естественная дисциплина работы со стопкой кирпичей. В программировании стеки часто бывают полезны для решения различных задач.
Реализовать стек можно различными способами. В приводимой далее программе элементы стека размещаются в массиве.
Модули
Объявления функций для работы со стеком поместим в заголовочном файле Stack.h, определения функций и переменных поместим в файл реализации Stack.cpp. Совокупность заголовочного файла и файла реализации принято называть модулем. В C++ Builder для этого используется термин unit. В C++Builder создание модулей автоматизировано: заготовка нового модуля добавляется в проект командой File, New, Unit, при этом заголовочный файл модуля будет
иметь страж включения. В TC заголовочный файл и файл реализации создаются по отдельности.
Программа 52. Реализация стека в виде массива
Рассмотрим стек, элементами которого являются символы. Программа состоит из трех файлов: Stack.h, Stack.cpp и Brackets.cpp. Файл Stack.h содержит объявления функций для работы со стеком.
// Файл Stack.h |
|
#ifndef STACKH |
// Страж |
#define STACKH |
// включения |
void push(int c); |
// Поместить c в стек |
int pop(); |
// Извлечь элемент из вершины стека |
#endif |
|
Реализация функций для работы со стеком находится в файле
Stack.cpp.
// Файл Stack.cpp
|
Программы из нескольких файлов |
237 |
#include <iostream.h> |
|
|
#include ”stack.h” |
|
|
static const int SZ = 100; |
// Максимальный размер стека |
|
static char s[SZ]; |
// Массив под элементы стека |
|
static int sp = 0; |
// Позиция свободного элемента массива |
|
// push: поместить c в стек |
|
|
void push(int c) |
|
|
{ |
|
|
if(sp < SZ) |
// Если в массиве есть место, |
|
s[sp++] = c; |
// помещаем символ в стек |
|
else |
|
|
cerr << "Стек полон," << char(c) << "не помещается \n"; |
|
|
} |
|
|
// pop: извлечь элемент из вершины стека |
|
|
int pop() |
|
|
{ |
|
|
if(sp > 0) |
// Если в стеке есть символы, |
|
return s[--sp]; |
// берем символ с вершины стека |
|
else{ |
|
|
cerr << "Стек пуст\n"; return EOF;
}
}
В функции main организовано посимвольное чтение текста и его анализ на правильность расстановки скобок. Все открывающие скобки, встреченные в тексте, помещаются в стек. Если встречается закрывающая скобка, то из вершины стека извлекается последняя встреченная открывающая скобка и сравнивается с закрывающей. Если скобки соответствуют друг другу, продолжается анализ, если не соответствуют, то это ошибка. Ошибкой являются также случаи, когда закрывающая скобка идет раньше открывающей и когда открывающих скобок больше чем закрывающих.
// Файл Brackets.cpp #include <iostream.h> #include <stdlib.h> #include <conio.h> #include "stack.h"
int main() |
|
{ |
|
int c, bro; |
|
while((c = cin.get()) != EOF) |
// Чтение символов |
if('(' == c || '[' == c || '{' == c) |
// Открывающие скобки |
push(c); |
// помещаем в стек |