Лаб №6 Структуры

Задание к лабораторной работе № 6
Разработать программу, создающую структуру и ее экземпляры. Структура должна содержать поля (см. свой вариант). Кроме того, в структуру должна входить функция вывода значений полей и одна из перегруженных операций (+, >,< ,>=,<=). Программа должна демонстрировать оба способа доступа к полям структуры и работу функции и перегруженной операции.
Краткую 13 LINK \l "Теория" 14теорию15 и 13 LINK \l "Пример" 14пример15 можно рассмотреть по ссылке.

Вариант 1.
Данные для простой складской системы. Структура должна содержать
следующую информацию: фамилию, имя, отчество поставщика, название города местонахождения поставщика, а также уникальный номер детали, ее название, цвет, вес .
Вариант 2.
Сведения об участниках конкурса бальных танцев. Структура должна
содержать следующую информацию: фамилию, имя, отчество участника,
город, фамилию тренера, оценки за каждый из 3-х танцев.
Вариант 3.
Сведения об успеваемости студентов. Структура должна содержать
следующую информацию: фамилию, имя, отчество студента, номер группы,
в которой обучается студент, название учебной дисциплины,
, оценку данного студента по данной дисциплине за
данное задание от 0 до 100 (как % сделанной работы).
Вариант 4.
Сведения о рабочем. Структура должна содержать
следующую информацию: фамилию, имя, отчество рабочего, название цеха,
в котором он работает, его разряд и оклад.
Вариант 5.
Учет изделий, собранных в цехе за неделю. Структура должна содержать
следующую информацию: фамилию, имя, отчество сборщика, количество
изготовленных изделий, название цеха, а также тип изделия и его стоимость.
Вариант 6.
Учет изделий категорий А, В, С, собранных рабочим цеха за месяц. База
данных должна содержать следующую информацию: фамилию, имя,
отчество рабочего, название цеха, количество изделий по категориям
Вариант 7.
Сведения об абонентах АТС. Структура должна содержать следующую
информацию: фамилию, имя, отчество владельца телефона, год установки
телефона, номер телефона, тип установки телефона (спаренный или нет),
льготу (процентную скидку при оплате).
Вариант 8.
Сведения об ассортименте игрушек в магазине. Структура должна
содержать следующую информацию: название игрушки, ее цену, количество,
а также название фабрики и города, где изготовлена игрушка.
Вариант 9.
Результаты сессии на первом курсе. Структура должна
содержать следующую информацию: индекс группы, фамилию, имя,
отчество студента, пол студента и оценки по 3
экзаменам.
Вариант 10.
Учет рейтинга теннисистов за 5 лет. Каждая запись содержит поля: фамилия,
имя, отчество спортсмена, пол, год рождения, фамилия, имя, отчество
тренера, названия страны и пять полей с рейтингом.
Вариант 11.
Сведения о рейсах Аэрофлота. Структура должна содержать следующую
информацию: номер рейса, пункт назначения, время вылета, время прибытия,
тип самолета и его вместимость.
Вариант 12.
Сведения об ассортименте обуви в магазине. Структура должна содержать
следующую информацию: артикул, наименование обуви, количество пар,
стоимость одной пары, имеющиеся размеры, название фабрики
Вариант 13.
Сведения о нападающих команды. Структура должна содержать следующую информацию: фамилию, имя, отчество, название команды, дату приема в команду, число заброшенных шайб, количество голевых передач, штрафное время и количество сыгранных матчей.
Вариант 14.
Сведения о выборе дисциплины студентом. Структура должна содержать
следующую информацию: фамилию, имя, отчество студента, номер зачетной
книжки и сведения о том, живет ли студент в общежитии, индекс группы, а
также пять дисциплин (1 – желает изучать, 0 – не желает).
Вариант 15.
Учет золотых изделий в ювелирном магазине. Структура должна содержать
следующую информацию: вид изделия, его вес, пробу, дату поступления и
стоимость, а также фамилию, имя, отчество мастера-изготовителя, стаж его
работы и разряд (1,2,3).
Вариант 16.
Учет оптовых продаж. Структура должна содержать следующую
информацию: наименование товара, цену единицы товара и дату его
поступления, номер партии, размер партии, названии фирмы-покупателя,
размер проданной партии, цену единицы товара и дату продажи.
Вариант 17.
Учет лекарств в аптеке. Структура должна содержать следующую
информацию: наименование лекарства, стоимость одной единицы,
количество единиц, дату изготовления, срок годности, а также название
фабрики, где производится данное лекарство, ее адрес.
Вариант 18.
Сведения о ветеранах спорта. Структура должна содержать следующую
информацию:фамилию, имя, отчество спортсмена, возрастную группа, название города и вид спорта.
Вариант 19.
Учет рождаемости в роддоме. Структура должна содержать следующую
информацию: фамилию, имя, отчество матери, пол ребенка, его вес, рост и
дату рождения ребенка.
Вариант 20.
Сведения об обучающихся на курсах повышения квалификации. Структура должна содержать следующую информацию: фамилию, имя, отчество
слушателя, его пол и адрес, тип организации (коммерческая, государственная),
наименование организации, должность слушателя и оценки по
прослушанным дисциплинам (маркетинг, финансы и кредит) для каждого
слушателя.
Вариант 21.
Сведения о размере стипендии студента. Структура должна содержать
следующую информацию: фамилию, имя, отчество студента, группу, адрес,
по которому проживает студент, размер стипендии.
Вариант 22.
Учет поступления больных. Структура должна содержать следующую
информацию: фамилию, имя, отчество больного, его пол, дату рождения,
дата поступления, номер палаты, куда был помещен больной, и фамилию, имя, отчество лечащего врача.
Вариант 23.
Учет призывников. Структура должна содержать следующую
информацию: фамилию, имя, отчество призывника, год его рождения, адрес,
семейное положение, заключение о пригодности к службе.

