8.4. Указатели на структуры
При объявлении указателя на структуру, как и в случае создания указателей на значения базовых типов, указывается тип структуры, а перед именем переменной-указателя ставится оператор *. Этот же оператор используется для получения доступа к переменной структуры по указателю на эту переменную. К0роме того, через указатель на структуру можно обращаться непосредственно к полям структуры, для чего используют оператор -> (стрелка, состоит из двух символов - и >). Например, если в программе определен указатель на переменную структуры, у которой есть поле, то доступ к этому полю можно получить с помощью инструкции указатель->поле. Пример использования указателей на структуры приведен в листинге 8.4.
// demoPtrStruct.cpp : Defines the entry point for the console application.
//
//Листинг 8.4. Указатели на структуру
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <conio.h>
struct Numbers
{
int integer;
double real;
char symbol;
};
void show(Numbers x)
{
cout << "Integer: "<<x. integer << endl;
cout << "Real: "<<x. real << endl;
cout << "Symbol: " << x. symbol << endl<<endl;
}
int main()
{
Numbers a,b;
Numbers *p,*q;
p=&a;
q=&b;
p->integer=1;
p->real=2.5;
p->symbol= 'a';
(*q).integer=2;
(*q).real=5.1;
(*q).symbol='b';
show(a);
show(*q);
getch();
return 0;
}
В программе объявлена структура Numbers, имеющая три поля: типа int, типа double и типа char. Кроме этого, описана функция show (), аргументом которой является переменная структуры Numbers, а в результате выполнения функции выводятся значения всех полей аргумента.
В главном методе программы командой Numbers a, b объявляются переменные а и b структуры Numbers, а командой Numbers *р, *q объявлены указатели р и q на переменные структуры Numbers. Значения указателям (адреса) присваиваются командами р=&а и q=&b соответственно. При этом использован, как и в случае переменных базовых типов, оператор получения адреса &. Поля переменной а заполняются посредством команд p->integer=l, p->real=2 . 5 и p->symbol='а'. В этом случае ссылка на поле реализуется через указатель р и оператор ->. Поля переменной b заполняются более консервативным способом. Для этого использованы команды (*q) .integer=2, (*q) . real=5.1 и (*q) .symbol = 'b' соответственно. Здесь принято во внимание, что инструкция *q является ничем иным, как той переменной, на которую ссылается указатель q (т.е. переменная b). Аналогично при вызове функции show () ее аргументом можно указать как имя переменной (а или b) структуры Numbers, так и инструкцию вида *р или *q. В результате выполнения программы получим следующее:
Integer: 1
Real: 2.5
Symbol: a
Integer: 2
Real: 5.1
8.5. Перечисления.
Перечисления – это список именованных целочисленных констант. Перечислимый тип определяются с помощью ключевого слова enum следующим образом:
enum имя-типа {список-значений};
Здесь имя-типа определяет новый перечислимый тип, а список-значений является перечнем разделенных запятыми имен констант данного перечислимого типа.
Следующий фрагмент определяет перечислимый тип с именем transport:
enum transport { car, truck, airplane, train, boat };
После того, как вы определили перечислимый тип, вы можете объявлять переменные этого типа. Например, следующее предложение объявляет одну переменную типа transport с именем how:
transport how;
Считая, что перечислимый тип transport объявлен указанным выше образом, следующее предложение присваивает переменной how значение airplane:
how = airplane;
При использовании перечислимых типов существенно понимать, что каждая константа перечислимого типа (или просто перечислимая константа) обозначает целое число и может быть использована в любом целочисленном выражении. Если перечислимые константы не инициализированы отдельно, первое значение из списка обозначает 0, второй 1 и т. д. Таким образом, предложение
cout << car << ' ' << train;
выводит на экран 0 3.
Имеется возможность задать значения одной или нескольким константам перечислимого типа с помощью инициализатора. Для этого после имени константы следует указать знак равенства и целое число. Если используется инициализатор, каждая следующая константа приобретает значение на 1 большее, чем предыдущая. Например, приведенное ниже предложение присваивает значение 10 константе airplane:
enum transport { car, truck, airplane = 10, train, boat };
Теперь значения констант будут следующими:
car |
0 |
truck |
1 |
airplane |
10 |
train |
11 |
boat |
12 |
Перечислимые константы не могут быть введены или выведены в виде отображающих их имена. Например, следующий фрагмент не будет выполняться так, как задумано:
// Этот фрагмент не выведет "train" на экран,
how = train;
cout << how;
Не забывайте, что обозначение train представляет собой просто имя целого числа; это не строка. Поэтому приведенный выше фрагмент выведет на экран числовое значение train, а не строку "train". Между прочим, создание кода, который будет вводить и выводить перечислимые константы в виде строк, оказывается довольно утомительным занятием. Например, для того, чтобы вывести на экран словами вид транспортного средства, которому отвечает значение переменной how, потребуется следующий код:
switch(how) {
case car:
cout << "Automobile"; break;
case truck:
cout « "Truck"; break*;
case airplane:
cout << "Airplane"; break;
case train:
cout << "Train"; break;
case boat:
cout << "Boat"; break;
}
Иногда оказывается возможным объявить массив строк и использовать значения перечислимых констант в качестве индексов для преобразования значений в соответствующие им строки. Например, приведенная ниже программа выводит на экран имена трех транспортных средств:
// demoEnum1.cpp : Defines the entry point for the console application.
//
// Листинг 8.5. Демонстрация работы с перечислимым типом.
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <conio.h>
enum transport { car, truck, airplane, train, boat } ;
char name[] [20] = {
"car [avtomobile]",
"track [gruzovik]",
"airplane [samolet]",
"train [poezd]",
"boat [lodka]"
};
int main()
{
//Значение перечислимой константы используется в качестве индекса массива.
transport how;
how = car;
cout << name[how] << '\n';
how = airplane;
cout << name[how] << '\n';
how = train;
cout << name[how] << '\n';
getch();
return 0;
}
Вот вывод этой программы:
car [автомобиль]
airplane [самолет]
train [поезд]
Метод, использованный в этой программе для преобразования значения перечислимой константы в строку, может быть приложен к любому перечислимому типу, если только он не содержит инициализаторов. Для правильной индексации массива строк значения перечислимых констант должны начинаться с нуля и располагаться далее строго в восходящем порядке, каждое точно на 1 больше предыдущего.
Контрольные вопросы
Что такое структура, как она определяется?
Что такое поля структуры и как к ним выполняется обращение?
Чем переменная (экземпляр) структуры отличается от непосредственно структуры?
Каким образом создаются массивы структур?
Как создаются указатели на экземпляры структуры? Каким образом через указатель осуществляется обращение к полям структуры?
Что такое перечисление и как оно создается?
Задачи для самостоятельного решения
Создайте структуру и функцию. Передайте структуру функции в качестве аргумента. Переменная х и точность eps определяются как поля структуры.
1. Написать программу для вычисления косинуса с заданной точностью :
.
2. Написать программу для вычисления экспоненты с заданной точностью :
.
3. Написать программу для вычисления гиперболического косинуса с заданной точностью :