Как объявляется структурная переменная
Перейти к содержимому

Как объявляется структурная переменная

  • автор:

Синтаксис: структуры в 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++. Структуры. Часть 4. Структуры и функции. Передача структуры в функцию в среде CLR. Возврат структуры из функции

Структуры. Часть 4. Структуры и функции. Передача структуры в функцию в среде CLR . Возврат структуры из функции

Поиск на других ресурсах:

1. Какие существуют способы передачи структуры в функцию?

Существует 2 способа передачи native -структуры в функцию в качестве параметра:

  • передача структуры по значению. При такой передаче делается копия структурной переменной в памяти. Если структура имеет большой размер, то такой способ неэффективен. Преимуществом этого способа есть то, что все манипуляции с копией структуры в функции не влияют на исходную переменную;
  • передача указателя на структуру. В этом случае передается только указатель на структуру а не вся структура. Если структура занимает большой объем памяти, то такой способ обеспечивает быструю передачу значений структурной переменной в функцию. Это связано с тем, что передается только указатель на структуру. Недостатком этого способа есть то, что в функции случайно можно изменить значения исходной структурной переменной, в тех случаях когда это нежелательно.
2. Какие есть способы возврата структуры из функции?

Так же, как и при передаче структуры в функцию (см. п.1), существуют 2 способа возврата:

  • возврат структуры по значению;
  • возврат указателя на структуру.

Преимущества и недостатки каждого способа такие же, как описано в п. 1.

3. Пример передачи native -структуры в функцию по значению

Пусть в модуле «MyStruct.h» даны объявления native -структуры:

// native-структура, которая описывает точку на координатной плоскости struct MyPoint < int x; int y; >;

Пусть в некотором классе объявляется функция EqualPoints() , которая сравнивает две точки на координатной плоскости. Функция возвращает true , если точки эквивалентны (равны между собой). В другом случае функция возвращает false .

// функция, которая сравнивает на равенство две точки public: bool EqualPoints(MyPoint p1, MyPoint p2) < bool f = false; if ((p1.x == p2.x) && (p1.y == p2.y)) f = true; return f; >

Тогда использование функции EqualPoints() может быть следующим:

// подключение модуля "MyStruct.h" #include "MyStruct.h" . // передача native-структуры в функцию по значению bool f_equal; MyPoint pt1, pt2; // p1, p2 – переменные типа "структура" // заполнение значениями pt1.x = 23; pt1.y = 35; pt2.x = 23; pt2.y = 35; f_equal = this->EqualPoints(pt1, pt2); // f_equal = true pt1.x = 100; f_equal = EqualPoints(pt1, pt2);
4. Пример передачи native -структуры в функцию по указателю

Пусть задана native -структура:

// native-структура struct MyPoint < int x; int y; >;

Ниже реализована функция, которая сравнивает на равенство значения структурных переменных. Функция получает указатель на структуру.

// передача указателя на структуру MyPoint bool EqualPointsP(MyPoint * p1, MyPoint * p2) < bool f = false; if ((p1->x == p2->x) && (p1->y == p2->y)) f = true; return f; >

Программный код, демонстрирующий использование функции EqualPoints() .

// Передача структуры по указателю MyPoint p1; MyPoint p2; bool f_equal; p1.x = 28; p1.y = 35; p2.x = 28; p2.y = 35; f_equal = EqualPointsP(&p1, &p2); // f_equal = true p2.y = 100; f_equal = EqualPointsP(&p1, &p2); // f_equal = false
5. Как передать в функцию managed -структуру, которая объявлена с квалификатором ref ? Пример

Пусть задана следующая ref -структура.

// ref-структура ref struct MyPointRef < int x; int y; >;

Структуры с квалификатором ref есть структурами ссылочного типа. Для таких структур память должна выделяться с помощью утилиты gcnew . Поэтому, в функцию можно передать только ссылку на такие структуры.

Пусть дана функция LengthRef() , которая определяет длину линии, которая соединяет 2 точки. Функция получает две ref -структуры в качестве параметров.

// Функция, определяющая длину между двумя точками float LengthRef(MyPointRef ^p1, MyPointRef ^p2) < float l; l = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return l; >

Использование функции LengthRef() в некотором программном коде.