Структуры в языке С++.
Проф. кафедры ИТ и ВТ МГТУ им. А.Н. Косыгина Ю.М. Винтер.

Структура - это составной объект, объединяющих одну, чаще несколько переменных одного или разных типов под одним именем. В отличие от массива, который является совокупностью переменных одного типа, структура может содержать данные различных типов. Каждая переменная, включенная в структуру, называется членом структуры (полем, компонентом, элементом). Структура является новым типом данных, описание которого начинается с служебного слова struct , затем следует выбранное программистом имя (идентификатор ) нового типа данных, далее в фигурных скобках помещается список описаний членов структуры вида тип идентификатор; . После фигурных скобок ставится точка с запятой. Список описаний не может быть пустым.
В приведенном ниже примере идентификатор student является именем нового типа данных.

struct student { char name[70];
int YearOfTheBirth; //год рождения
char grupp[6];
};

Это имя может быть использовано для последующего объявления экземпляров структур
данного типа.
student stud1, stud2, fitae[500];
Здесь выделяется память под 2 переменные и массив типа student.
Члены(поля) структуры могут иметь не только базовый, но и производные типы данных: массивы, классы, объединения и структуры. Член структуры не может быть структурой того же типа, что и содержащая его структура. Зато он может иметь тип указателя на структуру того же типа, что и содержащая его структура. Это позволяет создавать весьма полезные объекты - динамические списки и деревья
Доступ к членам (полям) структуры осуществляется с помощью указания имени(идентификатора) экземпляра структуры и следующего через точку имени члена (поля) структуры , например:
stud1.name="Деев Лев Иванович";
stud1. YearOfTheBirth =1987;
stud1.grupp = "40/05" ;
stud2.name = "Главашки Ия Робертовна";
Таким образом, имя переменной типа структура может быть произвольным, но имена полей должны быть такими, как в описании типа структуры. Инициализацию переменной stud1 можно было выполнить при ее объявлении и следующем образом
student stud1 ={"Деев Лев Иванович",1987, "40/05"};
Если в фигурных скобках не будет указано значение некоторых (последних в порядке следования полей ) , то значениями числовых полей будет 0 , полей – указателей NULL, полей типа char -. \0’.
Второй вариант доступа к полям структуры – по указателю на структуру. Напоминаю, указателем называется переменная (или константа), содержащая адрес другой переменной (или константы). Доступ к членам структуры по указателю осуществляется с помощью имени (индентификатора) указателя на структуру и следующего после
·> имени(идентификатора) члена структуры (поля), например:

student stud1 ={"Деев Лев Иванович",1987, "40/05"};
student * ptr = &stud1; //объявляется указатель на структуру типа student, он
//инициализируется адресом переменной типа student
cout << ptr
·> grupp; // будет выведено на дисплей 40/05
Выражение stud2 = stud1 означает копирование значений полей структуры stud1 в соответствующие поля структуры stud2. Функции С и С++ могут использовать структуры в качестве своих аргументов и возвращаемого значения.
Структура (только в С++, но не в С) может содержать функции, как члены структуры. Эти функции не занимают места в памяти, выделенной под конкретные экземпляры и имеют непосредственный доступ к данным, являющимся членами (полями) структуры (т.е. не требуется передача этих данных, как аргументов функции). Включим для примера в состав структуры student функцию prn, выводящую на дисплей значения полей.
struct student { char name[70];
int YearOfTheBirth;
char* grupp;
void prn () const
{ cout<< "ФИО "<< name << endl;
cout<< "Год рождения "<< YearOfTheBirth < cout<< "Группа "<< grupp << endl;
};
};
Здесь необязательное const после prn () означает, что функция не изменяет значения полей структуры. Пример применения функции – члена структуры:
student stud1 ={"Деев Лев Иванович",1987, "40/05"};
stud1.prn();
Будет выведено на дисплей:
ФИО Деев Лев Иванович
Год рождения 1987
Группа 40/05
В этом случае принято говорить о членах- данных и членах – функциях. В современных языках с видеокомпонентами принято члены- данные называть свойствами, а члены – функции – методами.
Если тело функции присутствует в описании структуры, то это означает , что вы предлагаете компилятору (инструкция inline) не хранить переведенный на машинный язык код функции в определенном месте памяти, а вставлять этот код в программу столько раз, сколько встречается вызов этой функции. При этом увеличивается быстродействие, но растет объем exe – файла. Компилятор не обязан выполнять это ваше указание, и не будет этого делать, если в теле функции есть цикл или сложные, вложенные операторы if . Если структура содержит много функций, или функция не может быть inline, или вас больше волнует объем exe – файла, то в описании структуры должны присутствовать только прототипы функций, а заголовки функций и их тела должны располагаться вне описания структуры. Пример:

struct student { char name[70];
int YearOfTheBirth;
char* grupp;
void prn () const;
};

inline void student :: prn() const
{ cout<< "ФИО "<< name << endl;
cout<< "Год рождения "<< YearOfTheBirth < cout<< "Группа "<< grupp << endl;
};
Здесь :: - операция разрешения области видимости, указывает компилятору, что prn является членом структуры student и этой функции видимы (т.е. могут использоваться непосредственно) поля структуры. Если вы не хотите, чтобы функция была inline, или
функция не может быть inline, то это служебное слово следует исключить.
Важной возможностью структур С++ ( но не языка С) являются перегрузка операций. Перегрузка операций позволяет использовать, например, операции
>,<,==,!=,>=,<=, +,- и другие для нового, созданного вами типа данных, самым естественным образом. Для демонстрации перегрузки операций дополним структуру student членом типа float, содержащим среднее значение всех проставленных к данному моменту в зачетку отметок а также функцией – членом, осуществляющим перегрузку операции > таким образом, что выражение stud1>stud2 (stud1 и stud2 – экземпляры структуры student) будет означать: если средняя отметка 1-го студента выше, то выражение будет равно 1 (в противном случае – 0).Для перегрузки операции создается функция, прототип которой состоит из типа возвращаемого операцией значения (за исключением случая перегрузки операции приведения типа), служебного слова operator, символа (или символов) перегружаемой операции и размещенного, как обычно в круглых скобках, списка описаний аргументов (параметров),нужных для вычисления результата перегружаемой операции:
struct student
{char name[70];
int YearOfTheBirth;
float mark; //средняя отметка
char* grupp;
void prn () const;
int operator > (student /*другой студент */)const;
};
inline void student :: prn() const
{ cout<< "ФИО "<< name << endl;
cout<< "Год рождения "<< YearOfTheBirth < cout<< "Средняя отметка "<< mark < cout<< "Группа "<< grupp << endl;
};

