Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lesson_16.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
134.14 Кб
Скачать

Урок 16.

План занятия.

  1. Структуры.

  2. Оператор sizeof.

  1. Структуры.

Введение в структуры

Предположим, вы необходимо хранить информацию о баскетболисте. Вы хотите хранить его имя, зарплату, рост, вес, среднюю результативность, процент попаданий, результативных передач и т.п. Вам понадобится некоторая форма данных, которая могла бы хранить всю эту информацию как единое целое. Массив здесь не подойдет. Хотя массив может хранить несколько элементов, но все они должны быть одного типа. То есть один массив может хранить 20 целых чисел, другой — 10 чисел с плавающей точкой, однако массив не может хранить целые значения в одних элементах и значения с плавающей точкой — в других.

Удовлетворить вашу потребность в совместном хранении всей информации о баскетболисте может структура C++. Структура — более универсальная форма данных, нежели массив, потому что одна структура может хранить элементы более чем одного типа. Это позволяет унифицировать представление данных за счет сохранения всей информации, связанной с баскетболистом, в одной переменной типа структуры. Если вы хотите отслеживать информацию о целой команде, то можете воспользоваться массивом структур. Тип структуры — это еще и ступенька к покорению бастиона объектно-ориентированного программирования C++ — класса. Изучение структур приблизит вас к сердцу ООП на языке C++.

Структура – это пользовательский тип данных, который создается программистом. Это простейший класс. После определения типа можно создавать переменные этого типа. То есть создание структуры — процесс, состоящий из двух частей. Вначале определяется описание структуры, в котором перечисляются и именуются типы данных, хранящиеся в структуре. Затем создаются структурные переменные, или, иначе говоря, структурные объекты данных, которые следуют плану, заданному объявлением.

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

struct inflatable // объявление структуры

{

char name[20];

float volume;

double price;

};

Ключевое слово struct указывает на то, что этот код определяет план структуры. Идентификатор inflatable — имя, или дескриптор, этой формы, т.е. имя нового типа. Таким образом, теперь можно создавать переменные типа inflatable точно так же, как создаются переменные типа char или int. Далее между фигурными скобками находится список типов данных, которые будут содержаться в структуре. Каждый элемент списка — это оператор объявления. Здесь допускается использовать любые типы C++, включая массивы и другие структуры. В этом примере применяется массив char, который подходит для хранения строки, затем идет один элемент типа float и один — типа double. Каждый индивидуальный элемент в списке называется членом структуры, так что структура inflatable имеет три члена.

После определения структуры можно создавать переменные этого типа:

inflatable hat; // hat — структурная переменная типа inflatable

inflatable woopie_cushion; // переменная типа inflatable

inflatable mainframe; // переменная типа inflatable

Дескриптор структуры используется в точности как имя фундаментального типа. Это изменение подчеркивает, что объявление структуры определяет новый тип.

При условии, что переменная hat имеет тип inflatable, для доступа к ее отдельным членам используется операция принадлежности или членства (.).

Например, hat.volume ссылается на член структуры по имени volume, a hat. price — на член по имени price. Аналогично, vincent.price — это член price переменной vincent. Короче говоря, имена членов позволяют ссылаться на члены структур почти так же, как индексы — на элементы массивов. Поскольку член price объявлен как double, члены hat.price и vincent.price являются эквивалентами переменных типа double и могут быть использованы точно так же, как любая другая переменная типа double. Короче говоря, hat является структурой, но hat.price относится к типу double.

Расположение объявления структуры.

Существует два варианта. Объявление можно разместить внутри функции main (). Второй вариант, использованный здесь, состоит в том, чтобы расположить объявление за пределами функции main (). Когда объявление встречается вне функции, оно называется внешним объявлением.

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

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

Теперь обратите внимание на процедуру инициализации:

inflatable guest =

{

"Glorious Gloria", // значение name

1.88, // значение volume

29.99 // значение price

};

Simple_struct.cpp

#include <iostream>

using namespace std;

struct inflatable //объявление структуры

{

char name[20]; //наименование продукта

float volume; //объем продукта в футах

double price; //цена продукта

};

void main()

{

setlocale (LC_CTYPE, "russian");

//инициализация переменных структуры

inflatable pr1 = { //структурная переменная pr1 типа inflatable

"Golden Gloriya", //значение name

1.88, //значение volume

29.99 //значение price

};

inflatable pr2 = { "B Product", 2.33, 32.45}; //структурная переменная pr2 типа inflatable

cout << "Реализуются следующие продукты: " << pr1.name << " и " << pr2.name << endl;

cout << "Их совокупная цена: " << pr1.price+pr2.price <<endl;

cin.get();

cin.get();

}

