Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tekhnologia_programmirovania.pdf
Скачиваний:
182
Добавлен:
08.04.2015
Размер:
1.76 Mб
Скачать

Структуры, перечисления, объединения 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.