inline int student :: operator > (student OtherStudent) const
{ if mark > OtherStudent.mark return 1;
return 0; //в противном случае
}
Тело этой функции с помощью операции "?" можно написать проще:
{return mark > OtherStudent.mark ? 1:0;}
Операция "?" подобна функции ЕСЛИ в Excel.
Вызов перегруженной операции приведет к копированию в системный стек достаточно большой структуры OtherStudent, что невыгодно. Лучше сообщить функции адрес этой структуры и тем самым избежать копирования. Наиболее простой способ добиться этого – применить тип данных ссылка (в С++ ссылка и указатель – разные типы данных) Прототип функции, перегружающей операцию > будет выглядеть так
int operator > (student &)const;
или
int operator > (student & OtherStudent) const;
что равноценно. Символ & (здесь: ссылка на тип данных student) означает передачу структуры OtherStudent в функцию по адресу , без копирования, – подобно var в аналогичной ситуации в Паскале. Передача параметров в функцию по ссылке или по указателю применяется также для того, чтобы функция могла изменить их значения. Чтобы зрительно отличить эти два случая, применяют служебное слово const : int operator > (const student & OtherStudent) const;
которое запрещает изменять параметр в теле функции. C++ несколько злоупотребляет символом & . Он может обозначать ссылку, операцию получения адреса , побитовую логическую операцию И , но значение этого символа всегда ясно из контекста. Нельзя перегрузить операцию (т.е. придать ей другой смысл) для базовых типов языка. Для перегружаемых операций можно использовать только те обозначения операций, которые уже есть в языке (т.е, +, *, <<,&,|, new, / , [] и т.д.), ибо только для них компилятору известны приоритет и направление выполнения (слева направо или наоборот).
Важным преимуществом языка С++ является возможность применения
шаблонов в функциях и структурах. Шаблоны дают возможность создать одно и то же описание функции и структуры для в определенной степени произвольного типа аргумента (в случае функции) или поля (в случае структуры, класса). При создании экземпляра структуры с помощью специального синтаксиса шаблон заменяется конкретным типом поля.
Для примера создадим структуру, описывающую комплексное число. С++ 3.1 фирмы Borland имеет класс complex, поля данных которого имеют тип double и его размер равен таким образом 16 –ти байтам. Класс complex совершенно необходим, например, для вычисления спектрограммы пряжи по результатам измерения ее линейной плотности, которое (вычисление) должно использовать метод быстрого преобразования Фурье (БФП). Т.к. данные измерения имеют в лучшем случае тип integer (а иногда и char -256 уровней), а замеры следуют через 1-2 мм, то применение класса complex приведет к неоправданному расходу памяти и увеличению времени вычисления. Использование шаблона делает описание структуры complex пригодным как для изложенного случая(т.е члены complex смогут иметь любой числовой тип данных) , так и для вычислений с повышенной точностью:

/*1*/template //шаблон, T – произвольный идентификатор
struct complex
{T re, im;};//действительная и мнимая части имеют неизвестный заранее тип
/*2*/ complex() { re=im = T();} //конструктор,обнуляюoий поля
/*3*/ complex(T x, T y=0) { re=x;im =y;} //перегруженный конструктор
/*4*/ complex operator + (){return *this;} //вернуть самого себя
/*5*/ complex operator - () {return complex(-re, -im);}
//перегрузка оператора + для сложения комплексных чисел
/*6*/ complex operator+( complex & cmpl2)
{ return complex(re + cmpl2.re, im + cmpl2.im);}
//перегрузка оператора - для вычитания комплексных чисел
/*7*/ complex operator-( complex & cmpl2)
{ return complex(re - cmpl2.re, im - cmpl2.im);}
//перегрузка оператора * для умножения комплексных чисел
/*8*/ complex operator*( complex & cmpl2)
{ return complex(re * cmpl2.re - im * cmpl2.im,
re * cmpl2.im + im * cmpl2.re );
}
//перегрузка оператора / для деления комплексных чисел -прототип
/*9*/ complex operator / ( complex & cmpl2);
void prn () const {cout << '{'<< re<<" , "< };//конец структуры
//тело функции для деления комплексных чисел – описание вне тела структуры
/*10*/ template
inline complex complex:: operator / ( complex & cmpl2)
{ T tmp =cmpl2.re*cmpl2.re + cmpl2.im*cmpl2.im;
T real = (re* cmpl2.re + im* cmpl2.im )/tmp;
T imped =(im* cmpl2.re - re* cmpl2.im )/tmp;
return complex (real,imped); //вызов конструктора
}

Шаблон структуры вводится служебным словом template после которого в угловых скобках располагается список шаблонов. Элементы списка разделяются запятыми. Каждый элемент состоит из служебного слова class ( не имеет ничего общего с классом – типом, в более поздних версиях оно может быть заменено более подходящим к данному случаю служебным словом typename) и следующего за ним идентификатора шаблона. Идентификаторы списка шаблонов должны быть различными. Внутри описания структуры идентификатор шаблона используется очень редко – в данном случае при вызове конструктора для формирования возвращаемого значения членом – функцией структуры: complex. Здесь это необходимо потому, что возможно в принципе существование одновременно второго шаблона. А вот если в теле структуры описан только прототип члена – функции структуры, то при ее описании вне структуры обязательным является повторение template , причем идентификаторы шаблонов структуры и функции должны совпадать (строки №1 и №10). При создании экземпляра структуры после указания типа структуры в угловых скобках должен быть указан фактический тип данных, который подставляется вместо шаблона.

Например:
complex a(1.,1.),b(2),c;
В результате происходит вызов конструктора (строка №3 для a и b, строка №2 для c), при этом значения в круглых скобках при идентификаторах a и b преобразуются к типу float ( а их изначальный тип – double и int), выделяется память под 3 структуры (8 байт на каждую), а поля структур получают значения, соответствующие комплексным числам 1.0 + 1.0i, 2.0 + 0.0i и 0.0 + 0.0i. Строка кода
complex d = a * a;
приведет к вызову перегруженного оператора * , поля структуры d получат значения, соответствующие комплексному числу 0.0 - 2.0i. В строке №4 применен указатель this, который неявно получает каждый экземпляр структуры (класса, объединения). Этот указатель содержит адрес экземпляра структуры, а операция разыменования * , примененная к this , возвращает саму структуру. Список параметров функций, обеспечивающих перегрузку бинарных операций(т.е. операций над двумя операндами : см. строки №6,7,8,9) содержит только один – 2-ой операнд, поскольку 1-ым операндом является экземпляр структуры, вызывающий бинарную операцию. В условиях предыдущего примера
d = a + b;
равносильно
d.operator + (b);
Поэтому возможно вычисление выражения a + 4.0 , которое будет истолковано компилятором, как d.operator + (complex(4.0)) , где complex(4.0) является вызовом конструктора для преобразования 4.0 (тип double) к типу complex. Но лучше определить соответствующие функции – члены класса, например
complex operator+(T x)
В тоже время выражение 4.0 + a вызовет ошибку, так как первое слагаемое не является структурой типа complex и не может вызвать функцию operator+. Более того, невозможно создать соответствующую функцию – член структуры, обеспечивающую перегрузку операции +, поскольку в этом случае 1-ым операндом становится структура. Выход в том, чтобы создать не входящую в состав структуры функцию со списком аргументов – операндов в нужном порядке и перегружающую операцию в подобном случае:
template
complex operator+(double x, complex & cmpl2)
{ return complex(x + cmpl2.re, cmpl2.im);}
Поскольку эта функция не является членом структуры complex , то идентификатор шаблона функции не обязан совпадать с идентификатором шаблона структуры .
Структура фактически отличается от класса доступностью компонентов по умолчанию (спецификатор доступа public: - т.е. общедоступны ), в то время, как у класса спецификатором доступа по умолчанию является private: -поля недоступны с помощью обычных методов “.” и “
·>”. Обычно доступ private применятся для членов-данных, а public - для членов- функций (за исключением тех функций, которые упрощают написание основных членов- функций ). В этом случае чтение и запись членов-данных производится с помощью специально созданных для этого членов- функций. С моей точки зрения доступ private применять для членов-данных разумно в случаях
Данные не могут принимать все допустимые для их типа значения, и поэтому
проверку значений – кандидатов на присвоение выгодно сосредоточить в одном
месте – в члене функции . Примером такого члена- данного может служить сумма
средств на банковском счете – при любых операциях она не должна стать
отрицательной.
Член- данное получает значение только 1-раз, и в дальнейшем оно не может быть изменено. Пример – время создания экземпляра.
Член данное доступно остальной части программы только чтения. Пример - член данное – это количество элементов, размещенных в специально управляемом массиве (стеке, хеш-таблице), которое изменяется только членами-функциями при вставке и удалении элементов.
В заключение коснемся особенностей применения шаблонов функций . Шаблоны позволяют не создавать много перегруженных функций для аргументов различных типов :
int max (int a,int b); float max (float a, float b); и т.д. а только одну
template max (T a, T b) { return a > b ? a:b;}
Она может быть использована для переменных любых типов , если для них определена операция > . Однако при наличии шаблона компилятор требует точного соответствия типов остальных параметров в вызове функции описанию функции. Он не использует автоматического приведения типов, как в обычно, когда шаблона нет. Пример : дана функция
template
void far SortInsert (T[]item,long count,int down=0 );
В использующей ее программе нельзя объявить массив так
сonst long N = 1500;
int mas [N};
и вызвать функцию
SortInsert (mas,N);,
потому, что в описании функции N –переменная, а не константа
Следует использовать директиву препроцессора:
# define N 1500L //, где L или l указывает компилятору, что 1500 – это длинное целое.
int mas [N};
SortInsert (mas,N);
Препроцессор изменит вызов функции на
SortInsert (mas,1500L), что не вызовет у компилятора никаких возражений. Второй путь-создать динамический массив.


-***-
Пример выполнения работы
(структура боксер):

# include
# include
# include

const LEN = 40,LEN3=120;
struct boxer {char fam[LEN] ,ima[LEN],otch[LEN];
unsigned rost,pobed,poragen;
float wes;
void prn () const
{printf ("\n%s %s %s\n",fam,ima,otch);
printf ("wes %g\n",wes);
printf ("rost %d\n",rost);
printf ("wstrech %d\n",pobed+poragen);
printf ("pobed %d\n",pobed);
printf ("poragen %d\n",poragen);
}
int operator > (boxer a) const
{float dolja1,dolja2;
dolja1=float(pobed)/(pobed + poragen);
dolja2=float(a.pobed)/(a.pobed + a.poragen);
return dolja1>dolja2;
}
};

int main()
{textbackground(1);textcolor(14);
clrscr();
boxer a,b={"Deev","Ivan","Petrovich",183,11,1,77} ;
boxer * a1=&a,* b1=&b;
cputs ("fam = ");gets(a1->fam );
cputs ("ima = ");gets(a.ima );
cputs ("otch = ");gets(a.otch );
cputs ("wes = ");scanf("%f",&a.wes);
cputs ("rost = ");scanf("%d",&a.rost);
cputs ("pobed = ");scanf("%d",&a.pobed);
cputs ("poragen = ");scanf("%d",&a.poragen);
a1->prn();
b1->prn();
if (a>b) cout << a.fam << " effektivnee " << b1->fam;
else cout << b.fam << " effektivnee " << a1->fam;
getch();
return 0;
}


Приложенные файлы

  • doc 26699148
    Размер файла: 97 kB Загрузок: 0

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