- •Предисловие
- •Глава 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. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
Структуры, перечисления, объединения 189
14.5. Перечисления
Перечисление – это список целых констант, например, enum Boolean {NO, YES};
Первая константа NO в перечислении enum имеет значение 0, у следующей костанты YES значение 1. Можно явно указывать значения констант в перечислении, например,
enum escapes {BELL = ’\a’, BACKSPACE = ’\b’, TAB = ’\t’, NEWLINE = ’\n’, VTAB = ’\v’, RETURN = ’\r’};
Если не все константы заданы явно, они продолжают прогрессию, начиная с последнего заданного значения, например,
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
Здесь значение FEB есть 2, значение MAR есть 3 и т.д.
Имена констант в различных перечислениях должны отличаться друг от друга.
Значения констант в одном перечислении могут быть одинаковыми.
Константы, объявленные в перечислении, могут участвовать в любых выражениях, где допустимо вхождение целых типов.
Перечисление является типом данных, поэтому можно объявлять переменные типа перечисления. Компилятор не контролирует, входят ли значения, присваиваемые таким переменным, в их тип. В следующей программе использовано перечисление months.
Программа 38. Использование перечислений
// Файл Enum.cpp
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
#include <iostream.h> #include <conio.h> int main()
{
months m, nextm, m1; // Три переменные типа months m = MAR;
nextm = m + 1; m1 = -1;
cout << "m = " << m << endl;
cout << "nextm = " << nextm << endl; cout << "m1 = " << m1 << endl;
190 14
getch(); return 0;
}
При компиляции строк:
nextm = m + 1; m1 = -1;
выдается предупреждение:
Warning: Assigning int to months
которое переводится как:
Предупреждение: присваивание целого months.
На рис.67 показано окно просмотра в процессе выполнения программы. Видно, что отладчик показывает значения из диапазона в числовом и символьном представлении.
Рис.68. Значения переменных типа перечисления Программа выдает:
m = 3 nextm = 4 m1 = -1
14.6. Объединения
Объединение – это структура, для всех полей которой отводится один и тот же участок памяти. Объединения описываются с использованием ключевого слова union. Объединения аналогичны записям с вариантами в Паскале. Использование объединений иллюстрируется приводимой далее программой.
Программа 39. Внутреннее представление float
Программа позволяет исследовать внутреннее представление чисел с плавающей точкой, которое было описано в параграфе 13.7.
Чтобы получить значения отдельных двоичных разрядов внутреннего представления, следует использовать побитовые операторы, однако их нельзя применять непосредственно к числам с
Структуры, перечисления, объединения 191
плавающей точкой. Поэтому используется объединение, включающее поле типа float, поле типа массив из 4-х символов и целое поле long, которое, как и float, имеет размер 4 байта.
// Файл InnPrsnt.cpp |
|
typedef union{ |
// Объединение можно рассматривать |
float f; |
// или как float |
char str[sizeof(float)]; |
// или как массив символов |
unsigned long l; |
// или как long |
}float_chars_long; |
|
С помощью typedef объединению присвоено имя float_chars_long. Отводимые объединению 4 байта можно рассматривать либо как число с плавающей точкой, либо как массив символов, либо как длинное целое. Получая, например, двоичное представление длинного целого, мы получим одновременно представление float.
Функция prn_long_bin выводит двоичные цифры для целого числа типа long.
//Продолжение файла InnPrsnt.cpp #include <iostream.h>
//prn_long_bin: печать двоичного представления long void prn_long_bin(unsigned long x)
{
int i,
n = sizeof(unsigned long) * 8; // n – число двоичных разрядов в long unsigned long h;
h = 1L << n - 1; // В старшем разряде у h 1 и 0 в остальных for(i = 1; i <= n; i++){
cout << ((x & h) != 0) << (i % 8 ? "" : " "); x <<= 1;
}
}
Длинная целочисленная константа 1L представляется в памяти единичкой в младшем правом разряде. После ее сдвига на n-1 разряд влево, получается величина h, у которой имеется только одна единичка в старшем левом разряде, остальные разряды нулевые. Результат побитового сравнения
x & h
будет отличен от нуля, если x также имеет в старшем разряде 1. В этом случае на экран выводится 1, в противном случае выводится 0. После каждого сравнения x сдвигается влево. Для большей наглядности содержимое одного байта отделяется от другого пробелами путем печати выражения
192 14
(i % 8 ?"" : " "),
в котором i есть номер разряда. Когда остаток от деления номера i на 8 равен нулю, выводится пробел, в остальных случаях пустая строка.
Программа вводит число с плавающей точкой, печатает его, а также печатает содержимое 4 - х байтов, отводимых под него, в шестнадцатеричной и в двоичной форме.
// Продолжение файла InnPrsnt.cpp #include <conio.h>
void main()
{
float_chars_long var; char c, i;
clrscr();
cout<<"\n Внутреннее представление чисел с плавающей точкой \n";
cout << "\nЧисло As hex |
|
As bin\n"; |
while((cin >> var.f) != NULL){ |
|
// Пока вводятся числа |
gotoxy(1, wherey() - 1); |
|
// Перевод курсора в начало |
|
|
// предыдущей строки экрана |
// wherey() возвращает номер строки, в которой находится курсор |
||
cout << var.f << '\t'; |
|
// Печать числа |
for(i = 1; i <= sizeof(float); i++){ |
// Печать содержимого байтов, |
|
c = var.str[sizeof(float) - i]; |
|
// отведенных числу |
cout << hex << ((c & 0Xf0) >> 4) << (c & 0X0f) << ' '; |
||
} |
|
|
cout.put('\t'); |
// Вывод табуляции для выравнивания |
|
prn_long_bin(var.l); |
// Печать двоичного представления |
|
cout << endl; |
|
|
}
getch();
}
При печати шестнадцатеричного представления объединение рассматривается как массив символов. Так как старшие разряды двоичного представления чисел располагаются в байтах с большими адресами, печать производится, начиная с символа массива с наибольшим индексом. Содержимое каждого байта печатается в виде двух 16-разрядных цифр, начиная со старшего полубайта. В выражении
(c & 0Xf0) >> 4
из символа с вырезаются 4 старших разряда и прижимаются к правому краю. С помощью выражения
c & 0X0f
Структуры, перечисления, объединения 193
получаются 4 младших бита символа c. После печати содержимого каждого байта выводится пробел. Эти действия обеспечивают печать внутреннего представления числа в принятой форме записи слева направо.
Входной поток настраивается на печать целых в шестнадцатеричном виде благодаря посылке в него величины
hex,
определенной в iostream.h. Сделанная настройка действует до явного ее изменения. Величина hex является манипулятором. Так называются специальные функции, которые позволяют управлять форматом выводимых чисел. Кроме hex, имеется еще манипуляторы:
dec – использование десятичной системы при вводе и выводе; oct – использование восьмеричной системы при вводе и выводе.
После того как число набрано, следует нажать Enter, что приводит в переводу курсора на следующую строку. Чтобы диалог с программой выглядел более аккуратно, курсор переводится в начало той строки, где набиралось вводимое число с использованием функции
int wherey(),
возвращающей номер строки, в которой расположен курсор. Позицию курсора в строке выдает функция
int wherex().
Для завершения работы с программой следует нажать Ctrl+Z и
Enter.
Далее приводится листинг, выданный программой:
Печать внутреннего представления чисел с плавающей точкой Число As hex As bin
13f 80 00 00 00111111 10000000 00000000 00000000
240 00 00 00 01000000 00000000 00000000 00000000
5.340 a9 99 9a 01000000 10101001 10011001 10011010
0.1 |
3d cc cc cd |
00111101 11001100 11001100 11001101 |
0.33e 99 99 9a 00111110 10011001 10011001 10011010
10 |
41 20 00 00 |
01000001 00100000 00000000 00000000 |
-1 |
bf 80 00 00 |
10111111 10000000 00000000 00000000 |
-2 |
c0 00 00 00 |
11000000 00000000 00000000 00000000 |
-4 |
c0 80 00 00 |
11000000 10000000 00000000 00000000 |
4.540 90 00 00 01000000 10010000 00000000 00000000
Из листинга видно, что число 5.3 округлено с избытком, так как старший отброшенный разряд мантиссы есть 1.