Каждый член структуры можно инициализировать данными соответствующего вида. Например, член структуры name — это символьный массив, поэтому его можно инициализировать строкой. Каждый член структуры трактуется как переменная этого типа. То есть pr2.price — переменная типа double, a pr2.name — массив char. И когда программа использует cout, чтобы отобразить pr2.name, она отображает этот член как строку. Кстати, поскольку pr2.name — символьный массив, для доступа к его отдельным символам можно использовать индексы. Например, pr2.name [0] содержит символ А. Однако pr2 [0] не имеет смысла, потому что pr2 является структурой, а не массивом.

Пустые фигурные скобки приводят к установке индивидуальных членов в 0.

Например, следующее объявление обеспечивает установку в 0 членов mayor .volume

и mayor .price, а также всех байтов в mayor. name:

inflatable mayor { } ;

И, наконец, сужение не допускается.

Структура может содержать член типа string при условии, что не используется устаревший компилятор, который не поддерживает инициализацию структур с помощью членов класса string, т.е.:

#include <string>

struct inflatable // определение структуры

{

std::string name;

float volume;

double price;

};

Прочие свойства структур

В C++ пользовательские типы сделаны, насколько возможно, похожими на встроенные типы. Например, структуру можно передавать как аргумент функции, а функция может использовать структуру в качестве возвращаемого значения. Также можно применять операцию присваивания (=), чтобы присвоить одну структуру другой того же самого типа. Эта операция устанавливает значение каждого члена одной структуры равным значению соответствующего члена другой структуры, даже если член является массивом. Такой тип присваивания называется почленным присваиванием.

Присваивание структур:

#include <iostream>

struct inflatable

{

char name[20];

float volume;

double price;

};

int main ()

{

using namespace std;

inflatable bouquet =

{

"sunflowers",

0.20,

12.49

};

inflatable choice;

cout « "bouquet: " « bouquet.name « " for $";

cout « bouquet .price « endl;

choice = bouquet; // присваивание одной структуры другой

cout « "choice: " « choice.name « " for $";

cout « choice.price « endl;

return 0;

}

Можно комбинировать определение формы структуры с созданием структурных переменных. Чтобы сделать это, сразу после закрывающей фигурной скобки понадобится указать имя переменной или нескольких переменных:

struct perks

{

int key_number;

char car[12];

} mr_smith, ms_jones; // две переменных типа perks

Можно даже инициализировать созданную переменную, как показано ниже:

struct perks

{

int key_number;

char car[12];

} mr_glitz =

{

7, //значение члена mr_glitz.key_number

"Packard" // значение члена mr_glitz.car

};

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

Структура inflatable содержит массив (по имени name). Также можно создавать массивы, элементами которых являются структуры. Подход здесь в точности совпадает с таковым для массивов фундаментальных типов. Например, чтобы создать массив из 100 структур inflatable, можно поступить так:

inflatable gifts[100]; // массив из 100 структур inflatable

Это объявление делает gifts массивом структур inflatable. В результате каждый элемент массива, такой как gifts [0] или gifts [99], является объектом типа inflatable и может быть использован с операцией членства:

cin » gifts[0].volume; // используется член volume первой структуры

cout << gifts [99] .price << endl; // отображается член price последней структуры

Имейте в виду, что сам по себе gifts является массивом, а не структурой, поэтому конструкция вроде gifts.price — некорректна.

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

inflatable guests [2] = // инициализация массива структур

{

{"Bambi", 0.5, 21.99}, // первая структура в массиве

{"Godzilla", 2000, 5 65.99} // следующая структура в массиве

};

// arrstruc.срр -- массив структур

finclude <iostream>

struct inflatable

{

char name[20];

float volume;

double price;

};

int main ()

{

using namespace std;

inflatable guests [2] = // инициализация массива структур

{

{"Bambi", 0.5, 21.99}, // первая структура в массиве

{"Godzilla"/ 2000, 5 65.99} // следующая структура в массиве

};

cout « "The guests " << guests [0] .name « " and " << guests [1] .name

« "\nhave a combined volume of "

« guests[0].volume + guests[1].volume << " cubic feet.\n";

return 0;

}

Функции и структуры

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

Имя структуры — это просто имя структуры, и если необходим ее адрес, то вы можете получить его с помощью операции &.

Самый прямой способ использования структуры в программе — это трактовать их так же, как обычные базовые типы — т.е. передавать в виде аргументов и если нужно, то использовать их в качестве возвращаемых значений. Однако существует один недостаток в передаче структур по значению. Если структура велика, то затраты, необходимые для создания копии структуры, могут значительно увеличить потребности в памяти и замедлить работу программы. По этой причине (и еще потому, что изначально язык С не позволял передавать структуры по значению) многие программисты на С предпочитают передавать адрес структуры и затем использовать указатель для доступа к ее содержимому. В C++ предлагается третья альтернатива, которая называется передачей по ссылке. Давайте сейчас рассмотрим два первых варианта, начиная с передачи и возврата целых структур.

Передача и возврат структур

