Синтаксис: структуры в C и С++
Структура — это агрегатный тип данных, так как может содержать в себе разнотипные элементы. Синтаксис объявления структуры в С++ отличается от C. Хотя версия C остается правильной для C++. Получается, что в С++ можно двумя стилями объявления структур пользоваться, а в языке C — только одной. Смотрим синтаксис объявления структуры в языке С++:
struct Name < type atrib; // остальные элементы структуры >structVar1, structVar2, . ;
- struct — ключевое слово, которое начинает определение структуры
- Name — имя структуры
- type — тип данных элемента структуры
- atrib — элемент структуры
- structVar1-2 — структурные переменные
Объявление структуры всегда должно начинаться с ключевого слова struct . Необязательно, чтобы структура имела имя, но тогда такая структура обязательно должна иметь структурные переменные, объявленные между закрывающей фигурной скобкой и точкой с запятой, строка 5. Обязательно в объявлении структуры должны присутствовать фигурные скобочки, они обрамляют тело структуры, в котором объявляются её атрибуты (элементы), строка 3. Структурные переменные, при объявлении структуры, указывать необязательно, строка 5.
Так как структура это тип данных, то, для того, чтобы использовать этот тип данных, необходимо объявить структурную переменную, а вместо типа данных указать имя структуры.
struct_name structVariable;
Синтаксис объявления структуры в языке Си:
typedef struct name < type atrib1; type atrib2; // остальные элементы структуры. >newStructName structVar;
Синтаксис объявления структуры в языке Си предполагает два варианта. П ервый, опустить ключевое слово typedef , при этом имя newStructName тоже не используется, и имя структуры, тогда обязательно необходимо при объявлении структуры использовать структурные переменные — structVar , строка 6. Смотрим пример:
struct name structVar;
Или вы можете воспользоваться typedef , для объявления псевдонима структуры newStructName , псевдоним:
newStructName structVar;
В любом случае, если вы хотите, объявить указатель на структуру внутри структуры, вы должны использовать первый синтаксис:
struct name *struct_instance; // указатель на структуру
Объявление указателя на структуру
Синтаксис объявления указателя на структуру в Си неоднозначен. В Си, если вы не используете typedef при определении структуры, то, в обязательном порядке необходимо использовать структурные переменные, между закрывающейся фигурной скобочкой и точкой с запятой.
В C++, этого не требуется. Чтобы объявить указатель на структуру, в С++ вы просто перед именем структурной переменной ставите символ указателя — * .
structName *structVar; // указатель на структуру structName
newStructName *structVar; // newStructName должно быть объявлено с typedef
или так, тоже для СИ:
struct name *structVar;
Доступ к элементам структуры
Доступ к элементам структуры так же прост, как использование символа «точка». Предположим. что у нас есть структурная переменная с именем car и у нее есть элемент с именем speed , к которому, мы сейчас получим доступ:
car.speed;
Примечание: такой способ доступа к элементам структуры работает только в том случае, когда структура не является указателем на структуру.
Доступ к элементам указателя на структуру
Чтобы получить доступ к элементам структуры, через указатель на структуру, вместо оператора «точка», используйте оператор стрелка -> :
carPtr->speed;
P.S.: Всем владельцам Android-смартфонов представляю хорошую подборку программ GPS навигаторов для android. В списке представлено около 20 программных продуктов, вы можете любой скачать и установить на свой девайс. Все программы абсолютно бесплатные.
C++. Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR . Объявление и инициализация структурной переменной
Поиск на других ресурсах:
1. Какое отличие между базовыми и составными типами данных?
Все типы данных в C++ делятся на:
- базовые типы данных ;
- составные (агрегатные) типы данных.
Переменные базовых типов данных состоят из одного элемента данных. Переменные составных типов данных содержат два и больше элемента данных.
2. Какие типы данных в C++ принадлежат к составным или агрегатным типам данных?
Составные типы данных еще называют агрегатными или конгломератными типами данных.
К составным или агрегатным типам данных принадлежат:
- массивы;
- структуры;
- объединения;
- перечисления ( enumeration );
- классы.
3. Что называется структурой в C++ ? Что называется полем структурной переменной?
Структура – это объединения одной или больше переменных в одной области памяти, которая имеет одно имя.
Структура – это объединение (группирование) переменных, которые родственны между собою по некоторому критерию.
Переменные, входящие в структуру называются полями структуры. Такие переменные могут быть разных типов. Имена полей (переменных) в одном шаблоне должны быть уникальными. Однако, в разных шаблонах имена могут повторяться.
4. Каким образом классифицируются структуры в среде CLR ? Native -структуры. Managed -структуры
Среда CLR поддерживает объявление структур двух видов:
- native -структуры;
- managed -структуры или управляемые структуры.
Native -структуры – это классические структуры языка C/C++.
Managed -структуры – это структуры, которые размещаются в памяти, которая выделяется и управляется средой CLR .
Managed -структуры могут быть объявлены с одним из двух квалификаторов:
- квалификатор ref – означает, что структура есть ссылочного типа;
- квалификатор value – означает, что структура есть типом-значением.
Отличие между квалификаторами ref и value состоит в способе выделения памяти для указателя на структуру. Более подробно работа с указателями на managed -структуры описана здесь .
5. Какая общая форма объявления native -структуры (шаблона структуры)?
Для объявления native -структуры (или шаблона структуры) используется ключевое слово struct . Общая форма объявления структуры:
struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
- имя_типа_структуры – название шаблона структуры. Шаблон структуры описывает новый тип данных, который может быть использован в дальнейшем в программе на C++ ;
- тип – тип данных, которые имеются в наличии на данный момент в программе;
- элемент1 , элемент2 , …, элементN – названия элементов (переменных), входящих в структуру. Элементы структуры еще называются полями структуры;
- структурные_переменные – это переменные, которые есть структурами. В случае объявления шаблона структуры структурные_переменные могут отсутствовать (смотрите следующие пункты).
6. Какая общая форма объявления managed -структуры с квалификаторами ref и value ?
Общая форма объявления структуры (шаблона структуры) с квалификатором ref :
ref struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
Общая форма объявления структуры (шаблона структуры) с квалификатором value :
value struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
В вышеприведенных описаниях:
- имя_типа_структуры – название шаблона структуры. Шаблон структуры образовывает новый тип данных, который может быть использован в дальнейшем в программе;
- тип – тип данных, имеющихся на данный момент в программе;
- элемент1 , элемент2 , …, элементN – названия элементов (переменных), входящих в структуру. Элементы структуры еще называются полями структуры;
- структурные_переменные – это переменные, которые есть структурами. В случае объявления шаблона структуры структурные_переменные могут отстствовать.
Более подробно работа с managed -структурами описана в теме:
7. Что такое шаблон (формат) структуры? Примеры задания шаблона
Чтобы описать структурную переменную, нужно сначала задать шаблон структуры. Шаблон структуры еще называется формат структуры. При задании шаблона структуры память не выделяется. Шаблон – это только описание (информация), переменные каких типов должны входить в структуру.
Пример 1. Описание шаблона структуры, которая описывает информацию об отработанных часах работником.
Шаблон содержит следующую информацию:
- код работника;
- фамилия и имя работника;
- количество отработанных часов;
- расценка за 1 час.
// информация о работнике // шаблон структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
В данном примере шаблон называется Worker . В шаблоне описываются следующие поля (переменные):
- code – код работника;
- name – имя работника;
- hours – количество отработанных часов;
- cost – расценка за 1 час.
Пример 2. Объявление шаблона с именем Laboratory , содержащего информацию о лаборатории в учебном заведении:
- номер лаборатории;
- название лаборатории;
- площадь лаборатории;
- количество посадочных мест.
// информация о лаборатории // шаблон структуры struct Laboratory < int number; char name; float area; int places; >;
Для managed-структур перед словом struct указывается квалификатора ref или value .
8. Что такое структурная переменная? Способы объявления структурных переменных. Доступ к полям структурной переменной
Структурная переменная – это переменная типа, который задан в шаблоне структуры. Если объявляется такая переменная, то происходит выделение памяти для нее. Структурная переменная еще называется экземпляром структуры.
Структурную переменную можно объявить несколькими способами:
- на основе шаблона, который был объявлен раньше;
- во время объявления шаблона;
- с помощью квалификатора typedef .
Ниже приведены все 3 способы объявления структурной переменной, которая базируется на основе шаблона Worker , описывающего информацию о работнике. Рассмотрен пример для native -структуры.
// информация о работнике // шаблон native-структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
Тогда структурную переменную можна описать следующими способами.
Способ 1. Описание переменной на основе ранее заданного шаблона Worker . В этом случае сначала задается шаблон структуры, затем описывается переменная (экземпляр структуры).
// Способ 1. Описание переменной по ранее созданному шаблону Worker w; // для переменной w выделяется память // заполнение полей переменной w.code = 334; strcpy(w.name, "Johnson B."); w.hours = 23; w.cost = 12.85f;
В вышеприведенном примере объявляется переменная с именем w на основе ранее описанного шаблона Worker . Затем для примера заполняются поля структурной переменной.
Способ 2. Объявление переменной во время задания шаблона. В этом способе объединяется объявление шаблона структуры и создание экземпляра структуры (переменной).
// Способ 2. Объявление переменной w1 во время объявления шаблона struct Worker < int code; char name[50]; int hours; float cost; > w1;
Доступ к полям переменной w1 из другого прогаммного кода
// заполнение значениями полей переменной w1 w1.code = 123; strcpy(w1.name, "Williams D."); w1.hours = 33; w1.cost = 10.58f;
Способ 3. Объявление переменной на основе типа, созданного с помощью квалификатора typedef .
Пусть в некоторой части программы объявлен новый тип WORKER , который основан на структуре Wrk , содержащей информацию о работнике:
// ключевое слово typedef // объявление нового типа WORKER typedef struct Wrk < int code; char name[50]; int hours; float cost; > WORKER;
Тогда, чтобы использовать переменную с именем w2 типа WORKER , нужно написать следующий код:
// объявление переменной на основе типа, // заданного с помощью ключевого слова typedef WORKER w2; w2.code = 100; strcpy(w2.name, "Typedef"); w2.hours = 33; w2.cost = 21.33f;
В этом способе задавать имя шаблона структуры Wrk необязательно. То есть, следующая запись также есть корректной
// после слова struct название шаблона отсутствует typedef struct < int code; char name[50]; int hours; float cost; > WORKER;
9. Где можно задавать шаблон структуры в среде CLR ?
В среде CLR рекомендуется объявлять шаблон структуры или новый тип на базе структуры (средство typedef ) в отдельном «*.h» файле, например «MyStruct.h» . Тогда удобно подключать эту структуру в другие модули программы, например:
#include "MyStruct.h"
10. Как осуществляется инициализация структурной переменной при ее объявлении? Пример инициализации native -структурной переменной
Пусть задан шаблон структуры Worker
// шаблон native-структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
Тогда инициализация структурной переменной может быть такой.
Способ 1. Объявление и инициализация переменной после того, как раньше был задан шаблон структуры Worker
Worker w = < 150, "Andrews", 45, 18.45f >; int d; d = w.code; // d = 150 float f; f = w.cost; // f = 18.45
Способ 2. Объединение задания шаблона, описания структурной переменной и ее инициализации.
// шаблон структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час > w1 = < 200, "Armstrong W.", 64, 22.34f >; . int d; float f; d = w1.code; // d = 200 f = w1.cost; // f = 22.34
Способ 3. Если задан тип с помощью квалификатора typedef , тогда инициализация структурной переменной будет следующей
// объявление нового типа WORKER typedef struct < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час > WORKER; . WORKER W = < 333, "Baxter N.", 34, 15.30f >; int d; float f; d = W.code; // d = 333 f = W.cost; // f = 15.30f
Связанные темы
- Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native -структур
- Структуры. Часть 3. Работа с managed -структурами в среде CLR . Квалификаторы ref и value . Объявление структурных переменных. Массивы managed -структурных переменных. Инициализация managed -структур
- Структуры. Часть 4 . Структуры и функции. Передача структуры в функцию в среде CLR . Возврат структуры из функции
- Функции.Часть 2. Функции и массивы. Передача одномерного и многомерного массива в функцию. Передача структуры и класса в функцию
- Указатели. Часть 3. Неуправляемые указатели и массивы. Указатель на структуру. Указатель на класс
- Указатели. Часть 6. Составные native и managed типы данных. Управляемые указатели ( ^ ) в среде CLR . Выделение памяти. Квалификаторы ref и value . Управляемые указатели ( ^ ) на структуры и классы
Как объявляется структурная переменная
Теперь, когда мы уже знаем основы языка и даже можем писать небольшие программы, можно перейти к детальному изучению предоставляемых Delphi возможностей для работы с самыми различными типами данных — массивами, записями, множествами и т.д. Здесь же мы рассмотрим вопросы преобразования типов данных.
Пользовательские типы данных
При разработке программ довольно часто оказывается недостаточно тех типов данных, которые представлены языком программирования. Например, бывает удобным совместить в одной переменной сразу ряд однотипных данных, или же предусмотреть хранение данных разных типов, например, строк и чисел. К счастью, в Object Pascal имеется возможность создавать собственные типы данных на основе уже имеющихся, совмещая их, или комбинируя. Например, для создания упорядоченного списка однотипных данных используют массивы (arrays), а для объединения нескольких типов в один — записи (records).
Другим аспектом применения собственных типов данных, упрощающих процесс программирования и делающий его более понятным человеку, является использование множеств — именованного набора из нескольких возможных значений.
Создание того или иного типа данных всегда начинается с декларации, или описания нового типа данных. Делается это в заголовочной части программы или модуля и начинается с ключевого слова type. После того, как новый тип данных определен, можно создавать переменные нового типа — точно так же, как и любого простого. Ну а особенности работы с тем или иным пользовательским типом данных определяются тем, к какому виду он принадлежит (массив, запись и т.д.), и собственно его реализацией (размер и размерность для — массивов, набор других типов — для записей и т.п.).
Массивы
Массив — это упорядоченная структура, состоящая из множества однотипных элементов, имеющих общее имя. Таким образом, при помощи всего лишь одной переменной можно хранить целый набор данных, при этом каждый элемент массива имеет свой собственный индекс, или индексы — в случае, если массив многомерный. Массив объявляется в Object Pascal при помощи ключевого слова Array, необязательных квадратных скобок с указанием числа элементов массива, и типа данных для элементов массива:
Array [индексы] of ;
Количество индексов определяет размерность массива. Так, для одномерного массива (в математике — вектор) требуется всего один индекс, а для двумерного массива (матрицы) понадобится 2 индекса и т.д. Объявления массивов могут выглядеть так:
type MyArray1 = array [1..100] of integer; type MyArray2 = array [1..10, 1..10] of integer;
В первом случае определен одномерный массив на 100 элементов типа целых чисел, во втором — двумерный массив размерностью 10 на 10, т.е. так же на 100 элементов типа целых чисел. После того, как массив определен, можно создавать переменные соответствующего типа:
var A1: MyArray1;
Другим вариантом создания массива является одновременное объявление как переменной, так и описания массива:
var A1: array [1..100] of Integer;
Если же необходимый размер массива заранее неизвестен, то можно использовать динамические массивы. Они могут определяться как с предварительным объявлением типа, так и без такового — достаточно создать переменную и в качестве ее типа указать массив:
var DynArray: array of integer;
Однако для того, чтобы приступить к использованию динамического массива, вначале требуется выделить для него место в памяти. Делается это при помощи процедуры SetLength, указав имя динамического массива и необходимый размер памяти:
Преимуществом динамического массива является то, что по ходу выполнения программы, количество выделяемой под массив память можно изменять.
Для обращения к конкретному элементу массива используется индекс (или индексы) элемента в массиве. Так, первый элемент в массиве типа MyArray1 (array [1..100]) имеет индекс, равный 1, а последний — 100. Соответственно, чтобы обратиться к первому элементу массива, скажем для того, чтобы присвоить ему значение, используются записи подобного типа:
Здесь мы присвоили элементу массива A1 с индексом 1 значение 10. Считывание данных производится аналогичным образом:
В данном случае переменной x будет присвоено значение 1-го элемента массива A1. При этом важно, чтобы было соблюдено 2 условия: во-первых, тот элемент массива, к которому идет обращение, должен существовать. Т.е. если обратиться к 11-му элементу массива, состоящего из 10 элементом, то произойдет ошибка доступа к памяти. Во-вторых, тип присваиваемых данных должен совпадать. Иначе говоря, если массив определен как целочисленный, то только целочисленные значения можно ему присваивать. При обратной же ситуации (считывания данных) правила несколько мягче, поскольку целое число можно присвоить переменой как целочисленного, так и вещественного типа.
В то же время, важной (и крайне полезной) особенностью массивов является то, что они могут хранить в себе данные любого типа, включая как любой простой, так и структурный тип, в том числе записи, объекты и другие массивы. Собственно говоря, двумерный массив можно охарактеризовать как одномерный массив, каждый элемент которого так же является одномерным массивом. С этой точки зрения становится понятным, почему для двумерных массивов допускается использовать 2 типа объявления и доступа к элементам, причем оба они полностью взаимозаменяемы и аналогичны по смыслу:
var A1: array [1..10, 1..10] of integer; var A2: array [1..10] of array [1..10] of integer; . A1[1][3]:=5; A2[1][3]:=5; A1[1,3]:=5; A2[1,3]:=5;
В данном примере оба объявленных массива (A1 и A2) полностью идентичны. Точно так же идентичны и обращения к элементам массивов — в обоих случаях можно использовать как синтаксис с отдельными значениями индексов, так и с индексами, перечисляемыми через запятую. Многомерными могут быть не только статические массивы, но и динамические, при этом используется 2-й вариант объявления. Например, двумерный динамический массив вещественных чисел объявляется следующим образом:
var DynArray: array of array of real;
При выделении памяти под такой массив так же следует учитывать его размерность. Например, если требуется массив размером 10 на 20 элементов, то следует использовать процедуру SetLength со следующими параметрами:
SetLength(DynArray, 10, 20);
В завершение знакомства с массивами нам осталось рассмотреть обещанный ранее пример использования циклов для заполнения массива. Допустим, у нас имеется простой массив-вектор для 10 целых чисел:
var MyArray: array [1..10] of integer;
Таким образом, если нам надо заполнить его значениями, следующими по порядку (скажем, числа от 10 до 100 с шагом 10), то вместо того, чтобы последовательно присваивать каждому элементу массива свое значение, можно использовать следующий цикл:
for i := 1 to 10 do MyArray[i] := i * 10;
Здесь переменная i, являющаяся счетчиком цикла, при каждой его итерации последовательно увеличивается на 1. В результате каждый элемент массива MyArray получает значение этой переменной, умноженной на 10, т.е. 10, 20, 30, 40 и т.д. — чего нам и требовалось. Чтобы убедиться в этом, а заодно продемонстрировать цикл для считывания данных из массива, обратимся к примеру, приведенному в листинге 5.1 (на CD этот пример находится в папке Demo\Part1\ArrayFor):
Листинг 5.1. Запись и считывание данных массивов в цикле
program arrayfor; var MyArray: array [1..10] of integer; i :integer; begin for i := 1 to 10 do MyArray[i] := i * 10; // заполнение массива for i := 1 to 10 do writeln(MyArray[i]); // вывод массива readln; // ожидание ввода для предотвращения закрытия окна end.
Относительно массивов можно сделать еще одно замечание: один уже известный нам тип данных — строки (string) можно рассматривать как массив символов (char). При этом никаких предварительных преобразований не требуется: если у нас уже есть строка, то всегда можно обратиться к отдельному ее символу как к элементу массива:
var s: string; c: char; . s := Москва; c := s[1];
В данном случае переменная c получит в качестве своего значения букву «М», т.е. первый символ строки.
Множества
Иногда бывает удобным ограничить возможные значения переменной только частью значений из множества всех значений, допускаемых ее типом. Допустим, нам нужна переменная типа Char, которая может принимать значения только из строчных латинских символов. В таком случае нам пригодится такое средство, как подмножество, в данном случае — подмножество символов от a до z. Определить его можно так:
type SmLetter = a..z;
Таким образом, мы получили новый тип данных — SmLetter, который является «урезанным» вариантом типа Char. При использовании такого типа данных, переменные типа SmLetter не смогут принимать значения, выходящие за пределы указанного диапазона:
var a: SmLetter; . a := ; // здесь все правильно, т.к. малая b входит в подмножество a..z a := B; // ошибка! Прописная B не входит в подмножество a..z
Практическими кандидатами в подмножества могут быть переменные, предназначенные для хранения отдельных фрагментов дат (скажем, от 1 до 12 для месяцев и от 1 до 31 — для дней месяца), для проверки значений, которые программы получает в результате ввода пользователя с клавиатуры, и т.д. Следует лишь учитывать, что подмножества, по понятным причинам, могут принадлежать только к ординарным типам данных — целым числам или символам.
Развитием подмножеств являются множества, или наборы (sets). Они, подобно подмножествам, могут быть выделены в отдельные типы данных, однако допустимые диапазоны их значений определяются несколько иначе. Прежде всего, для определения множества используется ключевое слово set:
Если провести аналогию с предыдущим примером, то диапазон из строчных латинских символов можно определить следующим образом:
type Letters = set of Сhar; var a: Letters; . a := [a..z];
Таким образом, определение множества состоит из двух этапов: вначале определяется тип, на основании которого строится подмножество (Letters), затем объявляется переменная этого типа (a), и уже к переменной применяется диапазон. Преимущество здесь состоит в том, что, во-первых, по ходу программы можно менять допустимые диапазоны значений, а во-вторых, сами диапазоны определяются гораздо более гибко. В частности, они могут содержать в себе как ряды отдельных значений, так и подмножества, или их сочетания в любой последовательности. Например, если нам надо выделить только некоторые символы, скажем, прописные от A до K, а так же цифры 1, 3, 4, 5 и 9, то определение группы получится следующим:
type Letters = set of Char; var a: Letters; . a := [1, 3..5, 9, A..K];
Для проверки, является ли то или иное значение членом множества, используется операция in. Например, чтобы проверить, относится ли введенный пользователем символ (обозначим его как переменную «c») к множеству a, достаточно такого выражения:
Чтобы продемонстрировать работу множеств и операции in, обратимся к примеру, приведенному в листинге 5.2 (Demo\Part1\Ranges).
Листинг 5.2. Операция in и подмножества
program rangeset; type Letters = set of Char; var a: Letters; c: Char; begin a := [1, 3..5, 9, A..K]; // определение группы readln(c); // считывание ввода пользователя if c in a then writeln(Input is Ok!) else writeln(Input is Wrong!); readln; // ожидание ввода для предотвращения закрытия окна end.
Еще одной разновидностью множества является перечисление. Использование перечислений призвано, прежде всего, улучшить читаемость (восприятие) кода программы. Допустим, в программе требуется неоднократно определять текущую раскладку клавиатуры, причем предусмотрено 3 состояния — русская, английская и другая. Разумеется, каждому состоянию можно назначить цифру, скажем, 1, 2 и 3 соответственно, однако по ходу написания программы всякий раз придется вспоминать, что означает та или иная цифра:
if KeyLang = 2 then . // по прошествии месяца вспомните, что тут значит 2!
На помощь здесь приходят перечисляемые типы. Они определяются следующим образом:
Например, в варианте для трех значений раскладки клавиатуры мы получим:
type TKeyLang = (klRussian, klEnglish, klOther);
Согласитесь, что klEnglish куда понятнее, чем просто цифра «2». Более того, на основании заданного таким образом перечисления можно создать тип-множество. Для этого после того, как исходный тип с диапазоном определен, определяют имя типа на его основе:
type TKeyLang = (klRussian, klEnglish, klOther); TKeyLangs = set of TKeyLang;
ВНИМАНИЕ
Обратите внимание на то, что имена типов начинаются с буквы «T». Хотя это и не является требованием языка, однако начинать названия сложных типов с этой буквы (от слова Type — тип) де-факто является стандартом.
Таким образом, в программе можно будет использовать уже не исходный тип, в котором определен состав множества, а новый тип, являющийся его производным:
var KeyLang: TKeyLangs; . if KeyLang = klEnglish then ;
ПРИМЕЧАНИЕ
Объявление типов-перечислений в 2 этапа является наиболее распространенной практикой. При этом исходный тип определяется именем в единственном числе (TKeyLang), а производный — во множественном, с «s» на конце (TKeyLangs).
Записи
Еще одной полезной разновидностью пользовательских видов данных являются записи (records). Запись, подобно массиву, может хранить в себе целый набор данных, но при этом они не должны принадлежать к одному типу. Иначе говоря, если массивы предназначены для хранения каких-либо рядов данных, то записи — для объединения разнородной информации под общим именем. Например, запись — просто незаменимый тип данных для хранения такой информации, как адреса или информация о персоне. И в том и в другом случае под общим именем должны быть собраны данные разного типа — строковые, численные и т.д. Например, для адреса это почтовый индекс, названия города и улицы, а так же номера дома и квартиры. Всю эту разнотипную информацию можно собрать под общей вывеской одной записи.
Объявление записи начинается с ключевого слова record, за которым следует перечисление всех входящих в нее элементов, называемых полями записи, и завершается ключевым словом end:
Применительно к почтовому адресу определение записи может выглядеть таким образом:
type TAddress = record PostIndex : integer; City : string; Street : string; HouseNr : integer; FlatNr : integer; end;
Обращение к отдельным полям записей производится при помощи точечной нотации, т.е. когда после имени переменной, являющейся записью, ставят точку, и сразу после точки указывают название того поля, к которому надо обратиться. Например, мы можем создать переменную типа TAddress и назвать ее, скажем, MyAddr, после чего заполнить те или иные ее поля, воспользовавшись для доступа к ним точкой:
var MyAddr: TAddress; . MyAddr.PostIndex := 119071; MyAddr.City := Москва; В том случае, если полем записи является другая запись, то точка используется дважды. Так, если у нас определена еще одна запись, для хранения информации о персоне, то одним из ее полей наверняка окажется адрес, а у нас уже есть подходящий тип данных для этого, так что можно использовать его в качестве поля: type TPerson = record Name : string; Phone : string; Address : TAddress; end;
Таким образом, все поля типа TAddress будут принадлежать также и к типу TPerson, но обращаться к ним надо не напрямую, а через поле записи TPerson соответствующего типа, т.е. через Address. Такие поля называются составными:
var Anybody: TPerson; . Anybody.Name := Вася Иванов; Anybody.Address.PostIndex := 119071; Anybody.Address.City := Москва;
В то же время, можно поступить и по другому: создать переменную типа TAddress, заполнить ее значениями, а затем присвоить соответствующему полю переменной типа TPerson. В примере, приведенном в листинге 5.3, продемонстрированы оба способа работы с составными полями, а так же продемонстрировано, что со всеми полями можно делать то же самое, что и с отдельными переменными того же типа.
Листинг 5.3. Записи
program recdemo; type TAddress = record PostIndex : integer; City : string; Street : string; HouseNr : integer; FlatNr : integer; end; TPerson = record Name : string; Phone : string; Address : TAddress; end; var Anybody: TPerson; Address: TAddress; begin write(Name: ); readln(Anybody.Name); write(Phone: ); readln(Anybody.Phone); write(Postal Index: ); readln(Address.PostIndex); write(City: ); readln(Address.City); write(Street: ); readln(Address.Street); write(House number: ); readln(Address.HouseNr); write(Flat number: ); readln(Address.FlatNr); Anybody.Address:=Address; writeln(Anybody.Name); writeln(Anybody.Phone); writeln(Anybody.Address.PostIndex); writeln(Anybody.Address.City); writeln(Anybody.Address.Street); writeln(Anybody.Address.HouseNr); writeln(Anybody.Address.FlatNr); readln; end.
Приведенная в листинге программа последовательно предлагает пользователю ввести свойства — сначала для записи о персоне, а затем — для адреса, после чего полю адреса персоны присваивается значение записи-адреса. После этого все поля последовательно выводятся на экран. Исходный код программы можно найти в папке Demo\Part1\Records (файл recdemo.dpr).
В завершение темы записей рассмотрим еще одну их особенность, характерную для Object Pascal, а именно — возможность сочетать в одном типе записи с разными полями. Называются такие записи вариантными и объявляются так же как и обычные, за исключением того, что содержат дополнительную часть, начинающуюся с ключевого слова case:
record [ : ; . : ;] case [ :] of : ( ); . : ( ); end;
В качестве примера можно привести такой случай, когда необходимо создать тип записи «служащий», в котором требуется имя и размер оплаты. Дело в том, что эти самые служащие могут быть как принятыми на постоянную работу, и имеет помесячный оклад, так и временные, для которых применяется почасовая оплата. Важно отметить, что одновременно может быть только один вид оклада. Соответственно, мы можем использовать вариантный тип записи, в качестве признака в которой будет выступать булево поле «Salaried» («на окладе»):
type TEmployee = record Name: string; JobTitle: string; case Salaried: Boolean of true: (Salary: Currency); false: (Hourly: Currency); end;
Здесь, в зависимости от того, будет ли значением поля Salaried той или иной переменной типа TEmployee ложь или истина, у нее будет либо поле Salary, либо Hourly. Пример использования подобной вариантной записи вы можете посмотреть в файле varrec.dpr.
Специальные типы данных
Помимо уже рассмотренных типов данных, простых и пользовательских, в Object Pascal имеется ряд иных, специализированных типов. Например, для времени используют тип TDateTime. В принципе, этот тип алогичен вещественному типу Double, однако для работы с такими данными, как временные диапазоны, удобнее использовать специальный тип TDateTime.
Поскольку этот тип является, фактически, вещественным числом, то данные хранятся в нем следующим образом: целая часть числа определяет дату, за которую берется количество дней, прошедших с 31 декабря 1899 года, а дробная определяет время в миллисекундах, прошедших с начала текущего дня. Преимуществом же типа TDateTime является то, что для него предусмотрен целый набор готовых функций, позволяющих работать с датами и временем. Их список приведен в таблице 5.1.
| Функция | Описание |
|---|---|
| Now | Возвращает текущие дату и время |
| Date | Возвращает текущую дату (целую часть TDateTime) |
| Time | Возвращает текущее время (дробную часть TDateTime) |
| DateTimeToStr | Преобразует дату и время в строку на основе системных настроек |
| DateTimeToString | Копирует дату и время в указанную строковую переменную |
| DateToStr | Преобразует дату в строку |
| TimeToStr | Преобразует время в строку |
| FormatDateTime | Преобразует дату и время в указанный формат |
| StrToDateTime | Преобразует строку, содержащую написанную надлежащим способом дату и время, в переменную типа TDateTime |
| StrToDate | Преобразует строку в дату в формате TDateTime |
| StrToTime | Преобразует строку во время в формате TDateTime |
| DayOfWeek | Возвращает номер дня недели (от 1 до 7) для указанной даты. Учитывайте, что 1-й день недели – воскресенье |
| DecodeDate | Раскладывает значение типа TDateTime на 3 целых, представляющих собой год, месяц и день месяца |
| DecodeTime | Раскладывает значение типа TDateTime на 4 целых, представляющих собой часы, минуты, секунды и миллисекунды |
| EncodeDate | Объединяет 3 целых, представляющих собой год, месяц и день, в одно значение типа TDateTime |
| EncodeTime | Объединяет 4 целых, представляющих собой часы, минуты, секунды и миллисекунды? в одно значение типа TDateTime |
Типичный пример использования функций для работы с датами, может выглядеть примерно таким образом:
var today, yesterday: TDateTime; s: string; . today := Now(); yesterday := today — 1; s := TateToStr(yesterday);
Здесь переменной s будет назначено значение, соответствующее вчерашнему дню в формате, принятому в системе (например, «16.07.2005»). Более полный пример работы с датами вы можете посмотреть в Demo\Part1\Dates.
Кроме дат, рассмотрим еще один тип данных — файлы (files). Файлы представляет собой некую последовательность однотипных элементов, размещенных на внешнем носителе, не находящемся в оперативной памяти ПК. В типичном случае таким носителем является жесткий диск. Этот тип данных можно охарактеризовать как одномерный массив без указания размера. Чтобы производить те или иные операции над такими данными, используют специальную переменную файлового типа. Причем в зависимости от того, с какими данными предстоит работать, задают тот или иной тип файла. Например, для работы с текстовыми файлами используют специальный тип TextFile, а если файл содержит в себе ряд чисел, то определяют, какой тип чисел в нем используется:
var f1: TextFile; // текстовый файл f2: File of integer; // файл с целыми числами f3: File of double; // файл с вещественными числами
Если же файл нетипизированный, (например, бинарный), то используют тип File без каких-либо дополнений:
var f4: File; // двоичный файл или файл заранее неизвестного типа
Работа с файловыми переменными имеет ряд особенностей. Прежде всего, просто объявить переменную файлового типа мало — необходимо так же связать ее с каким-либо конкретным файлом на диске. После этого файл следует открыть, при этом указывают режим файла — его можно открывать для чтения или для записи, или для чтения и записи одновременно.
ПРИМЕЧАНИЕ
Саму файловую переменную называют дескриптором файла, т.е. фактически она лишь указывает программе на место в памяти, через которое обеспечивается доступ к файлу средствами операционной системы.
Для работы с файлами так же предусмотрен целый ряд процедур и функций. Среди них можно отметить уже знакомые нам read/readln и write/writeln. Чтобы эти процедуры работали с файлами, в качестве первого параметра указывают имя файловой переменной (дескриптор файла):
writeln(f, Текст для записи в файл);
Но прежде, чем производить запись в файл, или начать считывать из него данные, как уже говорилось, надо связать переменную с файлом (назначить дескриптор) и открыть его, попутно назначив режим доступа. Назначение дескриптора файлу производится с помощью процедуры AssignFile, например
Что касается открытия файла, то тут дела обстоят несколько сложнее, поскольку следует учитывать тип файла и режим доступа. Так, применительно к текстовым файлам, используют процедуры Reset, Rewrite и Append, открывающие файл на чтение, перезапись и добавление (запись в конец файла), соответственно.
Наконец, следует отметить, что после того, как операции с файлом произведены, его необходимо закрыть. Для закрытия файла используется процедура CloseFile. Таким образом, вариант использование всех этих процедур для чтения и записи файла в общем случае, выглядит таким образом, как показано в листинге 5.4:
Листинг 5.4. Запись и чтение в файлах
program readwrite; uses SysUtils; var f: TextFile; s: string; begin AssignFile(f, c:\test.txt); // назначаем дескриптор файлу text.txt Rewrite(f); // открываем файл на запись writeln(f, s); // производим запись в файл CloseFile(f); // закрываем файл Reset(f); // открываем файл на чтение readln(f, s); // считываем данные из файла CloseFile(f); // закрываем файл end;
Еще один пример работы с файлами можно посмотреть в Demo\Part1\Files. Вместе с тем, на практике файловые типы данных не часто используются при современном программировании в среде Delphi, поскольку VCL предлагает ряд более удобных и изящных методов для хранения данных на диске, начиная от методов отдельных классов и заканчивая потоками и базами данных.
Совместимость и преобразование типов
При рассмотрении простых типов мы уже поднимали вопрос их совместимости и преобразования друг в друга. Теперь настала пора рассмотреть этот аспект более внимательно. В частности, если целое число без проблем приводится к вещественному, то как быть в том случае, если требуется обратное преобразование? Выход в данной ситуации состоит в использовании специальных функций преобразования типов. Так, для преобразования вещественного числа в целое используются функции Round и Trunc. Их отличие состоит в том, что первая округляет значение до целого, опираясь на стандартные математические правила, а вторая — просто отбрасывает дробную часть числа. Отметим, что если надо просто отбросить дробную часть числа, оставив тип данных без изменений, то следует использовать другую функцию — Int. Примеры их использования показаны ниже:
var i: integer; r: real; . r := 5.75; i := Round(r); // i получит значение 6 i := Trunc(r); // i получит значение 5 r := Int(r); // r получит значение 5.0
Куда большее количество функций предусмотрено для преобразования числовых типов в строковые и наоборот. С некоторыми из них, предназначенных для дат, мы уже знакомы (см. таблицу 5.1). Другие же представлены в таблице 5.2.
| Функция | Описание |
|---|---|
| IntToStr | Преобразует целое число в строку |
| StrToInt | Преобразует строку в целое число, в случае невозможности преобразования вызывает ошибку |
| StrToIntDef | Преобразует строку в целое число, в случае невозможности преобразования возвращает число, указанное в качестве второго аргумента |
| FloatToStr | Преобразует вещественное число в строку |
| FloatToStrF | Преобразует вещественное число в строку на основе указанного формата |
| StrToFloat | Преобразует строку в вещественное число, в случае невозможности преобразования вызывает ошибку |
| StrToFloatDef | Преобразует строку в вещественное число, в случае невозможности преобразования возвращает число, указанное в качестве второго аргумента |
| CurrToStr | Преобразует число типа Currency в строку |
| CurrToStrF | Преобразует число типа Currency в строку на основе указанного формата |
| StrToCurr | Преобразует строку в число типа Currency, в случае невозможности преобразования вызывает ошибку |
| StrToCurrDef | Преобразует строку в число типа Currency, в случае невозможности преобразования возвращает число, указанное в качестве второго аргумента |
В качестве формата в функциях типа FloatToStrF подразумевают один из предопределенных вариантов форматирования, а так же количество знаков после запятой и общее количество. Например, для того, чтобы оставить не более 2 знаков после запятой, можно использовать следующее выражение:
str := FloatToStrF(x, ffGeneral, 10, 2);
Здесь ffGeneral является указанием на формат вывода, 10 определяет максимально возможное число знаков в числе вообще, а 2 — предельно допустимое число знаков после запятой. Помимо ffGeneral, определяющего наиболее обобщенный формат представления чисел, имеются и другие:
- ffExponent — формат с экспонентой (например, 1.45E10);
- ffFixed — фиксированный формат (например, 145000.01);
- ffNumber — «прописной» формат (например, 1,450,000.0);
- ffCurrency — валютный формат (например, 145 000,00р).
Таким образом, привести то или иное число к строке нужного формата, оказывается достаточно просто — важно лишь определиться, что нужно получить. А еще одна функция — Chr — позволяет преобразовывать маленькие числа (до 255) в символы, т.е. фактически, из типа Byte делает Char.
Что касается обратных преобразований (строк в числа), то тут следует соблюдать определенную осторожность, поскольку далеко не всякая строка может стать числом. В первую очередь это касается преобразований вещественных числе, поскольку нередко вместо отделяющей мантиссу точки может оказаться запятая. В случаях, когда преобразование строки в число невозможно, возникает ошибка выполнения программы. Ее можно обрабатывать самостоятельно (об обработке ошибок будет рассказано во второй части книги), или же поручить это дело функции — в таком случае следует использовать функции с суффиксом Def (StrToIntDef, StrToFloatDef и StrToCurrDef). В качестве второго аргумента они принимают значение, которое следует использовать в том случае, если преобразование невозможно:
x := StrToIntDef(str, -1);
В данном случае, если в строке str не удастся распознать число, переменной x будет присвоено значение -1.
При всем многообразии типов данных, в Object Pascal существует тип еще один тип, который не имеет типа — вариантный. Называется он Variant. Переменные вариантного типа могут принимать значения любого простого типа, а так же некоторых специальных. В типичном случае использование вариантного типа может выглядеть так:
var v: variant; . v := 5; v := Строковое значение; v := 10.54;
Этот пример иллюстрирует, как одной т той же переменной последовательно присваиваются данные 3 разных типов — целочисленного, строкового и вещественного. При этом никакой ошибки не возникает. Однако вариантные данные обрабатываются гораздо медленнее, чем типизированные — практически так же медленно, как программы на языке BASIC. (кстати, в классическом BASIC как раз только вариантные данные и были). Кроме того, использование нетипизированных данных вообще, а в строго типизированном языке — особенно, чревато непредсказуемым поведением программы и прочими ошибками. Поэтому оставим этот тип для внутреннего использования Delphi — в VCL он применяется для работы с OLE и базами данных.
Указатели
Указатели (pointers) — это такой тип переменных, которые хранят адрес в памяти компьютера, по которому расположена другая переменная. Фактически, указатель не содержит значение, а ссылается на него.
Указатели можно задать двумя принципиально разными способами. Во-первых, можно использовать специальный тип — Pointer. При этом будет создан нетипизированный указатель, под который всякий раз надо будет принудительно выделять память, используя функцию GetMem. Другой, как правило более предпочтительный способ, состоит в том, что сразу же создается указатель нужного типа. Делается это при помощи символа «^», предшествующего названию типа:
Здесь мы определили указатель P, являющийся указателем на переменную целочисленного типа.
После того, как указатель создан, можно связать его с переменной подходящего типа, используя операцию @:
var P: ^integer; x: integer; . P := @x; Теперь к переменной x можно обращаться как непосредственно, так и через ее указатель. В случае обращения через указатель так же используют символ «^»: x := 10; P^ := 10;
В обоих случаях переменная x получит значение 10.
Другим вариантом использования указателя, помимо связывания с существующей переменной, является выделение для него памяти и дальнейшая работа как с ссылкой на некую абстрактную переменную (фактически, непосредственно на область в памяти, выделенную для хранения данных). В таком случае, код будет выглядеть так:
var P: ^integer; . New(P); // выделение памяти, необходимой для хранения данных типа Integer P^ := 10; // занесение данных в выделенный блок памяти Dispose(P); // освобождение памяти
При работе с указателями таким методом следует самостоятельно заботиться о выделении и очистке памяти под данные.
В целом же указатели, как правило, используются для взаимодействия с системными функциями операционной системы (в частности, с Windows API), для взаимодействия со сторонними программами и динамически подключаемыми библиотеками.
Объекты
Самые сложные и интересные типы данных — это объекты. В современных версиях Delphi объекты бывают 3 основных типов: собственно объекты, а так же классы и интерфейсы. Тип объекта (object) достался Delphi от предшественника — языка Pascal with Objects, и в настоящее время практически не используется. Основным типом объектных данных в современных программах является класс (class). Что касается интерфейсов (interface), то они являются разновидностью классов, и предназначены для взаимодействия с системными объектными функциями Windows.
Тема объектов достаточно обширна, поскольку является основой для парадигмы объектно-ориентированного программирования. ООП в Object Pascal рассматривается во второй части настоящего издания.
Избранное
Техподдержка / Связаться с нами
Copyright © 1999-2020 SNK. Все права защищены.
При использовании материалов с сайта ссылка на источник обязательна.
Структуры (struct)
Реальные данные об объектах часто описываются величинами разных типов. Например, автомобиль в автосалоне имеет следующие характеристики: модель (строка), год выпуска (типа int), объем двигателя (типа double), наличие подушек безопасности (типа bool) и т. д. В этом случае возникает необходимость хранить и обрабатывать совокупности данных различных типов, поэтому приходится использовать отдельные массивы для каждого типа данных, а для установления соответствия между ними вводятся соответствующие индексы. Такой подход не очень удобен и существенно усложняет написание программы. В C++ существует другой способ решения таких задач — использование комбинированного типа данных, который называется структурой (или структурным типом данных).
Объявление комбинированного типа данных. Комбинированный тип данных (структура) — это структурированный тип данных, состоящий из фиксированного числа компонентов различного типа. То есть структуры объединяют в одной переменной элементы разных типов. Переменную типа «структура» можно объявить двумя способами.
где — имя пользовательского типа для структур определенного вида;
struct — ключевое слово, с которого начинается описание типа «структура»;
имена полей структуры (задаются по правилам задания идентификаторов). Имена полей структуры должны быть уникальными в пределах данной структуры, т. е. в разных структурах поля могут иметь одинаковые имена. Однако во избежание ошибок лучше, чтобы имена полей были уникальными в пределах всей программы;
. . . — любой стандартный или определенный пользователем тип языка C++, включая тип «структура». Если используется тип, определенный пользователем, то он должен быть объявлен до описания структуры.
>симя переменной>;, где — идентификатор переменной типа «структура»;
имена полей записи (см. выше); . . . — любой стандартный или определенный пользователем тип языка C++, включая тип «структура».
Имя типа структуры определяет новый тип данных, и его можно использовать наряду со стандартными типами.
//объявлениеп типа структуры из 4 полей
//модель автомобиля //год выпуска //объем двигателя //мощность двигателя //окончание описания типа структуры //объявление переменных типа Avto
char Model[20]; int Year; double DV; int Power;
//мы ввели тип данных anketa, который объединяет три элемента: char name [50]; //строковая переменная — фамилия человека,
int age; //целая переменная — его возраст,
float pay; //вещественная переменная — его оклад
//мы ввели тип данных dinner, который объединяет два элемента: char cafe_name[70];
//строковая переменная — название кафе, где можно пообедать, float cost; //вещественная переменная — стоимость обеда
Теперь можно ввести структурные переменные, которые описываются с помощью введенных структурных типов данных:
Примеры определения структурных переменных:
anketa al, а2, аЗ;
//объявление трех переменных структурного типа anketa dinner dl, d2, d3;
//объявление трех переменных структурного типа dinner
Пример 3. Определение структурных переменных одновременно с определением типа.
struct anketa //определяем структурный тип анкета
char name[50]; int age; float pay;
> al, a 2 , аЗ ; //объявляем 3 переменных нового структурного типа
struct //без определения нового структурного типа
char name[50]; int age; float pay;
> al, a2 , аЗ ; //сразу определяем переменные структурного типа
Если задано имя структурного типа без последующего списка переменных, то такое объявление вводит новый тип данных — шаблон структуры, и память для него не выделяется. Память выделяется только при объявлении структурных переменных.
Работа с переменными структурного типа. Обращение к значению поля осуществляется с помощью составного имени, которое состоит из имени переменной типа «структура» и идентификатора поля, разделенных точкой. Составное имя можно использовать везде, где допустимо применение значения типа поля.
Полям записи можно присваивать значения с помощью оператора присваивания. Например,
а) присваивание значений полям записи типа Avto (см. пример выше):
Присваивание значений полям строкового типа осуществляется с помощью стандартных функций библиотеки string
б) присваивание полям одной структуры значений полей другой структуры того же самого типа:
//информация из структуры V копируется в структуру М
При выполнении этого оператора компилятор создает побитовую копию одной структуры в другую. По умолчанию применение стандартных операций («+», «-», «*», «/» и т. д.) к переменным типа структура не применимо. Приведем пример, демонстрирующий отсутствие возможности сложения двух структур.
void prn(chisla &ch)
printf(«a = %d x = %f «, ch.a, ch.x);
chisla chi = , ch2; prn(chi); prn(ch2); ch2 = chi;
11выполняется побитовая копия структуры chi в структуру ch2 prn(ch2); ch2 = ch2 + chi;
//на эту строчку компилятором будет сгенерирована ошибка
Пояснение. В программе введен структурный тип данных для хранения целого и вещественного чисел. Операция «=» осуществляет побитовую копию полей структуры. А на оператор сложения двух структур (ch2 = ch2 + chi;) компилятор сгенерирует ошибку: «error С2676: binary ‘ + ‘ : ‘chisla’ does not define this
operator or a conversion to a type acceptable to the predefined operator», означающую невозможность применения бинарной операции «+» к структурному типу chisla.
Чтобы реализовать выполнение стандартных операций для переменных структурного типа, необходимо перегрузить эти операции. Подробно этот материал разбирается в главе 16, параграф 16.7.
Ввод информации в структуру с клавиатуры и вывод данных из структуры осуществляется по полям:
//считываем данные
//выводим данные на экран
printf(«%s %6d V.Model %4.Ilf..%d «, V.Model,V.Year, V.DV, V.Power);
Сравнение записей можно также осуществить по полям:
if ((V.Model==M.Model) && (V.Year==M.Year)
Инициализация структур. Переменная структурного типа инициализируется так же, как и другие переменные. После имени переменной ставится знак равенства, и в фигурных скобках указываются все значения элементов структуры через запятую в порядке их описания. Можно одновременно описать структурный тип данных, объявить переменную этого типа и инициализировать ее.
Примеры инициализации переменных структурного типа.
struct anketa //вводам новый структурный тип данных
char name[50]; int age; float pay;
//определяем переменную а и задаем ей начальные значения
struct dinner //вводим новый структурный тип данных
char cafe_name[70]; float cos;t
> d= ; //объявляем и инициализируем переменную
Дранеє введенный структурный тип данных anketa используем для объявления и инициализации переменных этого типа*/
/*ранее введенный структурный тип данных dinner используем для
объявления и инициализации переменных этого типа*/
Доступ к элементам. Доступ к элементам структуры выполняется с помощью операции точка(.) при обращении к полю через имя структуры и операции -> при обращении через указатель:
Пример получения доступа к элементам структуры:
char name[50]; int age; double pay;
Теперь a . name или pa->name можно использовать, как и любой другой массив типа char, а. аде или ра->аде как переменную типа int, a a .pay или ра->рау как переменную типа double, например, можно присвоить им начальные значения:
а.name[0]= ‘П’; а.name[1]=’е’; а.name[ 2 ] = 1 т 1 ; а.name[3]=’р’; а.name[4]= 1 ‘;

pa->name[0] а.аде = 25;
Пример. Инициализировать структуру и вывести на экран ее элементы.
ttinclude int main()
char name[50]; int age; float pay;
puts(«Печать элементов структуры типа anketa»);
printf(«Возраст %d «,a.age); printf(«Оклад %f «,a.pay); return 0;
Пример. Определить структурный тип данных «турист», содержащий информацию о фамилии туриста, стоимости тура и места отдыха. Написать функции ввода информации о туристе с клавиатуры и вывода введенной информации на экран.
#include struct turist
void vvod(turist&); void vyvod(turist&);
ра->аде = 25; a.pay = 1525.0;
//структурный тип турист
//поле для хранения ФИО //поле для хранения стоимости тура //поле для хранения названия страны
//прототип функции ввода информации //прототип функции вывода информации
turist t; //объявляем переменную структурного типа
//вызываем функции
vvod (t) ; //ввода информации
vyvod (t) ; //и вывода информации
void vvod (turist &t) //реализация функции ввода информации
printf(«ФИО туриста: «); scant(«%s», t.fio);
//для доступа к полям структуры используем «.» printf(«Стоимость тура: «); scant(«%d», &t.cost); printf(«Страна: «); scant(«%s», t.country);
void vyvod (turist &t) //реализация функции вывода информации
printf(«ТуристХп»); printf(«%s «, t.fio);
printf(«купил тур стоимостью %d», t.cost); printf(«в страну %s «, t.country);
Пояснение. В программе вводится структурный тип данных turist. Для ввода данных с клавиатуры используется функция vvod, а для вывода информации на экран применяется функция vyvod. Передача переменной структурного типа осуществляется по ссылке. В теле функций доступ к полям структуры осуществляется с использованием операции «.».