МУ_ЛР6_ОП (Методические указания к лабораторным работам), страница 2

2018-01-11СтудИзба

Описание файла

Файл "МУ_ЛР6_ОП" внутри архива находится в папке "Методические указания к лабораторным работам". Документ из архива "Методические указания к лабораторным работам", который расположен в категории "". Всё это находится в предмете "программирование на основе классов и шаблонов" из 2 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "программирование на основе классов и шаблонов" в общих файлах.

Онлайн просмотр документа "МУ_ЛР6_ОП"

Текст 2 страницы из документа "МУ_ЛР6_ОП"

Face Face2;

Face2.birthdate.day = 30; // Двойная квалификация

9 Указатели на структуры и на динамические структуры

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

struct Person { // Персона

char name[50];

Date birthdate; // структурная переменная дата рожденич

double salary; // Оклад

};

Person p2 = { "Сидоров", {10, 3, 1978}, 1500.48 };

Person * pPerson = &p2;

// Изменить оклад

pPerson -> salary = 10.50;

(*pPerson).salary = 12.50; // Можно и так, но скобки обязательны

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

ptrPerson -> pStudent -> salary = 15.00;

и такого вида (где имеет место двойная квалифицированная ссылка):

p2.birthdate. year = 2014;

10 Передача структур в функцию

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

//

// Функция печати

void PrintPersonName( Person per)

{

printf ("Печать в функции per.name = %s\n" , per.name);

per.salary = 5.0;

};

Прототип в главной программе

void PrintPersonName( Person per);

В программе описания и вызов:

// Описание структуры

Person p2 = { "Сидоров", {10, 3, 1978}, 1500.48 };

//Вызов функции параметром структура

printf( "До функции p2.salary = %f \n" ,p2 .salary );

PrintPersonName( p2 ); // p2

printf( "После функции p2.salary = %f \n" ,p2 .salary );

Получим результат:

До функции p2.salary = 15.000000

Печать в функции per.name = Сидоров

После функции p2.salary = 15.000000

Значение полей структуры (в частности p2.salary) не изменяются.

11 Передача указателя на структуру в функции

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

//

void ChangePersonSalary( Person * p , double newSalary)

{

p -> salary = newSalary; // Изменение по указателю

};

Прототип в главной программе

void PrintPersonName( Person per);

// Описание структуры

Person p2 = { "Сидоров", {10, 3, 1978}, 15.00 };

// Передача указателя

printf( "До функции p2.salary = %f \n" ,p2 .salary );

ChangePersonSalary( &p2 , 30.0); // Передача указателя = &p2

printf( "После функции ChangePersonSalary p2.salary = %f \n" ,p2 .salary );

Получим результат:

До функции p2.salary = 15.000000

После функции ChangePersonSalary p2 .salary = 30.000000

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

Так как структура определяет новый тип переменной, то разрешается описывать массивы структур. Например:

// Описание массива структур типа Prepod

Prepod KafIU[30];

// Работа с элементами массива структур

KafIU[0].Oklad = 10.0;

KafIU[10].Oklad = 10.0;

// Цикл занесения

for (int i =0 ; i < 30 ; i++ )

{

KafIU[i].Oklad = 10.0;

};

Можно с массивом работать через указатель (ptrMas), при этом инициализация его должна быть проведена с начальным адресом массива структур (&KafIU[0]) или именем этого массива (KafIU), так как имя массива задает адрес начала массива.

// или с указателем

//Prepod *ptrMas = &KafIU[0]; // или

Prepod *ptrMas = KafIU;

Возможны способы: индексации указателя (ptrMas[2].Oklad), или вычислением нового адресного выражения для адреса ( ptrMas + 2) или выбором конкретного элемента массива – структуры посредством операции разыменования (*). Смотрите ниже примеры:

ptrMas[2].Oklad = 15.0; // для второго элемента массива структур

( ptrMas + 2) -> Oklad = 25.0; // можно и так

(*( ptrMas + 2)).Oklad = 35.0; // можно и так

ptrMas = ptrMas + 2;

ptrMas->Oklad = 45.0; // можно и так

(*ptrMas).Oklad = 55.0; // можно и так

Во всех рассмотренных случаях будет изменена одно и тоже поле элемента структуры с номером 2.

13 Вложенные структуры

Внутри одной структуры может быть описана другая структура (тип Prepod - DecPrep) или указатель (тип Person - pStudent).

// Структура со вложенными указателями

struct Person {

char name[50];

Date birthdate; // структурная переменная дата рожденич

double salary; // Оклад

};

//

struct Prepod {

char fam[50]; // Фамилия

Person * pStudent; // Указатель на структурную переменную Person

double Oklad; // Оклад

};

// Структура со вложенными структурами

struct Decan {

char fam[50]; // Фамилия

Prepod DecPrep; // Cтруктурная переменная Prepod вложенная

double Oklad; // Оклад

};

В программе для указателей поместим операторы вычисления (salary) оклада:

Prepod *ptrPerson = (Prepod * ) malloc ( sizeof (Prepod));

ptrPerson ->pStudent = &p2;

ptrPerson ->pStudent ->salary = 15.00;

// Доступ возможет разными способами

printf( "p2 .salary = %f \n" ,p2 .salary );

printf( "ptrPerson ->pStudent ->salary = %f \n" ,ptrPerson ->pStudent ->salary );

В результате получим:

p2 .salary = 15.000000

ptrPerson ->pStudent ->salary = 15.000000

Для вложенных структур (в структуру Decan вложена структура Prepod, см. Описания выше) можем записать, включая доступ и посредством указателя (pStudent->salary):