// передача ref-структуры в функцию MyPointRef ^ pt1; MyPointRef ^ pt2; float len; // выделение памяти для ref-структур pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение ref-структур значениями pt1->x = 35; pt1->y = 35; pt2->x = 40; pt2->y = 40; len = LengthRef(pt1, pt2); // len = 7.071068
6. Как передать в функцию managed -структуру, которая объявлена с квалификатором value ? Пример

Managed -структуру, объявленную с квалификатором value можно передать в функцию одним из двух способов:

  • по значению;
  • по указателю.

Ниже приведены оба способа для value -структуры MyPointValue , которая имеет следующее объявление.

// value-структура value struct MyPointValue < int x; int y; >;

Способ 1.

Пусть задана функция LengthValue() , определяющая расстояние между двумя точками. Функция получает входным параметром две структуры типа MyPointValue . Структуры передаются как параметр-значение.

// определение расстояния между двумя точками float LengthValue(MyPointValue p1, MyPointValue p2) < float len; len = (float)Math::Sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); return len; >

Пример использования функции LengthValue() в другом программном коде.

// передача value-структуры по значению MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 35; pt1.y = 50; pt2.x = 40; pt2.y = 55; len = LengthValue(pt1, pt2); // len = 7.071068

Способ 2. Передача структуры по указателю.

Пусть задана функция LengthValue() , получающая два указателя на структуры типа MyPointValue .

// функция получает указатель на value-структуру float LengthValueP(MyPointValue *p1, MyPointValue *p2) < float len; len = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return len; >

Использование функции LengthValue() в программе.

// передача value-структуры по указателю MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 0; pt1.y = 0; pt2.x = 10; pt2.y = 10; len = LengthValueP(&pt1, &pt2); // len = 14.14214
7. Как реализовать возврат экземпляра native -структуры из функции? Пример

Возвратить native -структуру можно:

  • по значению;
  • по адресу.

Пусть задана структура MyPoint

// native-структура struct MyPoint < int x; int y; >;

Пусть в программе реализована функция GetCenterLine() , которая вычисляет координаты середины отрезка, соединяющего 2 точки. Функция получает 2 параметра – координаты концов отрезка.

// функция, возвращающая native-структуру // функция вычисляет координаты середины отрезка MyPoint GetCenterLine(MyPoint p1, MyPoint p2) < MyPoint res; res.x = (p1.x + p2.x)/2; res.y = (p1.y + p2.y)/2; return res; >

Демонстрация возврата native -структуры по значению.

MyPoint pt1; MyPoint pt2; MyPoint res; // результат, память уже выделена pt1.x = 30; pt1.y = 20; pt2.x = 36; pt2.y = 40; res = GetCenterLine(pt1, pt2); // res - координаты середины отрезка
8. Пример возврата из функции указателя на native -структуру

Пусть задана структура MyPoint

// native-структура struct MyPoint < int x; int y; >;

Пусть реализована функция GetCenterLine() , которая получает 2 точки и возвращает указатель на структуру. В теле функции реализовано выделение памяти для структуры оператором new .

MyPoint * GetCenterLine(MyPoint p1, MyPoint p2) < MyPoint * res; // указатель на структуру MyPoint // выделение памяти для структуры res = new MyPoint; // вычисление середины отрезка - заполнение значениями resP->x = (p1.x + p2.x)/2; resP->y = (p1.y + p2.y)/2; return res; >

Демонстрация работы с функцией GetCenterLine() .

// возвращение native-структуры по указателю MyPoint * resPt; // указатель на структуру – память для структуры еще не выделена MyPoint pt1, pt2; // экземпляры структуры pt1.x = 28; pt1.y = 40; pt2.x = 38; pt2.y = 50; // вызов функции GetCenterLine() // для указателя resPt память выделяется внутри функции resPt = GetCenterLine(pt1, pt2); // проверка int d; d = resPt->x; // d = 33 d = resPt->y; // d = 45
9. Как возвратить экземпляр value -структуры из функции?

Если в среде CLR описана структура с квалификатором value , то возврат экземпляра такой структуры из функции ничем не отличается от возвращения native -структуры (см. п. 7.).

10. Пример возврата указателя ( ^ ) на value -структуру