Первый пример имеет дело со временем путешествия (не путать с путешествиями во времени). Некоторые карты сообщают, что на проезд из Thunder Falls в Bingo City нужно потратить 3 часа 50 минут, а на проезд из Bingo City в Grotesquo — 1 час 25 минут. Для представления этих периодов времени можно использовать структуру, один член которой предназначен для представления часов, а другой — для минут. Сложение двух периодов будет не простым, потому что придется преобразовывать минуты в часы, когда их сумма превышает 60. Например, два периода времени на дорогу, приведенные выше, дают в сумме 4 часа 75 минут, что должно быть преобразовано в 5 часов 15 минут. Давайте разработаем структуру для представления значений времени, а затем функцию, которая будет принимать две таких структуры в виде аргументов и возвращать структуру, представляющую их сумму. Определить структуру просто:

struct travel_time

{

int hours;

int mins;

};

Далее рассмотрим прототип для функции sum(), который вернет сумму двух таких структур. Возвращаемое значение должно иметь тип travel_time, как и два ее аргумента.

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

travel_time sum(travel_time tl, travel_time t2) ;

Чтобы сложить два периода времени, сначала необходимо сложить минуты. Целочисленное деление на 60 даст количество часов, в которые сложатся минуты, а операция модуля (%) даст оставшиеся минуты. В листинге этот подход воплощен в функции sum (); еще одна функция, show_time (), служит для отображения содержимого структуры travel_time.

#include <iostream>

using namespace std;

struct travel_time

{

int hours;

int mins;

};

const int Mins_per_hr = 60;

travel_time sum(travel_time tl, travel_time t2);

void show_time(travel_time t);

void main()

{

setlocale (LC_CTYPE, "russian");

travel_time dayl = {5, 45}; // 5 часов 45 минут

travel_time day2 = {4, 55}; // 4 часов 55 минут

travel_time trip = sum(dayl, day2);

cout << "Two-day total: "; // итог за два дня

show_time (trip) ;

travel_time day3= {4, 32};

cout << "Three-day total: "; // итог за три дня

show_time(sum (trip, day3));

}

travel_time sum (travel_time tl, travel_time t2)

{

travel_time total;

total.mins = (tl.mins + t2.mins) % Mins_per_hr;

total.hours = tl.hours + t2.hours +

(tl.mins + t2.mins) / Mins_per_hr;

return total;

}

void show_time(travel_time t)

{

cout << t.hours << " hours, "

<< t.mins << " minutes\n"; // часов, минут

}

Вывод:

Two-day total: 10 hours, 40 minutes

Three-day total: 15 hours, 12 minutes

Для продолжения нажмите любую клавишу . . .

«ШАГ»

В самом начале изучения языка С мы с Вами познакомились с понятием типы данных. Сегодня мы попробуем расширить это понятие. Дело в том, что помимо стандартных типов программист может создавать свои собственные составные типы данных под названием структуры. Именно они и будут являться темой нашего занятия.

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

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

Рассмотрим особенности работы со структурами на примере.

#include <iostream>

using namespace std;

/*

Создание пользовательского типа данных

(структуры) для хранения даты.

Все данные касающиеся одного объекта

собраны вместе.

*/

struct date

{

int day; //день

int month; //месяц

int year;//год

int weekday; //день недели

char mon_name[15];// название месяца

};

void main(){

//создание объекта с типом date и инициализация его при создании

date my_birthday={20,7,1981,1,"July"};

// показ содержимого объекта на экран

// обращение к отдельному члену структуры производится через

// оператор точка (.)

cout<<"________________MY BIRTHDAY____________________\n\n";

cout<<"DAY "<<my_birthday.day<<"\n\n";

cout<<"MONTH "<<my_birthday.month<<"\n\n";

cout<<"YEAR "<<my_birthday.year<<"\n\n";

cout<<"WEEK DAY "<<my_birthday.weekday<<"\n\n";

cout<<"MONTH NAME "<<my_birthday.mon_name<<"\n\n";

// Создание пустого объекта и заполнение его с клавиатуры

date your_birthday;

cout<<"DAY ? ";

cin>>your_birthday.day;

cout<<"MONTH ?";

cin>>your_birthday.month;

cout<<"YEAR ?";

cin>>your_birthday.year;

cout<<"WEEK DAY ?";

cin>>your_birthday.weekday;

cout<<"MONTH NAME ?";

cin>>your_birthday.mon_name;

cout<<"________________YOUR BIRTHDAY____________________\n\n";

cout<<"DAY "<<your_birthday.day<<"\n\n";

cout<<"MONTH "<<your_birthday.month<<"\n\n";

cout<<"YEAR "<<your_birthday.year<<"\n\n";

cout<<"WEEK DAY "<<your_birthday.weekday<<"\n\n";

cout<<"MONTH NAME "<<your_birthday.mon_name<<"\n\n";

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]