// Вложенные структуры

Decan DecIU;

DecIU.DecPrep.Oklad = 100.00;

// Доступ с указателем

DecIU.DecPrep.pStudent = &p2;

DecIU.DecPrep.pStudent->salary = 10.0;

14 Размер и размещение структур в ОП

Поля структуры располагаются в оперативной памяти последовательно, в связи с описанием в программе. При размещении в памяти разные типы должны быть выровнены на границу адреса своего размера ( int – 2 байта, long – 4 байта, double – 8 байт и т.д.). Из-за этого, даже при равных по количеству и типу полей размер структуры может отличаться. Это показано на примере структур First и Second.

struct First {

int i;

long j;

double k;

};

struct Second {

int i;

double k;

long j;

};

В программе определим актуальный размер структуры:

// Размещение структур в ОП

printf( "Размер структуры First = %d \n" ,sizeof (First) );

printf( "Размер структуры Second = %d \n" ,sizeof (Second) );

В результате получим:

Размер структуры First = 16

Размер структуры Second = 24

15 Динамической структуры

Работа с динамическими структурами и их массивами выполняется посредством указателей. Выделение памяти производиться библиотечными функциями из malloc.h. В этой библиотеке доступны функции: malloc, calloc, free, realolc и др. На примере, размещенном ниже, показано применение этих функций для структур.

Decan * pDec = (Decan * ) malloc ( sizeof (Decan)); // Выделение динамической памяти

pDec ->DecPrep.Oklad = 100.00; // Работа с полямиуктур

strcpy( pDec ->fam , "Фамилия декана");

pDec ->Oklad = 50.00;

pDec = (Decan *) realloc( pDec , sizeof (Decan) * 2 ); // Изменение размера

//

pDec = pDec + 1;

strcpy( pDec ->fam , "Новая Фамилия декана");

pDec = pDec - 1; // Востановление указателя для освобождения памяти (можно и /запомпить)

free ( pDec );

Обратите внимание на использование функции realloc, позволяющей изменить размер выделенной памяти в два раза, а также добавление к указателю 1-цы. При операциях целого типа с указателями определенного вида 1-ца соответствует размеру типа, для которого объявлен данный указатель.

16 Создание и удаление динамической структуры со строками

В динамических структурах часто возникает задача работы со строками (символьными массивами). Если заранее в структуре выделять максимальное число требуемых знаков в символьных массивах для строк (так мы поступали ранее, см. – fam , name), то, очевидно, будет значительный перерасход памяти. Поэтому при инициализации таких структур экономнее выделить столько памяти, сколько необходимо, то есть динамической памяти. Аналогичная процедура необходима и для изменения значений строковых полей: сначала идет освобождение (free), а затем новый захват ( malloc). Покажем это на примере. Пусть есть структура, в которой два указателя на строки (pName и pAvtor):

struct Book{

char * pName; // Название книги

char * pAvtor; // Автор книги

int StrCount; // Число страниц в книге

};

При ее инициализации нужно захватить память и записать строку:

Book Book1;

char * pStr = (char *) malloc ( strlen ("Три мушкетера") + 1);

Book1.pName = pStr;

strcpy(pStr , "Три мушкетера" );

pStr = (char *) malloc ( strlen ("Александр Дюма") + 1);

Book1.pAvtor = pStr;

strcpy(pStr , "Александр Дюма" );

Book1.StrCount =670;

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

// При завершении программы освободим память

free (Book1.pName);

free (Book1.pAvtor);

//

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

// Динамическая структура

Book * pBook = (Book *) malloc ( sizeof(Book));

pStr = (char *) malloc ( strlen ("Две Дианы") + 1);

pBook->pName = pStr;

strcpy(pStr , "Две Дианы" );

pStr = (char *) malloc ( strlen ("Александр Дюма") + 1);

pBook->pAvtor = pStr;

strcpy(pStr , "Александр Дюма" );

pBook->StrCount =470;

// При завершении программы освободим память под строки и саму структуру

free (pBook->pName);

free (pBook->pAvtor);

free (pBook );

//

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

free (pBook->pName);

pStr = (char *) malloc ( strlen ("Дама с камелиями") + 1);

pBook->pName = pStr;

strcpy(pStr , " Дама с камелиями" );

17 Структуры со ссылками на себя

В структурах нельзя использовать поля - структурные переменные такого же типа, однако поля - указатели на эти структуры допускаются. Например, элемент двухсвязного списка может выглядеть так:

// структуры со ссылками на самих себя

struct Node {

Node * pNext;

Node * pPrev;

int ValList;

};

В данном случае pNext и pPrev являются указателями на структуру Node.

18 Перечисления - enum

Это набор именованных целых констант, используемый для большей наглядности программы и ее переносимости. Перечисление может быть использовано для объявления переменных, которые принимают значения на заданном множестве значений. Примеры для перечислений: дни недели, месяцы в году, времена года, типы переменных и т.д. Формально перечисления (enum) могут быть описаны так:

enum [ <имя> ] {список перечисления} [ список переменных];

Например, для дня недели можно задать список констант:

// Дни недели

enum { mon , tue , wed , thu , fri , sat , sun };

int d = mon; // mon = 0 , tue = 1 и т.д.

Можно задать имя для объявления переменных перечисления:

// Дни недели с именем day

enum day { mon , tue , wed , thu , fri , sat , sun };

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5173
Авторов
на СтудИзбе
436
Средний доход
с одного платного файла
Обучение Подробнее