Если структура объявлена с квалификатором value , то функция может возвращать указатель на эту структуру. Допускается использование двух видов указателей:

  • классического указателя, который обозначается символом ‘*’ . Возврат такого указателя из функции не отличается от возврата указателя на native -структуру (см. п. 8);
  • указателя, предназначенного для работы с объектами среды CLR . Такой указатель обозначается символом ‘^‘ . Память для такого указателя выделяется утилитой gcnew . Ниже приведен пример возврата из функции такого указателя на value -структуру.

Пусть объявлена структура с квалификатором value

// value-структура value struct MyPointValue < int x; int y; >;

Пусть нужно реализовать функцию GetCenterLineVP() , которая получает 2 точки и возвращает указатель на результирующую value -структуру. Результирующая структура содержит координаты центра отрезка, который соединяет точки. Функция имеет следующий вид:

// функция возвращает указатель на value-структуру MyPointValue ^ GetCenterLineVP(MyPointValue p1, MyPointValue p2) < MyPointValue ^ pv; // указатель на структуру MyPointValue pv = gcnew MyPointValue; pv->x = (p1.x + p2.x)/2; pv->y = (p1.y + p2.y)/2; return pv; >

Демонстрация вызова функции из другого программного кода:

// создание экземпляров структур с инициализацией MyPointValue pt1 = < 20, 30 >; MyPointValue pt2 = < 40, 60 >; // указатель на структуру MyPointValue MyPointValue ^ resPt; // вызов функции GetCenterLineVP() // внутри функции выделяется память для структуры, // на которую указывает resPt resPt = GetCenterLineVP(pt1, pt2); // проверка int d; d = resPt->x; // d = 30 d = resPt->y; // d = 45
11. Пример возврата из функции структуры, которая объявлена с квалификатором ref

Для структуры, которая объявлена с квалификатором ref есть определенные особенности использования. Такая структура есть структурой ссылочного типа. Поэтому функция должна возвращать ссылку на такую структуру (указатель на структуру). Возвратить экземпляр ref -структуры (по значению) из функции не удастся (см. п. 5).

Пусть объявлена структура

// ref-структура ref struct MyPointRef < int x; int y; >;

Тогда функция, которая получает 2 точки в качестве параметров и находит центр между двумя точками будет иметь приблизительно следующий вид:

// функция, возвращающая ref-структуру MyPointRef ^ GetCenterLineRef(MyPointRef ^p1, MyPointRef ^p2) < MyPointRef ^resPt; // выделение памяти для указателя resPt resPt = gcnew MyPointRef; // заполнение значениями полей указателя resPt->x = (p1->x + p2->x)/2; resPt->y = (p1->y + p2->y)/2; return resPt; >

Демонстрация использования функции в другом программном коде.

// указатели на ref-структуру MyPointRef ^pt1; MyPointRef ^pt2; MyPointRef ^resPt; // выделение памяти для указателей pt1, pt2 pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заполнение значениями pt1->x = 20; pt1->y = 20; pt2->x = 30; pt2->y = 40; // вызов функции GetCenterLineRef() // память для указателя resPt выделяется внутри функции resPt = GetCenterLineRef(pt1, pt2); // проверка int d; d = resPt->x; // d = 25 d = resPt->y; // d = 30

Связанные темы

  • Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
  • Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native-структур
  • Структуры. Часть 3. Работа с managed-структурами в среде CLR. Квалификаторы ref и value. Объявление структурных переменных. Массивы managed-структурных переменных. Инициализация managed-структур
  • Функции. Часть 1. Описание функции. Фактические и формальные параметры. Передача параметров в функцию по значению и по адресу. Прототип функции
  • Функции. Часть 2. Функции и массивы. Передача одномерного и многомерного массива в функцию. Передача структуры и класса в функцию

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 . Управляемые указатели ( ^ ) на структуры и классы

Структурный тип данных в языке Си

Примером структуры может послужить любой объект, для которого описывается ряд его характеристик, имеющих значение в данной программе. Например, для книг это может быть название, автор, количество страниц; для окружности — координаты центра, диаметр, цвет. На языке программирования C объявление вышеупомянутых структурных типов данных может выглядеть так:

struct book  char title[50]; char author[30]; int pages; >; struct circle  int x, y; float dia; char color[10]; >;

В данном случае мы как бы создаем новый тип данных, но еще не объявляем переменных этих типов. Обратите внимание на точку с запятой в конце объявлений.

Чаще переменные структур объявляются так:

struct circle a, b, c; struct book mybook;

