
- •Р. Лафоре
- •Глава 1. Общие сведения 32
- •Глава 3. Циклы и ветвления 92
- •Глава 4. Структуры 142
- •Глава 5. Функции 168
- •Глава 6. Объекты и классы 217
- •Глава 7. Массивы и строки 261
- •Глава 8. Перегрузка операций 312
- •Глава 9. Наследование 361
- •Глава 10. Указатели 411
- •Глава 11. Виртуальные функции 476
- •Глава 12. Потоки и файлы 536
- •Глава 13. Многофайловые программы 596
- •Глава 14. Шаблоны и исключения 640
- •Глава 15. Стандартная библиотека шаблонов (stl) 681
- •Глава 16. Разработка объектно-ориентированного по 752
- •Глава 1 «Общие сведения» включает список тем, касающихся uml, с указа- нием их расположения в книге.
- •Глава 1
- •Глава 2
- •Глава 3
- •If внутри циклов
- •If и else во вложенных ветвлениях
- •Глава 4
- •Глава 5 Функции
- •Глава 6
- •Глава 7
- •123456. Россия
- •123456. Россия
- •Глава 8
- •Глава 9
- •Глава 10 Указатели
- •Main() передает адрес переменной var в ptrd в centimize()
- •Centimize() использует этот адрес для доступа к var
- •Глава 11
- •Глава 12
- •Тип:менеджер Фамилия: Александров Номер:1111
- •Тип:Ученый Фамилия: Лебедев Номер:2222
- •Тип:рабочий Фамилия:Шевелев Номер:3333
- •Глава 13
- •Глава 14
- •Много объектов разных классов в памяти Рис. 14.2. Шаблон класса
- •Алгоритмы используют итераторы для работы с объектами контейнеров. Рис. 15.1. Контейнеры, алгоритмы и итераторы
- •Глава 16
- •Глава 1
- •Глава 2
- •Глава 3
- •Глава 4
- •Глава 5
- •Глава 6
- •Глава 7
- •Глава 8
- •Глава 9
- •Глава 10 Ответы на вопросы
- •Глава 11
- •Глава 12 Ответы на вопросы
- •Глава 13 Ответы на вопросы
- •Глава 14 Ответы на вопросы
- •Глава 15 Ответы на вопросы
- •Глава 16
Структуры
Структуры
Перечисления
В предыдущих главах
мы рассматривали только переменные
стандартных типов,
таких, как float,
char
и int.
Подобные
переменные способны представлять
какую-ли-
бо одну величину — высоту,
сумму, значение счетчика и т. д. Однако
иногда отдель-
ные переменные бывает
удобно объединять в более сложные
конструкции. В реаль-
ной жизни мы
совершаем подобные действия, когда
организуем работников фирмы
в отделы
или составляем предложения из отдельных
слов. В C++
одной из конст-
рукций, реализующих
объединение разнородных данных, является
структура.
Структурам посвящена
первая часть этой главы. Во второй части
мы рассмот-
рим
перечисления —
другое средство языка C++,
определенным образом связан-
ное со
структурами.
Структуры
Структура является
объединением простых переменных. Эти
переменные могут
иметь различные
типы: int,
float
и т. д. (как
мы позже увидим, именно разнородно-
стью
типов переменных структуры отличаются
от массивов, в которых все пере-
менные
должны иметь одинаковый тип).
Переменные, входящие в состав струк-
туры,
называются
полями
структуры.
В книгах, посвященных
программированию на C, структуры зачастую
рас-
сматриваются как одно из
дополнительных средств языка и изучаются
в конце
курса. Для тех, кто изучает
язык C++,
структуры являются одной из состав-
ляющих
главных концепций языка — объектов и
классов. На самом деле син-
таксис
структуры фактически идентичен
синтаксису класса. На практике отли-
чие
структуры от класса заключается в
следующем: структуры, как правило,
используют
в качестве объединения данных, а классы
— в качестве объединения
данных и
функций. Таким образом, изучая структуры,
мы тем самым заклады-
ваем основы
для понимания классов и объектов.
Структуры в C++
имеют пред-
назначение, сходное с
элементом
запись
языка Pascal
и некоторых
других язы-
ков программирования.Глава 4
Простая структура
Мы начнем рассмотрение со структуры,
содержащей три поля, два из которых
имеют
целый тип и одно поле — вещественный
тип. Эта структура предназначе-
на
для хранения информации о комплектующих
деталях изделий, выпускаемых
фабрикой.
Компания производит несколько типов
изделий, поэтому номер моде-
ли
изделия включен в структуру как первое
из полей. Номер самой детали пред-
ставлен
вторым полем, а ее стоимость — последним,
третьим полем.
В программе PARTS
определяется
структура part
и переменная
part1
типа part.
Затем
полям переменной part
присваиваются
значения и выводятся на экран.
//
parts.cpp
//
структура для хранения информации о
деталях изделий
#include
<iostream>
using
namespace
std;
//////////////////////////////////////////////////////////
struct
part
//
объявление структуры
{
int
modelnumber;
//
номер модели изделия
int
partnumber;
//
номер детали
float
cost;
//
стоимость детали
};
//////////////////////////////////////////////////////////
int
main()
{
part
part1;
//
определение структурной переменной
part1.modelnumber
=
6244; //
инициализация
полей
part1.partnumber
=
373; //
переменной
part1
part1.cost
=
217.55F;
//
вывод значений полей на экран
cout
<<
"Модель
"
<< part1.modelnumber;
cout
<<
",
деталь
"
<< part1.partnumber;
cout
<<
",
стоимость
$"
<< part1.cost
<<
endl;
return
0;
}
Результат работы программы выглядит
следующим образом:
Модель
6244, деталь 373, цена $217.55
В программе PARTS
присутствуют
три основных аспекта работы со
структура-
ми: определение структуры,
определение переменной типа этой
структуры и до-
ступ к полям структуры.
Давайте подробно рассмотрим каждый из
этих аспектов.
Определение
структуры
Определение структуры задает ее
внутреннюю организацию, описывая
поля,
входящие в состав структуры:
struct
part
{
int
modelnumber;
int
partnumber;
float
cost;
};
Синтаксис
определения структуры
Определение
структуры начинается с ключевого слова
struct
Затем следует
имя
структуры, в данном случае этим
именем является part.
Объявления
полей струк-
туры modelnumber,
partnumber
и cost
заключены в
фигурные скобки. После за-
крывающей
фигурной скобки следует точка с запятой
(;)
— символ, означающий
конец определения
структуры. Обратите внимание на то, что
использование
точки с запятой после
блока операторов при определении
структуры отличает
синтаксис
структуры от синтаксиса других
рассмотренных нами элементов про-
граммы.
Как мы видели, в циклах, ветвлениях и
функциях блоки операторов
тоже
ограничивались фигурными скобками,
однако точка с запятой после таких
блоков
не ставилась. Синтаксис структуры
представлен на рис. 4.1.
Смысл определения
структуры
Определение
структуры part
необходимо для
того, чтобы создавать на его
основе
переменные типа part.
Само определение
не создает никаких переменных; други-
ми
словами, не происходит ни выделения
физической памяти, ни объявления
переменной.
В то же время определение обычной
переменной предполагает вы-
деление
памяти под эту переменную. Таким образом,
определение структуры
фактически
задает внутреннюю организацию структурных
переменных после то-
го, как они будут
определены. Рисунок 4.2 иллюстрирует
вышесказанное.
Не удивляйтесь,
если связь между структурой и структурными
переменны-
ми покажется вам сходной
со связью между классами и объектами,
о которой
шла речь в главе 1 «Общие
сведения». Как мы позже увидим, объект
действи-
тельно имеет такое же
отношение к своему классу, как структурная
переменная
к своей струкtype.
Определение
структурной переменной
Первый оператор
функции main()
выглядит
следующим образом:
part
part1;
Он представляет
собой определение переменной part1,
имеющей тип
part.
Определение
переменной означает, что под эту
переменную выделяется память.
Рис.
4.1.
Синтаксис определения структуры
Сколько же памяти
выделяется в данном случае? Под
структурную переменную
всегда
отводится столько памяти, сколько
достаточно для хранения всех ее по-
лей.
В нашем примере необходимо выделить
по 4 байта для двух полей типа int
(если
считать, что операционная система
является 32-битной)
и 4 байта для
поля типа float.
На рис. 4.3
изображено расположение в памяти
переменной
part1.
Определение
структуры
Foo
Переменные
типа Foo
Рис.
4.2.
Структуры и их переменные
Рис.
4.3.
Расположение членов структуры в памяти
В некотором смысле
мы можем считать структуру part
новым типом
данных.
Этот вопрос станет более
понятен при дальнейшем рассмотрении,
однако уже
сейчас вы можете заметить, что определение
структурной переменной по своему
синтаксису
идентично определению переменной
стандартного типа:
part
part1;
int
var1;
Такое сходство не
является случайным. Одна из целей языка
C++
— сделать
работу с пользовательскими
типами данных максимально похожей на
работу со
стандартными типами данных
(в
языке C при определении структурных
пере-
менных необходимо применять
ключевое слово struct;
определение
переменной
part1
на языке C
выглядело бы как struct
part
part1).
Доступ к полям
структуры
Когда структурная
переменная определена, доступ к ее
полям возможен с приме-
нением пока
неизвестной нам
операции точки.
В программе первому из полей
структуры
присваивается значение при помощи
оператора
part1.modelnumber
=
6244;
Поле структуры
идентифицируется с помощью трех
составляющих: имени
структурной
переменной part1,
операции точки
(.)
и имени поля modelnumber.
Подобную
запись следует понимать как «поле
modelnumber
переменной
part1».
Операция
точки в соответствии с общепринятой
терминологией называется
операцией
доступа к полю структуры,
но, как правило, такое длинное название
не
употребляют.
Обратите внимание
на то, что в выражении с использованием
операции точ-
ки (.)
на первом месте стоит не название
структуры (part),
а имя
структурной
переменной (part1).
Имя переменной
нужно для того, чтобы отличать одну
пе-
ременную от другой: part1
от part2
и т. д., как
показано на рис. 4.4.
С полями структурной переменной можно
обращаться так же, как с обычны-
ми
простыми переменными. Так, в результате
выполнения оператора
part1.modelnumber
=
6244;
полю modelnumber
присваивается
значение 6244 при помощи обычной
операции
присваивания. В программе
также продемонстрирован вывод значения
поля на
экран с помощью cout:
cout
<< "\nМодель
"
<< part1.modelnumber;
Другие возможности
структур
Структуры обладают достаточно широким
набором возможностей. Рассмотрим
некоторые
из них.
Инициализация
полей структуры
Следующий пример демонстрирует способ,
при помощи которого можно инициа-
лизировать
поля предварительно определенной
структурной переменной. В про-
грамме
используются две структурные переменные.
Рис.
4.4.
Операция «точка»
//
partinit.cpp
//
инициализация структурных переменных
#include
<iostream>
using
namespace std;
//////////////////////////////////////////////////////////
struct
part //
объявление
структуры
{
int
modelnumber; //
номер
модели
изделия
int
partnumber; //
номер
детали
float
cost; //
стоимость детали
};
//////////////////////////////////////////////////////////
int
main()
{
//
инициализация переменной
part
part1 = { 6244, 373, 217.55F };
part
part2; //
объявление переменной
//
вывод полей первой переменной
cout
<< "Модель
"
<< part1.modelnumber;
cout
<< ",
деталь
"
<< part1.partnumber;
cout
<< ",
стоимость
$"
<< part1.cost << endl;
part2
= part1; //
присваивание структурных переменных
//
вывод полей второй переменной
cout
<<
"Модель
"
<< part2.
modelnumber;
cout
<<
",
деталь "
<< part2.partnumber;
cout
<<
",
стоимость $"
<< part2.cost
<< endl;
return
0;
}
В приведенной
программе определены две переменные
типа part:
part1
и part2.
После
того как поля переменной part1
инициализированы,
происходит вывод их
значений на
экран, затем значение переменной part1
присваивается
переменной
part2,
и значения ее
полей также выводятся на экран. Результат
работы про-
граммы выглядит следующим
образом:
Модель
6244, деталь
373,
стоимость
$217.55
Неудивительно, что обе выведенные
строки идентичны, поскольку значение
второй
переменной было присвоено первой
переменной.
Инициализация
полей переменной part1
производится
в момент ее опреде-
ления:
part
part1
= { 6244, 373, 217.55F
};
Значения, которые присваиваются полям
структурной переменной, заключе-
ны
в фигурные скобки и разделены запятыми.
Первая из величин присваивает-
ся
первому полю, вторая — второму полю и
т. д.
Присваивание
структурных переменных
Как мы видим из
программы PARTINIT,
мы можем
присваивать значение одной
структурной
переменной другой структурной переменной:
part2
= part1;
Значение каждого
поля переменной part1
присваивается
соответствующему
полю переменной
part2.
Поскольку в
больших структурах число полей иногда
мо-
жет измеряться десятками, для
выполнения присваивания структурных
перемен-
ных компилятору может
потребоваться проделать большое
количество работы.
Обратите внимание на то, что операция
присваивания может быть выполне-
на
только над переменными, имеющими один
и тот же тип. В случае попытки
выполнить
операцию присваивания над переменными
разных типов компиля-
тор выдаст
сообщение об ошибке.
Пример применения
структур
Рассмотрим теперь,
каким образом можно применить способность
структуры
объединять данные различных
типов. Возможно, вы знаете, что в
английской
системе мер основными
единицами измерения длины служат фут
и дюйм, при-
чем один фут равен 12
дюймам. Расстояние, равное 15 футам и 8
дюймам, запи-
сывается как 15'-8".
Дефис в данной записи не означает знак
«минус», а служит
для разделения
значений футов и дюймов. Иллюстрация
к английской системе
мер приведена
на рис. 4.5.
Рис.
4.5.
Английская система мер
Предположим, вам
необходимо создать инженерный проект
с использовани-
ем английской системы
мер. Было бы удобно представлять длины
в виде двух
чисел, одно из которых
равнялось бы количеству футов, а другое
— количест-
ву дюймов. В следующем
примере, ENGLSTRC,
такая идея
реализована с помощью
структуры. Мы
покажем, как можно при помощи типа
Distance
складывать
две
длины.
//
englstrc.cpp
//
английская система мер, реализованная
с помощью структуры
#include
<iostream>
using
namespace std;
//////////////////////////////////////////////////////////
struct
Distance //
длина в английской системе
{
int
feet;
float
inches;
};
//////////////////////////////////////////////////////////
int
main()
{
Distance
d1, d3; //
определения двух переменных
Distance
d2 = { 11, 6.25 }; //
определение с инициализацией
//
ввод полей переменной d1
cout
<< "\nВведите
число футов: ";
cin
>>
d1.feet;
cout
<< "Введите
число дюймов: ";
cin
>>
d1.inches;
//
сложение длин d1 и d2 и присвоение
результата d3
d3.inches
= d1.inches + d2.inches; //
сложение
дюймов
d3.feet
= 0;
//
с возможным заемом
if(d3.inches
>= 12.0)
//
если сумма больше 12.0,
{
//
то уменьшаем
d3.inches
-= 12.0; //
число дюймов на 12.0 и
d3.feet++;
//
увеличиваем число футов на 1
}
d3.feet
+= d1.feet + d2.feet; //
сложение футов
//
вывод всех длин на экран
cout
<< d1.feet
<< "\'-"
<<
d1.inches
<<
"\" + ";
cout
<< d2.feet << "\'-"
<<
d2.inches <<
"\" = ";
cout
<< d3.feet << "\'-"
<<
d3.inches <<
"\"\n";
return
0;
}
Здесь структура
Distance
состоит из двух
полей: feet
и inches.
Число дюймов
не
обязательно является целым, поэтому
для его хранения мы используем тип
float.
Число футов,
наоборот, всегда является целым, и
поэтому его можно хра-
нить в переменной
типа int.
Мы определяем
переменные типа Distance,
d1,
d2
и d3,
причем переменную
d2
мы
инициализируем значением 11'-6.25", а
переменные d1
и d3
пока оставлены
без
начального значения. Далее программа
запрашивает у пользователя число
футов
и дюймов, которые используются для
инициализации переменной d1
(при
этом
число дюймов должно быть меньше 12.0).
Затем значения d1
и d2
склады-
ваются,
а результат присваивается переменной
d3.
Наконец,
программа выводит
две первоначальные
длины и их сумму. Примером результата
работы програм-
мы может служить
следующий:
Введите
число футов: 10
Введите число дюймов:
6.75
10'-6.75" + 11'-6.25" = 22' -1"
Обратите внимание на то, что мы не можем
сложить две длины следующим
образом:
d3
=
d1
+
d2;
//
некорректное действие
Такое действие
вызовет ошибку потому, что в C++
не определены дейст-
вия, которые
необходимо выполнить при сложении
переменных типа Distance.
Операция
+
применима для стандартных типов C++,
но она не определена
для типов данных,
которые создаются пользователями (как
мы увидим в гла-
ве 8 «Перегрузка
операций», одним из достоинств классов
является возмож-
ность определять
сложение и другие операции над
пользовательскими типами
данных).
Вложенные
структуры
Структуры допускают
вложенность, то есть использование
структурной перемен-
ной в качестве
поля какой-либо другой структуры. Внесем
дополнения в програм-
му ENGLSTRC,
которые позволят
это продемонстрировать. Пусть нам
необходимо
хранить данные о размерах
комнаты, то есть ее ширину и длину.
Поскольку мы
работаем с английской
системой мер, нам придется хранить эти
величины с исполь-
зованием типа
Distance:
struct
Room
{
Distance
length;
Distance width;
}
//
englarea.cpp
//
использование вложенных структур
#include
<iostream>
using
namespace std;
//////////////////////////////////////////////////////////
struct
Distance //
длина
в
английской
системе
{
int
feet; //
футы
float
inches; //
дюймы
};
//////////////////////////////////////////////////////////
struct
Room
//
размеры
прямоугольной
комнаты
{
Distance
length; //
длина
Distance
width; //
ширина
};
//////////////////////////////////////////////////////////
int
main()
{
Room
dining;
//
переменная
dining типа
Room
dining.length.feet
= 13; //
задание параметров комнаты
dining.length.inches
= 6.5;
dining.width.feet
= 10;
dining.width.inches
= 0.0;
//
преобразование длины и ширины в
вещественный формат
float
l = dining.length.feet + dining.length.inches / 12;
float
w = dining.width.feet + dining.width.inches / 12;
//
вычисление площади комнаты и вывод на
экран
cout
<< "Площадь
комнаты равна "
<< l * w
<<
"
квадратных футов\n";
return
0;
}
В данной программе
используется единственная переменная
dining,
имеющая
тип
Room:
Room
dining; //
переменная
dining
типа
Room
Затем программа производит различные
действия с полями этой структур-
ной
переменной.
Доступ к полям
вложенных структур
Если одна структура
вложена в другую, то для доступа к полям
внутренней
структуры необходимо
дважды применить операцию точки (.):
dining.length.feet
=
13;
В этом операторе
dining
— имя структурной
переменной, как и раньше;
length
— имя поля
внешней структуры Room;
feet
— имя поля
внутренней струк-
туры Distance.
Таким образом,
данный оператор берет поле feet
поля Length
пере-
менной
dining
и присваивает
этому полю значение, равное 13. Иллюстрация
этого
механизма приведена на рис.
4.6.
Рис.
4.6.
Операция «точка» и вложенные структуры
Когда поля переменной
dining
инициализированы,
программа подсчитывает
площадь
комнаты, как показано на рис. 4.7.
Чтобы найти площадь
комнаты, программе необходимо выразить
значения
длины и ширины в футах. Для
этого используются переменные l
и w
типа float.
Их
значения получаются путем сложения
числа футов соответствующего изме-
рения
с числом дюймов, деленным на 12.
Преобразование целого типа поля feet
к
типу float
произойдет
автоматически, и результат сложения
будет иметь тип
float.
Затем переменные
l
и w
перемножаются,
в результате чего мы получаем
значение
площади комнаты.
Преобразования
пользовательских типов данных
Обратите внимание
на то, что программа преобразовывает
две величины типа
Distance
к двум величинам
типа float.
Кроме того, при
вычислении площади ком-
наты на самом
деле осуществляется преобразование
переменной типа Room,
хра-
нящей
два значения типа Distance,
к одному
вещественному значению. Результат
работы
программы выглядит так:
Площадь
комнаты равна 135.416672 квадратных футов
Возможность преобразования значений
одного типа в значения другого
типа
является важным аспектом для
программ, которые используют типы
данных,
определяемые пользователем.
Инициализация
и вложенные структуры
Каким образом
инициализировать структурную переменную,
которая содержит
внутри себя поле,
также являющееся структурной переменной?
Следующий опе-
ратор инициализирует
переменную dining
теми же
значениями, что и в послед-
ней
программе:
Room
dining
=
{
{13,
6.5},
{10,
0.0} };
Каждая структура
Distance,
входящая в
состав типа Room,
инициализируется
отдельно.
Как мы уже говорили, значения, которыми
инициализируется струк-
турная
переменная, заключаются в фигурные
скобки и разделяются запятыми.
Первая
из внутренних структур Distance
инициализируется
с помощью конструкции:
{13,
6.5}
а вторая — с помощью
конструкции:
{10,
0.0}
Инициализировав
по отдельности каждое из полей
типа Distance,
мы инициа-
лизируем
переменную типа Room,
заключив
значения типа Distance
в фигурные
скобки
и разделив их запятыми.
Глубина
вложения
Теоретически не существует ограничения
на величину уровня вложенности
структур.
В программе, работающей с дизайном
квартир, вы встретите такое об-
ращение
к полю структурной переменной:
apartment1.laundry_room.washing_machine.width.feet
Пример карточной
игры
Давайте рассмотрим еще один пример. В
нем с помощью структуры будет соз-
дана
модель игральной карты. Эта программа
имитирует действия уличного
игрока.
Игрок показывает вам три карты,
перемешивает их и раскладывает.
Если
вам удастся угадать, в какой
последовательности разложены карты,
то вы
выиграли. Все происходит у вас
на виду, но игрок мешает карты настолько
бы-
стро и умело, что вы путаетесь в
расположении карт и, как правило,
проигрыва-
ете свою ставку.
Структура, хранящая информацию об
игральной карте, выглядит так:
struct
card
{
int
number;
int
suit;
};
Эта структура
содержит два поля, number
и suit,
предназначенных
для хране-
ния соответственно
достоинства карты и ее масти. Достоинство
карты определя-
ется числом от 2 до
14, где числа 11, 12, 13 и 14 означают
соответственно валета,
даму, короля
и туза. Масть карты — число от 0 до 3, где
0 означает трефовую
масть, 1 — бубновую,
2 — червовую, 3 — пиковую.
Листинг программы
CARDS
выглядит
следующим образом:
//
cards.cpp
//
представление игральных карт при помощи
структуры
#include
<iostream>
using
namespace std;
const
int
clubs = 0; //
масти
const
int
diamonds = 1;
const
int
hearts = 2;
const
int
spades = 3;
const
int
jack = 11; //
достоинства
карт
const
int
queen = 12;
const
int
king = 13;
const
int
ace = 14;
//////////////////////////////////////////////////////////
struct
card
{
int
number; //
достоинство
int
suit; //
масть
};
//////////////////////////////////////////////////////////
int
main()
{
card
temp, chosen, prize; //
три
карты
int
position;
card
card1 = { 7, clubs }; //
инициализация
карты
1
cout
<< "Карта
1: 7 треф\n";
card
card2 = { jack, hearts }; //
инициализация
карты
2
cout
<< "карта
2: валет червей\n";
card
card3
= { ace,
spades
};
//
инициализация карты 3
cout
<< "Карта
3: туз пик\n
";
prize
= card3;
//
запоминание карты 3
cout
<< "Меняем
местами карту 1 и карту 3...\n";
temp
= card3; card3 = card1; card1 = temp;
cout
<< "Меняем
местами карту 2 и карту 3...\n";
temp
= card3; card3 = card2; card2 = temp;
cout
<< "Меняем
местами карту 1 и карту 2...\n";
temp
= card2; card2 = card1; card1 = temp;
cout
<< "На
какой позиции (1, 2 или 3) теперь туз пик?
";
cin
>>
position;
switch(position)
{
case
1: chosen = card1; break;
case
2: chosen = card2; break;
case
3: chosen = card3; break;
}
if(chosen.number
== prize.number && //
сравнение карт
chosen.suit
== prize.suit)
cout
<< "Правильно!
Вы
выиграли!\n";
else
cout
<< "Неверно.
Вы проиграли.\n";
return
0;
}
Вот пример возможного
взаимодействия с программой:
Карта
1:
7 треф
Карта 2: валет червей
Карта
3: туз пик
Меняем
местами карту 1 и карту 3
Меняем
местами карту 2 и карту 3
Меняем
местами карту 1 и карту 2
На
какой позиции (1.2 или 3) теперь туз пик?
3
Неверно.
Вы проиграли.
В данном случае
незадачливый игрок выбрал неверную
карту (правильным
ответом
было число 2).
Программа начинается
с объявления нескольких переменных
типа const
int,
предназначенных
для хранения величин, соответствующих
четырем мастям и
четырем достоинствам,
имеющим словесное (нецифровое)
название. В данной
программе
используются не все из объявленных
переменных; «лишние» объяв-
ления
сделаны в целях сохранения общности
алгоритма. Далее в программе оп-
ределяется
структура card
и три
неинициализируемые структурные
переменные
temp,
chosen
и prize.
Позже определяются
и инициализируются еще три струк-
турные
переменные: card1,
card2
и card3,
играющие роль
трех карт, предназна-
ченных для
угадывания. Информация об этих картах
выводится игроку на эк-
ран. Далее
одна из карт запоминается с помощью
переменной prize,
и эту карту
будет
предложено угадать игроку в конце игры.
Теперь программа
перемешивает карты. Она меняет местами
первую и третью
карты, затем вторую
и третью карты, и наконец, первую и
вторую карты. При
этом программа
сообщает игроку обо всех перестановках
(если
такой вариант
игры покажется вам
слишком простым, можете добавить в
программу еще не-
сколько операций
по перемешиванию карт. Кроме того, можно
усложнить пра-
вила игры, ограничив
время, в течение которого сообщение о
перестановке карт
будет присутствовать
на экране).
Программа спрашивает
пользователя, где находится одна из
карт. Информа-
ция о карте, находящейся
в выбранной позиции, записывается в
переменную
chosen,
значение которой
сравнивается со значением переменной
prize.
Если эти
значения
совпадают, то игрок выигрывает; в
противном случае игрок считается
проигравшим.
Обратите внимание на то, насколько
простой оказывается реализация
пере-
мешивания карт:
temp
= card3; card3 = card2; card2 = temp;
Благодаря возможности выполнения
операции присваивания над структур-
ными
переменными процесс перемешивания
карт в программе очень похож на
аналогичный
процесс в реальной жизни.
К сожалению, сравнивать между собой
структурные переменные, как и скла-
дывать
их друг с другом, нельзя. Конструкция
if(chosen
==
prize)
//
некорректно
недопустима потому,
что операции ==
ничего не известно о переменных
типа
card.
Однако, как мы
увидим позже, данная проблема разрешима
с помощью пе-
регрузки операций.
Структуры и
классы
Мы должны признать,
что утаили от вас некоторые сведения,
касающиеся воз-
можностей структур.
Мы были правы, когда говорили, что
структуры обычно
используются для
объединения данных, а классы — для
объединения данных
и функций. Тем
не менее, в C++
структуры также обладают возможностью
включать
в себя функции (что,
правда, неверно в отношении языка С).
Различия
в синтаксисе между структурами
и классами минимальны, поэтому
теоретически
можно использовать
одно вместо другого. Однако структуры
обычно использу-
ют только для
хранения данных, а классы — для хранения
данных и функций.
Мы разберем этот
вопрос подробнее в главе 6 «Объекты и
классы».
Перечисления
Как мы уже видели,
структуры можно рассматривать в качестве
нового типа дан-
ных, определяемого
пользователем. Кроме структур, существует
еще один спо-
соб создания
пользовательских типов данных, называемый
перечислением.
Этот
способ имеет гораздо меньшую
практическую важность, чем структуры,
и для
того, чтобы писать хорошие
объектно-ориентированные программы
на языке
С++,
нет необходимости применять перечисления.
И все же перечисления отно-
сятся к типичным
средствам программирования в стиле
C++,
и их использова-
ние может заметно
упростить процесс создания вашей
программы.
Дни недели
Перечисления
используются в тех случаях, когда
переменные создаваемого типа
могут
принимать заранее известное конечное
(и,
как правило, небольшое)
мно-
жество значений. Приведем простой
пример, DAYENUM,
в котором
перечисления
используются для
создания типа данных, хранящего дни
недели.
//
dayenum.cpp
//
применение перечислений
#include
<iostream>
using
namespace std;
//
объявление перечисляемого типа
enum
days_of_week { Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
};
int
main()
{
days_of_week
day1, day2; //
определения переменных,
//
хранящих дни недели
day1
= Mon;
//
инициализация переменных
day2
= Thu;
int
diff = day2 - day1; //
арифметическая операция
cout
<< "Разница
в днях: "
<< diff << endl;
if(day1
< day2)
//
сравнение
cout
<< "day1
наступит раньше, чем day2\n";
return
0;
}
Объявление типа
начинается со слова enum
и содержит
перечисление всех
возможных значений
переменных создаваемого типа. Эти
значения называются
константами
перечисляемого
типа.
Перечисляемый тип days_of_week
включает
7
констант перечисляемого типа: Sun,
Mon,
Tue
и т. д. до Sat.
На рис. 4.8
приведен
синтаксис объявления
перечисляемого типа.
Рис.
4.8.
Синтаксис спецификатора enum
Итак, перечисление
представляет собой список всех возможных
значений.
В этом отношении тип int
отличается от
перечислений, поскольку он задается
Рис.
4.9.
Использование типов int
и
enum
Когда тип days_of_week
определен,
можно определять и переменные этого
ти-
па. В программе DAYENUM
мы используем
две переменные типа days_of_week:
days_of_week
day1,
day2;
В языке C в подобных
объявлениях было необходимо использовать
ключе-
вое слово enum:
enum
days_of_week
day1,
day2;
но язык C++
устранил эту необходимость.
Переменным
перечисляемого типа можно присваивать
любое из значений,
указанных при
объявлении типа. Например, переменным
day1
и day2
из нашей
последней
программы мы присваиваем значения Mon
и Thu.
Присваивание
зна-
чений, не указанных при
перечислении, например
day1
=
halloween;
не допускается.
Перечисляемые типы
данных допускают применение основных
арифметиче-
ских операций. В частности,
в нашей программе производится вычитание
двух пе-
ременных перечисляемого
типа. Кроме того, перечисляемые типы
допускают
с помощью диапазона
значений. Используя перечисления,
необходимо давать
имя каждому
возможному значению создаваемого типа.
Различие между типом
int
и перечисляемыми
типами проиллюстрировано на рис. 4.9.
тип
enum
Небольшое
число значений
поименовано, и
обращение
к ним происходит по именам
тип
int
Когда
значений много,
они не именуются;
обращение
по значениям
применение операции
сравнения, что также используется в
нашем примере.
Результат работы
программы DAYENUM
выглядит
следующим образом:
Разница
в днях: 3
day1
наступит
раньше, чем day2
Использование
арифметических операций и операций
отношения с перечис-
ляемыми типами
данных, как правило, не несет большой
смысловой нагрузки.
Например, если
мы определили тип данных pets,
хранящий
названия домашних
животных, следующим
образом:
enum
pets {
cat,
dog,
hamster,
canary,
ocelot
};
то неясен смысл
выражений dog
+
canary
или (cat
<
hamster)
и т.п.
Внутренне
перечисляемые типы данных представляются
и обрабатываются
как целые числа.
Этот факт объясняет возможность
применения к переменным
перечисляемого
типа арифметических операций и операций
отношения. Фак-
тически первое
значение в списке рассматривается как
число 0, второе — как
число 1, и т. д.
В программе DAYENUM
значения от
Sun
до Sat
представляют
собой
целые числа в диапазоне 0...6.
Арифметические операции над переменными
перечисляемых типов сводятся
к
операциям над целыми числами. Однако,
несмотря на то, что компилятор зна-
ет
о целочисленной форме представления
перечисляемых значений, стоит
ис-
пользовать этот факт с большой
осторожностью. Если вы попробуете
выпол-
нить присваивание
day1
=
5;
компилятор выдаст
предупреждающее сообщение (хотя
компиляция произой-
дет без ошибок).
Рекомендуется там, где возможно, не
использовать целочис-
ленную
интерпретацию перечисляемых значений.
Перечисления и
программа подсчета числа слов
Наша следующая
программа подсчитывает количество
слов в предложении, - вво-
димом с
клавиатуры пользователем. Структура
работы программы показана на
рис.
4.10.
Флаг
isWord
Рис.
4.10.
Работа программы WDCOUNT
В отличие от примера
CHCOUNT,
здесь мы уже
не будем сводить подсчет слов
к
подсчету введенных пробелов (хотя
наша программа все еще не будет обраба-
тывать табуляции
и прочие разделяющие символы).
Мы используем перечис-
ляемый тип
данных с двумя значениями. Вот листинг
программы WDCOUNT:
//
wdcount.cpp
//
подсчет числа слов в предложении с
использованием перечислений
#include
<iostream>
using
namespace std;
#include
<conio.h>
//
для
getche()
enum
itsaWord { NO,
YES
}; //
NO = 0, YES = 1
int
main()
{
itsaWord
isWord = NO;
//
isWord равно
YES, когда
//
вводится слово, и NO, когда вводятся
пробелы
char
ch = 'a';
//
считывание символа с клавиатуры
int
wordcount = 0; //
число слов
cout
<< "Введите
предложение: \n";
do
{
ch
= getche();
//
ввод символа
if(ch
== '
'
|| ch == '\r')//
если введен пробел,
{
if(isWord
== YES)
//
а до этого вводилось слово,
{
//
значит, слово закончилось
wordcount++;
//
учет слова
isWord
= NO;
//
сброс флага
}
}
//
в противном случае
else
//
ввод слова продолжается
if(isWord
== NO)
//
если начался ввод слова,
isWord
= YES;
//
то устанавливаем флаг
}
while(ch
!= '\r');
//
выход по нажатию Enter
cout
<< "\n---Число
слов:
" <<
wordcount <<
"---\n";
return
0;
}
Программа считывает
символы с клавиатуры в цикле do.
Она не
выполняет
никаких дополнительных
действий над непробельными символами.
Когда с кла-
виатуры вводится пробел,
счетчик количества слов увеличивается
на единицу,
после чего программа
игнорирует все пробелы, вводимые до
появления первого
непробельного
символа. Далее программа снова
«пропускает» непробельные сим-
волы
до появления пробела, увеличивает
счетчик количества слов на единицу
и
т. д. Для того чтобы реализовать подобный
алгоритм, программе необходимо
различать,
вводится ли в данный момент слово или
последовательность пробе-
лов. Для
этого используется переменная isWord
перечисляемого
типа itsaWord,
определенного
следующим образом:
enum
itsaWord
{ NO,
YES
};
Переменные типа
itsaWord
могут иметь
только два различных значения:
NO
и
YES.
Обратите
внимание на то, что перечисление
начинается со значения NO;
это
означает, что этому значению будет
соответствовать внутреннее представле-
ние
в виде целого числа 0, которое, как мы
знаем, может интерпретироваться
еще
и как ложное значение (мы
могли бы использовать вместо
перечисляемого
типа стандартный
тип bool).
В начале работы
программы переменной isWord
присваивается
значение NO.
Как
только с клавиатуры буден получен
первый непробельный символ, значе-
ние переменной
изменится на YES
и будет сигнализировать о том, что в
данный
момент вводится слово. Значение
YES
будет сохраняться за переменной isWord
до
тех пор,
пока с клавиатуры не будет введен
пробел. Ввод пробела означает конец
слова,
поэтому переменная isWord
получит значение
NO,
которое будет сохранять-
ся до тех
пор, пока не появится непробельный
символ. Мы знаем, что значения
NO
и YES
на самом деле представлены как 0 и 1,
однако не используем этот факт.
Мы
могли бы использовать запись if(isWord)
вместо if(isWord
==
YES)
и if(!isWord)
вместо
if(isWord
==
NO), но
это не является хорошим стилем
программирования.
Обратите внимание
на то, что нам необходимы дополнительные
фигурные
скобки вокруг второго из
операторов if,
чтобы последующий
else
сочетался не
со
вторым if,
а с первым.
Для того чтобы
организовать флаг в ситуациях, подобных
рассмотренной в
программе WDCOUNT,
можно
воспользоваться переменной типа bool.
В зависимо-
сти
от контекста задачи такой способ может
оказаться проще, чем использова-
ние
перечислений.
Пример карточной
игры
Рассмотрим еще
один, последний, пример использования
перечисляемых типов
данных. Вспомним,
что в программе CARDS,
созданной нами,
использовалась груп-
па констант
типа const
int,
предназначенных
для представления карточных мастей:
const
int
clubs =
0;
const
int
diamonds =
1;
const
int
hearts =
2;
const
int
spades =
3;
Такой способ задания
констант, как можно видеть, не отличается
изящно-
стью. Давайте перепишем код
программы CARDS,
используя
перечисления.
//
cardenum.cpp
//
карточная игра с использованием
перечислений
#include
<iostream>
using
namespace std;
const
int
jack = 11;
//
именованные достоинства карт
const
int
queen = 12;
const
int
king = 13;
const
int
ace = 14;
enum
Suit { clubs,
diamonds,
hearts,
spades
};
//////////////////////////////////////////////////////////
struct
card
{
int
number; //
достоинство карты
Suit
suit; //
масть
};
//////////////////////////////////////////////////////////
int
main()
{
card
temp, chosen, prize; //
определение карт
int
position;
card
card1 = { 7, clubs
}; //
инициализация card1
cout
<< "Карта
1: 7 треф\n";
card
card2 = { jack, hearts
}; //
инициализация card2
cout
<< "Карта
2: валет червей\n";
card
card3 = { ace, spades
}; //
инициализация card3
cout
<< "Карта
3: туз пик\n";
prize
= card3;
//
запоминаем карту 3
cout
<< "Меняем
местами карту 1 и карту 3\n";
temp
= card3; card3 = card1; card1 = temp;
cout
<< "Меняем
местами карту 2 и карту 3\n";
temp
= card3; card3 = card2; card2 = temp;
cout
<< "Меняем
местами карту 1 и карту 2\n";
temp
= card2; card2 = card1; card1 = temp;
cout
<< "На
какой позиции (1, 2 или 3) теперь туз пик?
";
cin
>>
position;
switch(position)
{
case
1: chosen = card1; break;
case
2: chosen = card2; break;
case
3: chosen = card3; break;
}
if(chosen.number
== prize.number && //
сравнение карт
chosen.suit
== prize.suit)
cout
<< "Правильно!
Вы
выиграли!\n";
else
cout
<< "Неверно.
Вы проиграли.\n
";
return
0;
}
Мы заменили серию констант, обозначающих
масти, на перечисляемый тип:
enum
Suit {
clubs,
diamonds,
hearts,
spades
};
Такой подход упрощает использование
констант, поскольку нам известны
все
возможные значения мастей, и попытка
использования некорректного зна-
чения,
например
card1.suit
=
5;
вызовет предупреждающее сообщение от
компилятора.
Задание
целых значений для перечисляемых
констант
Как мы говорили, первой из перечисляемых
констант соответствует целое значе-
ние,
равное 0, второй — значение, равное 1, и
т. д. Для того чтобы изменить зна-
чение,
с которого начинается нумерация, можно
с помощью операции присваи-
вания
задать это значение первой из перечисляемых
констант:
enum
Suit {
clubs
=
1, diamonds,
hearts,
spades
};
В этом случае следующим по списку
константам будут соответствовать
чис-
ла 2, 3 и 4 соответственно. Фактически
мы можем изменить величину целого
числа,
соответствующего любому элементу
списка, применив к нему операцию
присваивания,
как это было показано выше.
Недостаток
перечислений
Важным недостатком
перечисляемых типов данных является
то, что они не
распознаются средствами
ввода/вывода
C++.
Например,
результатом
вывода
в
фрагменте
enum
direction {
north,
south,
east,
west
};
direction
dir =
south;
cout
<<
dir1;
будет не south,
формально
являющееся значением переменной dir,
а ее внутрен-
нее
представление, то есть целое число 1.
Примеры
перечисляемых типов
Приведем несколько
примеров перечисляемых типов данных,
которые, возмож-
но, помогут вам лучше
понять область наилучшего применения
этого средства
языка C++:
enum
months {
Jan,
Feb,
Mar,
Apr,
May,
Jun,
Jul,
Aug,
Sep,
Oct,
Nov,
Dec
};
// месяцы
года
enum
switch
{
off,
on };
//
переключатель
enum
meridian {
am,
pm
};
//
меридиан
enum
chess {
pawn,
knight,
bishop,
rook,
queen,
king
};
// шахматные
фигуры
enum
coins {
penny,
nickel,
dime,
quarter,
half-dollar,
dollar
};
//
монеты
Мы еще встретимся с применением
перечислений в других разделах
нашей
книги.
Резюме
В этой главе мы
познакомились с двумя средствами C++:
структурами и пере-
числениями.
Структура является важным аспектом
C++,
поскольку ее синтаксис
совпадает с
синтаксисом класса. Классы (по
крайней мере, с точки зрения син-
таксиса)
представляют собой не что иное, как
структуры, включающие в себя
функции.
Типичной целью использования структур
является объединение дан-
ных
различных типов в один программный
элемент. В определении структуры
содержится
информация о том, какие поля находятся
внутри нее. При определе-
нии
структурных переменных выделяется
память, необходимая для размещения
значений
всех полей такой переменной. Содержимое
структурных переменных в
некоторых
ситуациях рассматривается как единое
целое, например при при-
сваивании
значения одной структурной переменной
другой структурной пере-
менной, но
в остальных случаях существует
возможность доступа к отдельным
полям
структурной переменной. Как правило,
обращение к полю структурной
переменной
производится с помощью операции точки
(.).
Перечисление представляет собой тип
данных, определяемый пользователем,
значения
которого задаются с помощью списка.
При объявлении типа указыва-
ется
его имя и список значений, каждое из
которых представлено константой
перечисляемого
типа. После объявления типа можно
определять переменные,
имеющие этот
тип. Компилятор использует внутреннее
представление значений
констант
перечисляемого типа в виде целых чисел.
Не следует смешивать между собой понятая
структуры и перечисления. Струк-
тура
представляет собой мощное и гибкое
средство, позволяющее объединять
данные
самых разных типов. Перечисления всего
лишь позволяют определять
переменные,
принимающие фиксированный перечисляемый
набор значений.
Вопросы
Ответы на приведенные вопросы можно
найти в приложении Ж.
Структура объединяет:
а) данные
одного типа;
б) логически
связанные данные;
в) целые
именованные значения;
г) переменные.
Истинно ли следующее утверждение:
структура и класс имеют схожий
синтаксис?
После закрывающей фигурной скобки
структуры ставится .
Опишите структуру,
содержащую три переменные типа int
с названиями
hrs,
mins
и sees.
Назовите
структуру именем time.
Истинно ли следующее утверждение: при
определении структуры выде-
ляется
память под переменную?
При обращении к
полю структуры левым операндом операции
(.)
является:
а) поле
структуры;
б) имя
структуры;
в) структурная
переменная;
г) ключевое
слово struct.
Напишите оператор,
присваивающий полю
hrs
структурной
переменной
time2
значение,
равное 11.
Сколько байтов
памяти займут три структурные переменные
типа time,
если
структура time
содержит три
поля типа int?
Напишите определение,
инициализирующее поля структурной
переменной
time1
типа time,
описанной в
вопросе 4, значениями hrs
=
11, mins
=
10, secs
=
59.
10. Истинно
ли следующее утверждение: вы можете
присвоить значение одной
структурной
переменной другой структурной переменной
того же типа?
11. Напишите
выражение, присваивающее переменной
temp
значение поля
paw
структурной
переменной fido.
12.
Перечисление объединяет:
а) данные
различных типов;
б) логически
связанные переменные;
в) именованные
целые числа;
г) константные
значения.
Напишите оператор,
описывающий перечисление с именем
players
и на-
бором
значений B1,
B2, SS,
B3,
RF,
CF,
LF,
P
и C.
Считая, что
перечисление players
задано так,
как указано в вопросе 13, оп-
ределите
переменные joe
и tom
типа players
и присвойте
им значения LF
и
P
соответственно.
Учитывая выражения, созданные при
ответах на вопросы 13 и 14, укажи-
те,
какие из следующих операторов являются
корректными:
а) joe
=
QB;
б) tom
=
SS;
в) LF
=
tom;
г) difference
=
joe
-
tom.
Первые три константы
перечисляемого типа обычно представляются
чис-
лами , и .
Напишите оператор,
в котором объявляется перечисляемый
тип speeds
с
константами
obsolete,
single
и album.
Присвойте
этим константам целые
значения 78,
45 и 33.
Объясните, почему
объявление
enum
isWord
{
NO,
YES
};
более удачно, чем объявление
enum
isWord
{
YES,
NO
};
Упражнения
Решения к упражнениям,
помеченным знаком *,
можно найти в приложении Ж.
*1.
Номер
телефона, например (212)
767—8900, можно условно разделить на
три
части: код города (212),
номер телефонной станции (767)
и номер
абонента
(8900).
Напишите программу с использованием
структуры, поз-
воляющую
раздельно хранить эти три части
телефонного номера. Назо-
вите
структуру phone.
Создайте две
структурные переменные типа
phone.
Инициализацию
одной из них произведите сами, а значения
для другой
запросите
с клавиатуры. Затем выведите содержимое
обеих переменных
на
экран. Результат работы программы
должен выглядеть приблизитель-
но
так:
Введите
код города, номер станции и номер
абонента:
415
555 1212
Мой
номер (212) 767-8900
Ваш
номер (415) 555-1212
*2.
Расположение
точки на плоскости можно задать с
помощью двух коорди-
нат:
x и y. Например, если точка имеет координаты
(4,
5),
то это значит, что
она
отстоит на 4 единицы справа от вертикальной
оси и на 5 единиц вверх
от горизонтальной оси. Сумма двух точек
определяется как точка, име-
ющая
координаты, равные сумме соответствующих
координат слагаемых.
Напишите программу,
использующую для интерпретации точки
на плоско-
сти структуру с названием
point.
Определите три
переменные типа point,
и
две из них инициализируйте с помощью
значений, вводимых с клавиа-
туры.
Затем присвойте третьей переменной
значение суммы первых двух
переменных
и выведите результат на экран. Результат
работы программы
может выглядеть
следующим образом:
Введите
координаты точки p1:
3 4
Введите координаты точки p2:
5 7
Координаты точки p1
+ p2
равны
8.11
*3.
Создайте структуру с именем Volume,
содержащую три
поля типа Distance
из
примера englstrc,
для хранения
трех измерений помещения. Определи-
те
переменную типа Volume,
инициализируйте
ее, вычислите объем, зани-
маемый
помещением, и выведите результат на
экран. Для подсчета объема
переведите
каждое из значений типа Distance
в значение типа
float,
равное
соответствующей
длине в футах и хранимое в отдельной
переменной. За-
тем для вычисления
объема следует перемножить три полученные
веще-
ственные переменные.
Создайте структуру
с именем employee,
содержащую
два поля: номер со-
трудника типа
int
и величину
его пособия в долларах типа float.
Запроси-
те
с клавиатуры данные о трех сотрудниках,
сохраните их в трех струк-
турных
переменных типа employee
и выведите
информацию о каждом из
сотрудников
на экран.
Создайте структуру
типа date,
содержащую
три поля типа int:
месяц,
день
и год. Попросите пользователя ввести
день, месяц и год в формате
31/12/2002,
сохраните введенное значение в
структурной переменной, а за-
тем
извлеките данные из этой переменной
и выведите их на экран в том же
формате,
в каком они вводились.
Как мы говорили,
стандартные средства ввода/вывода
C++
вместо значе-
ний перечисляемых
типов данных выводят их внутреннее
представление
в виде целых чисел.
Для того чтобы преодолеть это
ограничение, вы мо-
жете использовать
конструкцию switch,
с помощью
которой устанавлива-
ется соответствие
между значением переменной перечисляемого
типа и ее
внутренним представлением.
Пусть, например, в программе определен
пе-
речисляемый тип данных etype,
отражающий
должность сотрудника:
enum
etype {
laborer,
secretary,
manager,
accountant,
executive,
researcher
};
Напишите программу,
которая сначала по первой букве
должности, введен-
ной пользователем,
определяет соответствующее значение
переменной, по-
мещает это значение
в переменную типа etype,
а затем выводит
полностью
название должности, первую
букву которой ввел пользователь.
Взаимодей-
ствие программы с
пользователем может выглядеть следующим
образом:
Введите
первую букву должности
(laborer,
secretary,
manager,
accountant,
executive,
researcher);
a
полное
название
должности:
accountant
Возможно, вам
понадобится два ветвления switch:
одно — для
ввода значе-
ния, другое — для вывода.
Добавьте поля
типа enum
etype
(см.
упражнение 6)
и struct
date
(см.
упраж-
нение 5)
в структуру employee
из упражнения
4. Организуйте программу
таким
образом, чтобы пользователь вводил
4 пункта данных о каждом из
трех
сотрудников: его номер, величину
зарплаты, его должность и дату
принятия
на работу. Программа должна хранить
введенные значения в трех
переменных
типа employee
и выводить
их содержимое на экран.
Вернитесь к
упражнению 9 главы 2 «Основы
программирования на C++».
В
этом упражнении требуется написать
программу, которая хранит значе-
ния
двух дробей в виде числителя и
знаменателя, а затем складывает
эти
дроби согласно арифметическому
правилу. Измените эту программу
так,
чтобы значения дробей хранились
в струкtype fraction,
состоящей из
двух
полей типа int,
предназначенных
для хранения числителя и знаменателя.
Все
значения дробей должны храниться в
переменных типа fraction.
Создайте структуру
с именем time.
Три ее поля,
имеющие тип int,
будут
называться
hours,
minutes
и seconds.
Напишите
программу, которая просит
пользователя
ввести время в формате часы, минуты,
секунды. Можно
запрашивать на ввод
как три значения сразу, так и выводить
для каж-
дой величины отдельное
приглашение. Программа должна хранить
время
в структурной переменной
типа time
и выводить
количество секунд в вве-
денном
времени, определяемое следующим
образом:
long
totalseсs
=
t1.hours
* 3600 +
t1.minutes
* 60 +
t1.seconds
Создайте структуру
с именем sterling,
хранящую
денежные суммы в старой
английской
системе, описанной в упражнениях 8 и
11 главы 3 «Циклы и
ветвления». Поля
структуры могут быть названы pounds,
shillings
и pence
и
иметь тип int.
Программа
должна запрашивать у пользователя
значение
денежной суммы в новых
десятичных фунтах (значение
должно хранить-
ся в переменной
типа double),
затем переводить
эту сумму в старую систе-
му,
сохранять переведенное значение в
переменной типа sterling
и выво-
дить
на экран полученную сумму в фунтах,
шиллингах и пенсах.
Используя структуру
time
из упражнения
9, напишите программу, кото-
рая
получает от пользователя два значения
времени в формате 12:59:59,
сохраняет
их в переменных типа struct
time,
затем переводит
оба значения
в секунды, складывает
их, переводит сумму в исходный формат,
сохраня-
ет его в переменной типа
time
и выводит
полученный результат на экран
в
формате 12:59:59.
Переработайте
программу-калькулятор для дробей,
описанную в упраж-
нении 12 главы 3
так, чтобы каждая из дробей хранилась
как значение пе-
ременной типа
struct
fraction,
по аналогии
с упражнением 8 этой главы.