Здесь объявляются три структуры типа circle и одна структура типа book . Можно объявлять типы структур и их переменные по-иному, но мы для избежания путаницы рассматривать другие способы не будем.

Каждая переменная типа circle содержит четыре элемента (или поля) — x , y , dia , color . Можно сказать, что они представляют собой вложенные переменные. Причем эти переменные разных типов. Таким образом переменная-структура позволяет объединить под одним именем ряд разнородных данных. Обычно это нужно для удобства обработки данных. Если нельзя было бы создавать структуры, то пришлось бы создавать множество независимых переменных или ряд массивов, явной взаимосвязи между которыми не было бы. Структуры же позволяют объединять взаимосвязанные данные. Это конечно еще не объектно-ориентированное программирование, но уже взгляд в его сторону.

Объявив переменную структурного типа, мы можем получить доступ к каждому ее элементу для присваивания, изменения или получения значения:

a.x = 10; a.dia = 2.35; printf("%.2f ", a.dia);

Значение элементов структуры можно сразу определять при объявлении переменной, что похоже на инициализацию массивов:

struct book lang_c = {"Language C", "Ritchi", 99};

Значение переменной-структуры можно присвоить переменной того же типа:

struct book { char *title, *author; int pages; }; struct book old, new; old.title = "GNU/Linux"; old.author = "people"; old.pages = 20213; new = old; new.pages += 2000; printf("%d, %d\n", old.pages, new.pages);

В примере данные переменной old присваиваются new . В итоге вторая структура содержит копию данных первой. То, что можно выполнять присваивание по отдельным полям должно быть понятно.

Структуры и функции

Структуры-переменные можно передавать в функции в качестве аргументов. Также функция может возвращать структуру. Структуры передаются по значению, как обычные переменные, а не по ссылке, как массивы.

Рассмотрим программу, в которой одна функция возвращает структуру, а другая — принимает структуру в качестве параметра:

#include #include struct circle { int x, y; float dia; char color[10]; }; struct circle new_circle(); void cross (struct circle); int main () { struct circle a; a = new_circle(); cross(a); } struct circle new_circle() { struct circle new; printf("Координаты: "); scanf("%d%d", &new.x, &new.y); printf("Диаметр: "); scanf("%f", &new.dia); printf("Цвет: "); scanf("%s", new.color); return new; } void cross (struct circle c) { double hyp; hyp = sqrt((double) c.x * c.x + (double) c.y * c.y); printf("Расстояние: %.2lf\n", hyp); if (hyp  c.dia / 2) puts("Пересекает"); else puts("Не пересекает"); }

Примечание. При компиляции программы в GNU/Linux команда выглядит так: gcc program.c -lm . Это связано с использованием библиотеки с математическими функциями.

  • Объявляется структура circle как глобальный тип данных. Таким образом любая, а не только main , функция может создавать переменные этого типа.
  • Функция new_circle() возвращает структуру, а функция cross() принимает структуру по значению. Следует отметить, что можно создавать функции, которые как принимают (возможно, несколько структур) так и возвращают структуру.
  • В функции new_circle создается переменная new типа struct circle , поля которой заполняются пользователем. Функция возвращает значение переменной new в функцию main , где это значение присваивается переменной a , которая также принадлежит типу sctruct circle .
  • Функция cross определяет, пересекает ли круг начало координат. В ее теле вычисляется расстояние от центра круга до начала координат. Это расстояние является гипотенузой прямоугольного треугольника, длина катетов которого равна значениям x и у . Далее, если гипотенуза меньше радиуса, то круг пересекает начало координат, т.е. точку (0, 0).
  • В функции main при вызове cross() данные, содержащиеся в переменной a , копируются и присваиваются переменной c .

Указатели и структуры

В отличие от массивов, структуры передаются в функции по значению. Это не всегда рационально, т.к. структуры могут быть достаточно большого размера, и копирование таких участков памяти может замедлять работу программы. Поэтому часто структуры в функцию передают по ссылке, при этом можно использовать как указатель, так и операцию получения адреса.

// переменная-структура struct book new; // указатель на структуру struct book *pnew; // передаем адрес reader(&new); pnew = &new; // передаем указатель reader(pnew); 

Тогда функция reader должна иметь примерно такое объявление:

void reader(struct book *pb); 

Возникает вопрос, как при использовании указателей обращаться к элементам структур? Во первых надо получить саму структуру, т.е. если pnew указатель, то сама структура будет *pnew . Далее можно уже обращаться к полям через точку: *pnew.title . Однако это выражение не верно, т.к. приоритет операции «точка» (обращение к полю) выше операции «звездочка» (получить значение по адресу). Таким образом приведенная запись сначала пытается получить значение поля title у указателя pnew , но у pnew нет такого поля. Проблема решается с помощью скобок, которые изменяют порядок выполнения операций: (*pnew).title . В таком случае сначала извлекается значение по адресу pnew , это значение является структурой. Затем происходит обращение к полю структуры.

В языке программирования C записи типа (*pnew).title часто заменяют на такие: pnew->title , что позволяет синтаксис языка. Когда в программе вы видите стрелку (тире и скобка) всегда помните, то, что написано до стрелки, — это указатель на структуру, а не переменная-структура.

Пример кода с использованием указателей:

#include struct circle { int x, y; float dia; }; void inversion (struct circle *); int main () { struct circle cir, *pc = &cir; pc->x = 10; pc->y = 7; pc->dia = 6; inversion(pc); printf("x = %d, y = %d\n", cir.x, cir.y); } void inversion(struct circle *p) { p->x = -p->x; p->y = -p->y; }

Массивы структур

Обычно создание в программе одной переменной структурного типа не имеет особого смысла. Чаще структурами пользуются, когда необходимо описать множество похожих объектов, имеющих разные значения признаков. Значения каждого объекта следует объединить вместе (в структуру) и тем самым отделить от значений других объектов. Например, описание ряда книг или множества людей. Таким образом мы можем организовать массив, где каждый элемент представляет собой отдельную структуру, а все элементы принадлежат одному и тому же структурному типу.

Напишем программу для учета персональных компьютеров в организации. Каждая структура будет описывать определенные модели и содержать поле, в котором будет указано количество таких объектов. Поэтому при объявлении структурного типа данных следует описать такие поля как тип компьютера, модель процессора, количество.

Программа будет предоставлять возможность получать информацию о всех моделях и изменять количество компьютеров указанной пользователем модели. В программе будут определены две функции (помимо main ): для вывода всей информации и для изменения количества компьютеров.

#include #define N 4 struct computer { char *type; char *proc; int qty; }; void viewer (struct computer *); void changer (struct computer *); int main () { struct computer comps[N]= { "Desktop", "Core", 20, "Notebook", "Core", 5, "Desktop", "AMD", 10, "Notebook", "AMD", 2, }; viewer(comps); changer(comps); viewer(comps); } void viewer (struct computer *comp) { for (int i = 0; i  N; i++, comp++) printf("%2d) %-8s - %-15s: %3d\n", i+1, comp->type, comp->proc, comp->qty); } void changer (struct computer *comp) { int i, differ; printf("Введите номер модели: "); scanf("%d", &i); i--; printf("На сколько уменьшить или увеличить: "); scanf("%d", &differ); (comp+i)->qty += differ; }
  • Массив структур инициализируется при его объявлении.
  • Функции viewer() и changer() принимают указатели на структуру computer .
  • В теле viewer указатель инкрементируется в заголовке цикла; таким образом указывая на следующий элемент массива, т.е. на следующую структуру.
  • В выражении (comp+i)->qty скобки необходимы, т.к оператор -> имеет более высокий приоритет. Скобки позволяют сначала получить указатель на i-ый элемент массива, а потом обратиться к его полю.
  • Декрементирование i в функции changer связано с тем, что индексация начинается с нуля, а номера элементов массива, которые пользователь видит на экране, с единицы.
  • Для того, чтобы уменьшить количество компьютеров, при запросе надо ввести отрицательное число.

Пример результата работы программы:

1) Desktop - Core : 20 2) Notebook - Core : 5 3) Desktop - AMD : 10 4) Notebook - AMD : 2 Введите номер модели: 3 На сколько уменьшить или увеличить: -2 1) Desktop - Core : 20 2) Notebook - Core : 5 3) Desktop - AMD : 8 4) Notebook - AMD : 2

Перепишите приведенную выше программу и дополните ее функцией, которая позволяет добавлять в массив новый элемент-структуру.

Курс с решением задач:
pdf-версия

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *