Приведем еще несколько примеров на вложенные структуры. Пример 14.6 При создании простого базы данных о сотрудниках предприятия целесообразно ввести, по крайней мере, две структуры. Одна из них будет содержать информацию о фамилии, имени и отчестве сотрудника, а вторая будет включать в себя первую с добавлением полей о профессии и возрасте. struct tag_fio { char last[100]; char first[100]; char otch[100]; }; struct tag_people { struct tag_fio fio; //вложенная структура char job[100]; int old; }; Рассмотрим способ инициализации и доступ к полям структуры people на следующем примере. Пример 14.7 Работа с вложенными структурами. int main() { struct people man = { {“Иванов”, “Иван”, “Иванович”},“Электрик”, 50 }; printf(“Ф.И.О.:%s %s %s\n”,man.fio.last,man.fio.first, man.fio.otch); printf(“Профессия : %s \n”,man.job); printf(“Возраст : %d\n”,man.old); return 0; } В данном примере показано, что для инициализации структуры внутри другой структуры следует использовать дополнительные фигурные скобки, в которых содержится информация для инициализации полей фамилии, имени и отчества сотрудника. Для того чтобы получить доступ к полям вложенной структуры, выполняется сначала обращение к ней по имени man.fio, а затем к ее полям: man.fio.last, man.fio.first и man.fio.otch. Используя данное правило, можно создавать многоуровневые вложения для эффективного хранения и извлечения данных. Пример 14.8 При работе со списками студентов целесообразно ввести, по крайней мере, две структуры. Одна из них будет содержать информацию о фамилии, имени и отчестве студента, а вторая будет включать в себя первую с добавлением полей об оценках в сессию. struct fn //описан структурный тип с именем fn, { char fam[25]; //включающий фамилию char name [15]; // имя char otch[30]; // и отчество }; struct student //описан тип student, включающий { fn namestud; //фамилию и имя студента, int age ; //его возраст, int mark [5] ; //оценки в сессию по пяти предметам }stud [30]; //определен массив stud из 30 элементов, // каждый элемент которого типа student 1.9. Массивы структурного типа Структуры могут быть объединены в массивы структур. Наглядно массив структур можно представить в виде таблицы, где столбцы таблицы представляют собой поля структуры, а строки – элементы массива структур. Объявление массива структур делается аналогично объявлению массива переменных. Общий вид объявления массива структур: Имя_структурного_типа имя_переменной [количество_элементов_массива]; Например, описана структура Struct Man { char fio[31]; // ФИО int year; // Год рождения float pay; // Оклад }; то объявление массива структур может иметь вид: Man d[3]; // массив d структур из четырех элементов Например, информация о студенте объявлена в структурной переменной student (см. пример 14.???), то для хранения информации о студенческой группе stud101, состоящей из 30 студентов, объявление массива может быть следующим struct student stud101[30]; Здесь stud101 - имя массива структур типа student, а stud101[0] - это первая структура, stud101[1] - вторая... stud101[9] - десятая структура. Обратите внимание, что нумерация элементов массива структур начинается с нулевой компоненты и заканчивается индексом, равным количеству элементов массива минус 1. Доступ к элементам массива структурного типа также осуществляется с использованием операции точка, например: stud101[4].age // доступ к полю age пятой структуры stud101 stud101[0].kurs // доступ к полю kurs первой структуры stud101 personal[5].weight // доступ к полю weight шестой структуры personal personal[3].birthday.day // доступ к полю day подструктуры birthday четвертой структуры personal и т. п. При обращении к полю структуры сначала происходит обращение к элементу массива (stud101[i]), а затем только обращение к полю структуры (stud101[i]. age). Доступ к полю элемента массива структур может быть получен через константу-указатель на массив и смещение внутри массива, например, доступ к полю элемента массива с номером i следует записать следующим образом: (*(stud101+i)).age или (stud101+i) ->age. Инициализация массива структур обычно выполняется в цикле с помощью оператора for. Пример 14.120 Date mas[15]; //массив mas структур Date // из трех полей day, month и year //ввод значений массива for(int i=0;i<15;i++) { cout<<”\nEnter day:”;cin>>mas[i].day; cout<<”\nEnter month:”;cin>>mas[i].month; cout<<”\nEnter year:”;cin>>mas[i].year; } Массив структур также может быть передан в функцию в качестве аргумента, передача массива происходит через указатель на массив. 1.10. Структурные переменные и указатели Синтаксис описания указателя: <тип>*<имя_переменной>; Таким образом, для описания указателя на структуру должен быть создан новый тип. -> – операция доступа к полям структурной переменной через указатель (минус больше). Пример 14.45 typedef struct Student { char fio[30]; char Adress[40]; int Age; int oc[4]; float sr; } MY_Student; //имя нового типа MY_Student *S3 // Указатель на структуру Примеры обращения к полям: S3->Age, S3->oc[0], S3->oc[i], S3->fio, S3-> sr Мы уже упомянули, что нельзя передавать функции структурную переменную целиком в качестве аргумента (хотя можно передавать отдельные элементы). Но существует возможность обойти это ограничение, используя в качестве аргумента указатель на структуру. Описание struct anketa *uk; говорит, что uk -указатель на структуру типаanketa.Обозначение относится к конкретному элементу структуры и означает выборку этого элемента, например: uk-> tab_nom.Поскольку ukесть указатель на структуру anketa,то к элементу tab_nomможно обращаться и так: (*uk).tab_nom, если учесть, чтоуказатель установлен на начало массива структур. Имя массива, как обычно, эквивалентно адресу его начального элемента и при добавлении к указателю на структуру или вычитании из него целого числа размер структуры учитывается автоматически Так, оператор uk=a;устанавливает указатель на первый экземпляр массива структур, а запись ++a;обеспечивает автоматический переход к следующему экземпляру. В выражении (*uk).fioскобки обязательны, так как приоритет операции выделения элемента " . "выше чем у "*". Если функции передается большая структура, то эффективнее передать указатель на эту структуру, нежели копировать ее в стек целиком. Указатель на структуру по виду ничем не отличается от указателей на обычные переменные. Формат: struct point *pp; где pp – указатель на структуру типа struct point, *pp – сама структура, (*pp).x и (*pp).y – члены структуры. Скобки (*pp).x необходимы, так как приоритет операции (.) выше приоритета операции (*). В случае отсутствия скобок *pp.x понимается как *(pp.x). Инициализация указателя на структуру выполняется так же, как и инициализация указателей других типов: struct point var1, *S1; здесь var1 – структурная переменная, *S1 – указатель на структуру. Для определения значения указателя ему нужно присвоить адрес уже сформированной структуры: S1 = &var1; Теперь возможно еще одно обращение к элементам структуры: (*S1).name. Указатели на структуры используются весьма часто, поэтому для доступа к ее полям была введена короткая форма записи. Если р – указатель на структуру, то p -> <поле структуры> позволяет обратиться к указанному полю структурной переменной. Знак -> вводится с клавиатуры с помощью двух символов: '–' (минус) и '>' (больше). Например, pp -> x; pp -> y. Операторы доступа к полям структуры (.) и (->) вместе с операторами вызова функции () и индексами массива [] занимают самое высокое положение в иерархии приоритетов операций в языке C. Указатели на структуру используются в следующих случаях: · доступ к структурам, размещенным в динамической памяти; · создание сложных структур данных – списков, деревьев; · передача структур в качестве параметров в функции. Если обращение к структуре происходит через указатель, то операцию «точка» используют после разыменования указателя (*p).kurs. Для этой конструкции предусмотрен более наглядный аналог p->kurs — операция «стрелка» — обращение к полю kurs структуры, на которую указывает указатель p. Переменные структурного типа можно создавать динамически. Для этого нужно описать указатель на структуру student *p; а затем создать экземпляр структуры с помощью операции new: p = new student; //. Структура не может содержать в качестве элемента структуру такого же типа, но может включать указатель на структуру этого типа, при условии, что в объявлении структуры указано имя типа. Это позволяет создавать связанные списки структур. Пример 14.77 Описание бинарного дерева, struct tree { int number; struct tree *left; struct tree *right; }; 1.11. Структуры и функции Структуры могут быть переданы в функцию в качестве аргументов и могут служить в качестве возвращаемого функцией результата. Существует три способа передачи структур функциям: - передача компонентов структуры по частям; - передача целиком структуры; - передача указателя на структуру. Например, в функцию передаются координаты двух точек: void showrect(struct point p1,struct point p2) { printf("Левый верхний угол прямоугольника:%d %d\n", p1.x, p1.y); printf("Правый нижний угол прямоугольника: %d %d\n", p2.x, p2.y); } При вызове такой функции ей надо передать две структуры: struct point pt1={5,5}, pt2={50,50}; showrect(pt1,pt2); Теперь рассмотрим функцию, возвращающую структуру: struct point makepoint (int x,int y) /*makepoint – формирует точку по компонентам x и y*/ { struct point temp; temp.x = x; temp.y = y; return temp; } Результат работы этой функции может быть сохранен в специальной переменной и выведен на экран: struct point buf; buf=makepoint(10,40); printf("%d %d\n",buf.x,buf.y); После выполнения этого фрагмента на экран будут выведены два числа: 10 и 40. Структура может быть параметром функции и возвращаемым функцией значением, например заголовок функции ff: struct student ff (struct student x) говорит, что формальный параметр х и возвращаемый функцией результат имeют структурный тип student. Фактический параметр функции ff структура типа student, связь между формальным и фактическим параметром устанавливается по значению, т.е. для переменной х выделяется память, куда копируется значение фактической структуры при вызове функции. Вызов функции (для приведенных выше описаний): stud1 = ff ( stud[0] ); Кроме того, в обоих случаях могут использоваться указатели на объекты структурного типа: student * ff ( student * x ) Вызов функции (для приведенных выше описаний): pstud = ff ( &stud [j] ) ; Здесь pstud – указатель на структуру, который должен быть определен до вызова ff: student *pstud; Если функция не изменяет структуру, вы можете передать структуру в функцию по имени. Например, следующая программа в примере 14.50использует функцию show_employee для вывода элементов структуры типа employee: Пример 14.50 #include <iostream.h> #include <string.h> struct employee { char name[64]; long employee_id; float salary; char phone[11]; int office_number; }; void show_employee(employee worker) { cout << "Служащий: " << worker.name << endl; cout << "Телефон: " << worker.phone << endl; cout << "Номер служащего: " << worker. employee_id << endl; cout << "Оклад: " << worker.salary << endl; cout << "Офис: " << worker.office_number << endl; } void main(void) { employee worker; // Копировать имя в строку strcpy(worker.name, "Джон Дой"); worker.employee_id = 12345; worker.salary = 25000.00; worker.office_number = 102; // Копировать номер телефона в строку strcpy(worker.phone, "555-1212"); show_employee(worker); } Как видите, программа передает переменную типа данной структуры worker в функцию show__employee по имени. Далее функция show_employee выводит элементы структуры. Однако обратите внимание, что программа теперь определяет структуру employee вне main и до функции show_employee. Поскольку функция объявляет переменную worker типа employee, определение структуры employee должно располагаться до функции. Как вы знаете, если функция изменяет параметр, вам следует передавать этот параметр в функцию с помощью адреса. Если функция изменяет элемент структуры, вы должны передавать эту структуру в функцию с помощью адреса, Для передачи переменной типа структуры с помощью адреса вы просто предваряете имя переменной оператором адреса C++ (&), как показано ниже: some_function(&worker); Внутри функции, которая изменяет один или несколько элементов, вам следует работать с указателем. Если вы используете указатель на структуру, легче всего обращаться к элементам структуры, используя следующий синтаксис: pointer_variable->member = some_value; Например, следующая программа в примере 14.51передает структуру типа employee в функцию с именем get_employee_id, которая запрашивает у пользователя идентификационный номер служащего и затем присваивает этот номер элементу структуры employee_id. Чтобы изменить элемент, функция работает с указателем на структуру: Пример 14.51 #include <iostream.h> #include <string.h> struct employee { char name[64]; long employee_id; float salary; char phone[11]; int office_number; }; void get_employee_id(employee *worker) { cout << "Введите номер служащего: "; cin >> worker->employee_id; } void main(void) { employee worker; // Копировать имя в строку strcpy(worker.name, "Джон Дой"); get_employee_id(&worker) ; cout << "Служащий: " << worker, name << endl; cout << "Номер служащего: " << worker.employee_id << endl; } Как видите, внутри main программа передает переменную worker типа структуры в функцию get_employee_id с помощью адреса. Внутри функции gel_employee_id значение, введенное пользователем, присваивается элементу employee_id с помощью следующего оператора: cin >> worker->employee_id; Если функция изменяет элемент структуры, вызвавшая программа должна передать структуру в функцию с помощью адреса. Функция, в свою очередь, использует указатель на структуру. Для обращения к элементу структуры функции следует использовать следующий формат: value = variable->member; variable->other_member = some_value; Структуры позволяют достаточно эффективно решить вопрос возврата множества значений из функции. Если функция должна вернуть несколько значений в качестве результата, то их достаточно поместить в структуру и возвращать значение указанного типа. struct Point { int x,y; }; Point GetCursorPosition() { Point cursor; … return cursor; } В этом случае вызывающая функция будет получать результат типа Point, содержащий два значения – координаты x и y курсора: void DisplayCursorInfo() { Point cursor; cursor = GetCursorPosition(); cout << cursor.x; cout << cursor.y; } 1.11. Использование синонима типа Ключевое слово typedef позволяет в программе создать синоним типа, который может использоваться для объявления переменных, параметров функций. Синоним можно создать для любого существующего типа (int, float и т. д.), в том числе для пользовательского типа – структуры или массива. Пример 14.67 Создание синонима структуры: typedef struct point { int x,y; } POINT; Идентификатор POINT представляет собой синоним типа point. С помощью синонима POINT можно объявить переменную: POINT pt1; или передать переменную в функцию: void ShowRect(POINT pt1,POINT pt2); Пример 2. Создание синонима массива: typedef float mas[4][5]; Идентификатор mas обозначает тип – двумерный массив, состоящий из четырех строк и пяти столбцов. Этот идентификатор можно использовать для объявления переменной – массива A: mas A; или для передачи массива в функцию: void FormMas(mas A,int m,int n); 1.12. Доступ к отдельному биту Если некоторые поля структуры принимают только два значения т.е. используются как флаги, то очень удобно пользоваться полями битов. Поля битов это специальный тип членов структуры, в котором определено, из скольких бит состоит каждый элемент. Основная форма объявления структуры с битовыми полями: struct имя_структуры { тип имя1: длина_в_битах; тип имя2: длина_в_битах; ... тип имяN: длина_в_битах; } Здесь тип может быть int, unsigned или signed. Длина такой структуры всегда кратна восьми. Если определить struct student { unsigned status: 1; } stud; то для переменной stud будет выделено 8 бит, а использоваться будет только один первый бит. 1.13.Типичные ошибки при разработке структур Наиболее часто встречающейся ошибкой является включение в структуру взаимозависимых данных. То есть таких членов, значения которых могут быть вычислены на основании других членов структуры. Например, неправильной структурой будет: struct Line { vec3 pt1,pt2; double length; }; В данном случае член length может быть вычислен на основании pt1 и pt2. Хранение значение length в структуре нарушает вторую рекомендацию по использованию структур. Кроме расхода памяти для хранения избыточной информации программист получает намного более сложную проблему: необходимость синхронизации данных. При каждом изменении любого из членов структуры придётся пересчитывать значение length. Более утончённые примеры ошибок: // Прямоугольник на плоскости struct Box2 { vec2 pt1, pt2, pt3, pt4; }; // Окружность в трехмерном пространстве struct CircleIn3D { Plane plane; // Плоскость, в которой лежит окружность vec3 center; double radius; }; 1.14. Примеры программирования задач на структуры Пример 14.10 Сформировать структуру, содержащую сведения о студентах. Структурный тип содержит поля: ФИО студента, адрес, возраст, оценки сессии, средний балл в сессию. Написать программу, которая вводит и выводит информацию о студенте. #include <stdio.h> main() { /* Описание шаблона структуры */ struct Student { char *fio; // Фамилия - указатель на char char Adress[40]; // Адрес - строка int Age; // Возраст - целое int oc[4]; // Оценки - целочис. массив float sr; // Средний балл - вещественное } ; struct Student S; // Описание структурной переменной S int i; float sr; S.fio="Петушков"; //Присваивание полю значения printf("Введите адрес студента %sa ",S.fio); gets(S.Adress); //Ввод значения поля S.Age=1987; //Присваивание полю значения S.oc[0]=3; S.oc[1]=5; S.oc[2]=4; S.oc[3]= S.oc[2]; sr=0; //Вычисление среднего балла for(i=0;i<=3;i++) sr=sr+S.oc[i]; sr=sr/4; S.sr=sr; //Присваивание полю вычисленного значения /* Вывод полей записи S */ printf(" Средний балл студента %sа", S.fio); printf(" %d года рождения,\n проживающего по адресу: %s,", S.Age,S.Adress); printf(" равен %5.2f\n", S.sr); fflush(stdin); getchar(); return(0); } Из примера видно, что имя поля структуры и имя переменной могут совпадать, поскольку у них разные области видимости. Более того, поля разных структур могут совпадать. Но делать так не рекомендуется поскольку себя запутать легче, чем компилятор. Вид экрана после выполнения приведенной программы: Введите адрес студента Петушковa ул. Солнечная, д.1, кв. 4 Средний балл студента Петушкова 1987 года рождения, проживающего по адресу: ул. Солнечная, д.1, кв. 4, равен 4.00 Здесь красным цветом выделен текст, который пользователь набрал на клавиатуре. Пример 14.5 Составить инвентарный перечень книг, в котором для каждой книги необходимо указывать ее наименование, автора и год издания. Причем количество книг может быть разным, но будем полгать, что не более 100. В этом случае программу ввода и хранения информации по книгам можно записать в виде: #include struct book { char title[100]; //наименование книги char author[100]; //автор int year; //год издания }; int main() { int cnt_book = 0, ch; struct book lib[100]; // массив структур типа book do { printf(“Введите наименование книги: “); scanf(“%s”,lib[cnt_book].title); printf(“Введите автора книги: “); scanf(“%s”,lib[cnt_book].author); printf(“Введите год издания книги: “); scanf(“%d”,&lib.year); printf(“Нажмите q для завершения ввода: ”); cnt_book++; } while(scanf(“%d”,ch) == 1 && cnt_book < 100); return 0; } Данный пример показывает удобство хранения информации по книгам. Тот же алгоритм в общем случае можно реализовать и без структуры, но тогда пришлось бы использовать два двумерных массива символов и один одномерный массив для хранения года издания. Несмотря на то, что формально такая запись была бы корректной с точки зрения языка С++, но менее удобна в обращении. Пример 14.20 Поиск в массиве структур, вводимых с клавиатуры. Сформировать структуру, имеющую поля ФИО, год рождения, оклад. Вывести фамилии сотрудников, имеющих оклад выше среднего Текст программы /* Фамилии сотрудников, имеющих оклад выше среднего */ #include <stdio.h> #include <string.h> #include <iostream.h> void main() { const int lfio=20, lpay=5, lo=7, //длины полей фио, г.рожд., оклада ldb=10; struct Man { char fio[lfio+1]; // фио int year; // год рожд. float pay; // оклад }; Man db[ldb]; // массив структур int i, n; float s; // Средний оклад puts("Число записей?(1<n<=10)"); cin>>n; /*Ввод массива записей */ for(i=0; i<n; i++) { puts("Фамилия? "); cin>>db[i].fio; puts("Год рождения? "); cin>>db[i].year; puts("Оклад? "); cin>>db[i].pay; } /* Вывод массива записей в форме таблицы*/ puts(" Список сотрудников"); puts("┌──────────┬───┬────┐"); puts("│ ФИО │ г.р.│Оклад │"); puts("├──────────┼───┼────┤"); for(i=0; i<n; i++) printf("|%-20s|% 5d | % 7.2f |\n", db[i].fio, db[i].year, db[i].pay); puts("└──────────┴───┴────┘"); puts("Фамилии сотрудников, имеющих оклад выше среднего"); //Вычисление среднего оклада s=0; for(i=0; i<n; i++) s+=db[i].pay; // s=s+db[i].pay; s/=n; //s=s/n; // Определение и вывод фамилий for(i=0; i<n; i++) if(db[i].pay>s) printf("%-s\n", db[i].fio); fflush(stdin); getchar(); } Пример 14.10 Сформировать структуру, содержащую сведения о студентах. Структурный тип содержит поля: ФИО студента, курс, возраст. Написать программу, которая вводит и выводит информацию о студенте. Пример программы. #include <stdio.h> // определение структуры struct student { char name[30]; int kurs; int age; }; void main() { // объявление переменных stud1 и stud2 типа struct student struct student stud1, stud2; printf("Введите имя:"); // ввод имени gets(stud1.name); printf("Введите возраст:"); // ввод возраста scanf("%d", &stud1.age); printf("Введите номер курса:"); // ввод номера курса scanf("%d", &stud1.kurs); // присваивание stud2=stud1 возможно, так как один и тот же шаблон stud2=stud1; // Вывод printf("Студент %sn", stud2.name); printf("Курс %dn", stud2.kurs); printf("Возраст %dn", stud2.age); } Заметьте, что когда мы делаем вызов scanf("%d", &stud1.age); и scanf("%d", &stud1.kurs); мы ставим знак & перед именем структуры, а не перед именем поля (элемента структуры). Пример 14.11 Модифицировать программу примера 14.10 так, чтобы она обеспечивала ввод, вывод и хранение информации о всех студентах группы. Будем считать, что количество студентов в группе не превышает 30 человек. Текст программы #include <stdio.h> // определение структуры struct student { char name[30]; int kurs; int age; }; void main() { // объявление массива на 30 структур struct student stud[30]; int i, n; printf("Количество студентов:"); // ввод n (число студентов) scanf("%d", &n); for(i=0;i<n;i++) { printf("Введите имя:"); // ввод имени scanf("%s", stud[i].name); printf("Введите возраст:"); // ввод возраста scanf("%d", &stud[i].age); printf("Введите номер курса:"); // ввод номера курса scanf("%d", &stud[i].kurs); } // Вывод for(i=0;i<n;i++) { printf("Студент %sn", stud[i].name); printf("Курс %dn", stud[i].kurs); printf("Возраст %dn", stud[i].age); } } Пример 14.11 Сформировать структуру, содержащую сведения о вкладах. Структурный тип содержит поля: ФИО вкладчика, номер счета, тип вклада (срочный, депозит, обычный), сумма вклада, дата последнего обращения к вкладу. Написать программу, которая выводит информацию о всех вкладчиках банка в алфавитном порядке имен и о вкладчиках банка, имеющих наибольший размер вклада. Текст программы: #include <string.h> #include <stdio.h> # include <iomanip.h> struct Banc { char name[20]; // фамилия вкладчика int sch; // номер счета char tip[10]; // тип вклада float sum; // сумма вклада char data[10]; // дата последнего обращения }; void main(void) { Banc b[10],b_new[10]; int kol; cout<<"Введите количество вкладчиков >"; cin>>kol; for(int i=0; i<kol; i++) { cout<<"Имя вкладчика :"; cin>>setw(15)>>b[i].name; cout<<"Номер счета :"; cin>>b[i].sch; cout<<"Тип вклада :"; cin>>b[i].tip; cout<<"Сумма вклада :"; cin>>setw(10)>>b[i].sum; cout<<"Дата последнего обращения к вкладу :"; cin>>setw(10)>>b[i].data; cout<<endl; } /* Вывод содержимого массива вкладчиков в алфавитном порядке*/ for(int i=0; i<kol; i++) { Banc min=b[i]; int num=i; for(int j=i; j<kol; j++) if(strcmp(banc[j].name,min.name)<0) { min=b[j]; num=j; } b[num]=b[i]; b[i]=min; } cout<<"Имя вкладчика”<<”Номер счета”<<”Тип вклада”; cout<<”Сумма вклада”<<”Дата последнего обращения к вкладу”<<endl; for(int i=0; i<kol; i++) { cout<<setw(15)<<b[i].name<<setw(13)<<b[i].sch<<setw(11)<<b[i].tip; cout<<setw(13)<<b[i].sum<<setw(16)<<b[i].data<<endl; } // Формирование массива вкладчиков, имеющих наибольший размер вклада float max=0.0; int kol_new=0; for(int i=0; i<kol; i++) // Определение значения наибольшего вклада if(b[i].sum>max) max=b[i].sum; cout<<”Наибольшая сумма вклада”<<max<<endl; // Массив вкладчиков с наибольшей суммой вклада for(int i=0; i<kol; i++) if(b[i].sum==max) b_new[kol_new++]=b[i]; cout<<”Имя вкладчика”<<”Номер счета”<<”Тип вклада”; cout<<”Сумма вклада”<<”Дата последнего обращения к вкладу”<<endl; for( i=0; i<kol_new; i++) { cout<<setw(15)<<b_new[i].name<<setw(13)<<b_new[i].sch<< setw(11)<< b_new[i].tip; cout<<setw(13)<<b_new[i].sum<<setw(16)<<b_new[i].data<<endl; } } Пример 14.12 Сформировать структуру FLAT, содержащую сведения о квартире. Структурный тип содержит поля: адрес, количество комнат, общая площадь, стоимость квадратного метра. Написать программу, которая осуществляет поиск квартиры в пределах заданной суммы. Текст программы на языке С++: #include<iostream.h> #include<conio.h> #include<string.h> #include<stdlib.h> struct flat { char adres[30]; int kolvo; long int stoimost; double ploshad; }; int main() { const n=3; int i,j; flat s[n],t; cout.setf(ios::left); clrscr(); for(i=0;i<=n-1;i++) { cout<<" Vvedite adress\n"; cin>>s[i].adres; cout<<" Vvedite kolichestvo komnat\n"; cin>>s[i].kolvo; cout<<" Vvedite ploshad\n"; cin>>s[i].ploshad; cout<<" Vvedite stoimost\n"; cin>>s[i].stoimost; cout<<"\n"; } cout<<"\n Adress Kolichestvo_komnat Ploshad Stoimost\n\n"; for(i=0;i<=n-1;i++) { cout.width(20);cout<<s[i].adres; cout.width(20);cout<<s[i].kolvo; cout.width(15);cout<<s[i].ploshad; cout.width(15);cout<<s[i].stoimost<<"\n"; } int stoimost; cout<<"\n\n Vvedute stoimost kvartirbl za kv metr\n"; cout<<"\n"; cin>>stoimost; for(i=0;i<=n-1;i++) if(s[i].stoimost<=stoimost) { cout.width(20);cout<<s[i].adres; cout.width(20);cout<<s[i].kolvo; cout.width(20);cout<<s[i].ploshad; cout.width(20);cout<<s[i].stoimost<<"\n"; } getch(); clrscr(); } Результат тестирования программы:  Пример 14.13 Сформировать структуру FLAT, содержащую сведения о квартире. Структурный тип содержит поля: адрес, количество комнат, общая площадь, стоимость квадратного метра. Написать программу, которая осуществляет поиск двухкомнатной квартиры в пределах заданной суммы. Текст программы на языке С++: #include <iostream.h> #include <string.h> #include <conio.h> const int L=31; struct flat { char adr [L]; int kk; int plo; int skm; }; struct gruppa { char adr [L]; int kk; int plo; int skm; }; void input(flat x[ ],int n); void output(flat x[ ],int n); void outputgr(gruppa y[ ],int n); void input(flat x[ ],int n) {int i; for (i=0;i<n;i++) { cout<<"adress"; cin>>x[i].adr; cout<<"kol komnat"; cin>>x[i].kk; cout<<"obch plochad"; cin>>x[i].plo; cout<<"stoim kv metra"; cin>>x[i].skm; cout<<endl; } } void output(flat x[ ],int n) { int i; for (i=0;i<n;i++) cout << i + 1 <<" "<< x[i].adr <<" "<< x[i].kk <<" "<< x[i].plo <<" "<< x[i].skm << endl; } void outputgr(gruppa y[ ],int n) { int i; for (i=0;i<n;i++) cout << i + 1 <<" "<< y[i].adr <<" "<< y[i].kk <<" "<< y[i].plo <<" "<< y[i].skm << endl; } void main() { clrscr(); const int N=100; flat a[N]; gruppa b[N]; for (int i = 0; i < N; i++) { a[i].adr[0] = NULL; a[i].kk = 0; a[i].plo = 0; a[i].skm = 0; b[i].adr[0] = NULL; b[i].kk = 0; b[i].plo = 0; b[i].skm = 0; } int i, k, s, m, v; cout<<"kol kvartir"; cin>>m; input(a,m); cout<<"ishodn massiv"; output(a,m); cout<<"vvedite stoim"; cin>>s; k=0; for(i=0;i<m;i++) { v=a[i].plo*a[i].skm; if((a[i].kk == 2) && (v<=s)) { strcpy (b[k].adr,a[i].adr); k++; } } cout<<"perechen"; outputgr(b,k); getch(); } Пример 14.14 Дан массив записи, содержащие сведения о веществах: указывается название вещества, его удельный вес и проводимость. Найти название и удельные веса веществ заданной проводимости и напечатать их в порядке убывания удельного веса. Текст программы на языке С++: #include<stdlib.h> #include<string.h> #include<iostream.h> #include<conio.h> #include<stdio.h> struct materials{ char caption[20]; int mass; int res; }p[50],result[50],tmp; int n,res_n,resist; void search(int resistance,int count){ res_n=-1; for (int j=0;j<count;j++) if (p[j].res==resistance) { res_n++; result[res_n]=p[j]; } } void sort(){ for (int i = 0; i <= res_n-1; i++) { int min = i; for (int j = i+1; j <= res_n; j++) if (result[j].mass <= result[min].mass) min = j; tmp=result[i]; result[i]=result[min]; result[min]=tmp; } } void showresults() { for (int i=0;i<=res_n;i++) cout<<result[i].caption<<" "<<result[i].res<<" "<<result[i].mass<<endl; getch(); } void main(){ clrscr(); int n; printf("Enter n:"); cin>>n; for (int i=0;i<n;i++) { cout<<"enrter name, resistance and mass of "<<i+1<<" element: \n"; cin>>p[i].caption>>p[i].res>>p[i].mass; } printf("Enter resistance:"); scanf("%i",&resist); search(resist,n); sort(); showresults(); } Тестирование программы  Пример 14.15 Задано n комплексных чисел, найти число наибольшего модуля. Текст программы #include <iostream> #include <math.h> using namespace std; int main() { struct complex { float x; //действительная часть float y; //мнимая часть }; //Объявление массива комплексных чисел complex p[100]; int i,n,nmax; float max; cout<<"n="; cin>>n; for(i=0;i<n;i++) { cout<<"Vvedite complex chislo\n"; //ввод действительной части i-го комплексного числа cin>>p[i].x; //ввод мнимой част i-го комплексного числа cin>>p[i].y; cout<<p[i].x<<"+"<<p[i].y<<"i"<<endl; } max=pow(p[0].x*p[0].x+p[0].y*p[0].y,0.5);nmax=0; for(i=1;i<n;i++) if (pow(p[i].x*p[i].x+p[i].y*p[i].y,0.5)>max) { max=pow(p[i].x*p[i].x+p[i].y*p[i].y,0.5);nmax=i; } cout<<"Nomer maxsimalnogo modulya "<<nmax<< "\nEgo velichina "<<max<<endl; return 0;} Результаты n=5 Vvedite complex chislo 1 3 1+3i Vvedite complex chislo 5 0.2 5+0.2i Vvedite complex chislo -0.2 3 -0.2+3i Vvedite complex chislo 4.2 0.01 4.2+0.01i Vvedite complex chislo -6.2 0.45 -6.2+0.45i Nomer maxsimalnogo modulya 4 Ego velichina 6.21631 Press any key to continue Пример 14.16 Динамические структуры Решим предыдущую задачу с использованием динамических структур. Текст 1 #include <iostream> #include <math.h> #include <malloc.h> using namespace std; int main() { struct complex { float x; float y; }; complex *p; int i,n,nmax; float max; cout<<"n="; cin>>n; //выделяется память под массив p p=(complex *)calloc(n,sizeof(complex)); for(i=0;i<n;i++) { cout<<"Vvedite complex chislo\n"; cin>>p[i].x; cin>>p[i].y; cout<<p[i].x<<"+"<<p[i].y<<"i"<<endl; } max=pow(p[0].x*p[0].x+p[0].y*p[0].y,0.5);nmax=0; for(i=1;i<n;i++) if (pow(p[i].x*p[i].x+p[i].y*p[i].y,0.5)>max) { max=pow(p[i].x*p[i].x+p[i].y*p[i].y,0.5);nmax=i; } cout<<"Nomer maxsimalnogo modulya "<<nmax<<"\nEgo velichina "<<max<<endl; free(p); return 0; } Текст 2 #include <iostream> #include <math.h> #include <malloc.h> using namespace std; int main() { struct complex { float x; float y; }; complex *p; int i,n,nmax; float max; cout<<"n="; cin>>n; p=new complex [n]; for(i=0;i<n;i++) { cout<<"Vvedite complex chislo\n"; //запись (p+i)->x аналогична записи p[i].x cin>>(p+i)->x; cin>>(p+i)->y; cout<<(p+i)->x<<"+"<<(p+i)->y<<"i"<<endl; } max=pow(p->x*p->x+p->y*p->y,0.5); nmax=0; for(i=1;i<n;i++) if (pow((p+i)->x*(p+i)->x+(p+i)->y*(p+i)->y,0.5)>max) { max=pow((p+i)->x*(p+i)->x+(p+i)->y*(p+i)->y,0.5);nmax=i; } cout<<"Nomer maxsimalnogo modulya "<<nmax<< "\nEgo velichina "<<max<<endl; delete [] p; return 0; } Пример 14.44 Программа, реализующая ввод списка студентов и вывод информации о студенте по его номеру в списке. Ввод информации о студенте реализован в виде отдельной функции. #include<stdio.h> const int n=3; typedef struct { int num; char fam[20]; char name[15]; }student; student mas[n]; student *ptr=&mas[0]; void vvod(student *p) { scanf("%d",&p->num); scanf("%s",p->fam); scanf("%s",p->name); } void main () { int i,d; for(i=0;i<n;i++) vvod(ptr+i); рrint("Введите номер студента в списке\п"); scanf("%d",&d); for(i=0;i<n;i++) if (mas[i].num==d) printf(" Студент %s %s\n",mas[i].fam,mas[i].name); } Процедуре vvod передается значение указателя на элемент массива mas, который является структурой. В приведенной программе использованы оба способа обращения к элементу структуры (с использованием указателя и без него). Пример 14.56 Программа, реализующая ввод списка студентов и вывод информации о студенте по его номеру в списке. Ввод информации о студенте реализован в виде отдельной функции. #include<stdio.h> const int n=3; typedef struct { int num; char fam[20]; char name[15]; }student; student mas[n]; student *ptr=&mas[0]; void vvod(student *p) { scanf("%d",&p->num); scanf("%s",p->fam); scanf("%s",p->name); } void main () { int i,d; for(i=0;i<n;i++) vvod(ptr+i); рrint("Введите номер студента в списке\п"); scanf("%d",&d); for(i=0;i<n;i++) if (mas[i].num==d) printf(" Студент %s %s\n",mas[i].fam,mas[i].name); } Процедуре vvod передается значение указателя на элемент массива mas, который является структурой. В приведенной программе использованы оба способа обращения к элементу структуры (с использованием указателя и без него). Пример 14.57 Структуры, как и обычные типы данных, можно передавать функции в качестве аргумента. Следующий пример демонстрирует работу функции отображения полей структуры на экран. Передача структур через аргументы функции. #include struct tag_people { char name[100]; char job[100]; int old; }; void show_struct(struct tag_people man); int main() { struct tag_people person = {“Иванов”,”Электрик”,30}; show_struct(person); return 0; } void show_struct(struct tag_people man) { printf(“Имя: %s\n”,man.name); printf(“Профессия: %s\n”,man.job); printf(“Возраст: %d\n”,man.old); } В приведенном примере используется функция с именем show_struct, которая имеет тип аргумента struct tag_people и переменную-структуру man. При передаче структуры функции создается ее копия, которая доступная в теле функции show_struct под именем man. Следовательно, любые изменения полей структуры с именем man никак не повлияют на содержание структуры с именем person. Пример 14.58 Иногда необходимо выполнять изменение полей структуры функции и возвращать измененные данные вызывающей программе. Для этого можно задать функцию, которая будет возвращать структуру, как показано в листинге следующей программы. //Функции, принимающие и возвращающие структуру. #include struct tag_people { char name[100]; char job[100]; int old; }; void show_struct(struct tag_people man); struct tag_people get_struct(); int main() { struct tag_people person; person = get_struct(); show_struct(person); return 0; } void show_struct(struct tag_people man) { printf(“Имя: %s\n”,man.name); printf(“Профессия: %s\n”,man.job); printf(“Возраст: %d\n”,man.old); } struct tag_people get_struct() { struct tag_people man; scanf(“%s”,man.name); scanf(“%s”,man.job); scanf(“%d”,man.old); return man; } В данном примере используется функция get_struct(), которая инициализирует структуру с именем man, запрашивает у пользователя ввод значений ее полей и возвращает введенную информацию главной программе. В результате выполнения оператора присваивания структуры man структуре person, происходит копирование информации соответствующих полей и автоматическое удаление структуры man. Пример 14.59 Функциям в качестве аргумента можно также передавать массивы структур. Для этого используется следующее определение: void show_struct(struct people mans[], int size); Здесь size – число элементов массива, которое необходимо для корректного считывания информации массива mans. Следующий пример показывает принцип работы с массивами структур. //Передача массива структур функции #include #define N 2 struct tag_people { char name[100]; char job[100]; int old; }; void show_struct(struct people mans[], int size); int main() { struct people persons[N] = { { “Иванов”, «Электрик», 35 }, { “Петров”, «Преподаватель», 50 }, }; show_struct(persons, N); } void show_struct(struct people mans[], int size) { for(int i = 0;i < size;i++) { printf(“Имя: %s\n”,mans[i].name); printf(“Профессия: %s\n”,mans[i].job); printf(“Возраст: %d\n”,mans[i].old); } } При передаче аргумента persons выполняется копирование информации в массив mans и указывается дополнительный параметр size, для определения числа элементов массива mans. Затем в функции show_struct() реализуется цикл, в котором выполняется отображение информации массива структуры на экран монитора. Пример 14.80 Работа со структурой magazin Привести ????? // объявления и инициализация magazin *pm, m = ("Nature", 2000, 4}; // доступ к элементам cout « m.tittle « " " « m.number « endl; // одна структура в свободной памяти *pm = new magazin; *pm = m; pm->tittle = "Nature"; delete pm; // массив структур в свободной памяти pm = new magazin[10]; pm[0].tittle = "Природа"; delete[] pm; Пример 14.81 Программа, в которой массив точек формируется и выводится на экран с помощью функций. #include <stdio.h> #define N 5 struct point { int x,y; }; void form_mas(struct point* mas, int n) { printf("Enter koordinates!\n"); for(int i=0;i<n;i++) { printf("x→"); scanf("%d",&mas[i].x); printf("y→"); scanf("%d",&mas[i].y); } } void print_mas(struct point* mas, int n) { printf(" x y\n"); for(int i=0; i<n; i++) printf("%4d %6d\n",(mas+i)→x,(mas+i)→y); } int main() { struct point Points[N]; form_mas(Points,N); print_mas(Points,N); return 0; } Функция form_mas() заполняет массив точек, который передан в функцию через указатель mas. Параметр функции n определяет количество элементов массива. Доступ к элементу массива – через операцию . (точка). Выражение &mas[i].x вычисляет адрес элемента структуры mas[i].x, так как операция & имеет более низкий приоритет, чем операции [] и · (точка). Функция print_mas() выводит массив на экран. Передача массива в функцию происходит также через указатель mas. Параметр n – количество элементов массива. Доступ к элементу массива – через операцию → (стрелка). 2. ЗАДАНИЕ 2.1. Изучить теоретические сведения. 2.1.1. Изучить поняте структура. 2.1.2. Изучить порядок описания структуры. 2.1.3. Изучить порядок объявления структуры. 2.1.4. Изучить понятие массива структур. 2.1.5. Изучить понятие вложенной структуры. 2.1.6. Изучить инициализацию переменных структурного типа. 2.1.7. Изучить операции со структурами. 2.1.8. Изучить порядок доступа к значениям полей структурного типа. 2.1.9. Изучить понятие указателя на структуру. 2.1.10. Изучить порядок передачи структур в функцию. 2.1.11. Изучить порядок создание синонима структуры. 2.2. Разобрать и выполнить примеры к данной лабораторной работе. 2.3. Написать и отладить семь программ на языке С++. 2.4. Задания для выполнения на занятиях 2.4.1. Задание 1. Вычисление с использованием структур 2.4.1.1. Условие задания Создать массив структур, содержащий информацию согласно варианту индивидуального задания. Выполнить задание и вывести на экран полученный результат. Таблица 14.1 № | Структура данных и задание | | Структура "Автомобиль" имеет поля: марка; серийный номер; регистрационный номер; год выпуска. Вывести все сведения об автомобилях, имеющих дату выше заданной (новые автомобили). | | Структура "Сотрудник" имеет поля: фамилия, имя, отчество; должность; год рождения; заработная плата. Вывести все сведения о сотрудниках, имеющих заработную плату выше средней. | | Структура "Государство" имеет поля: название; столица; численность населения; занимаемая площадь. Вывести все сведения о государствах, в столицах которых проживает более 5 млн жителей. | | Структура "Человек" имеет поля: фамилия, имя, отчество; домашний адрес; номер телефона; возраст. Вывести все сведения о людях, имеющих возраст больше заданного. | | Структура "Человек" имеет поля: фамилия, имя, отчество; год рождения; рост; вес. Вывести все сведения о людях, имеющих рост выше среднего. | | Структура "Школьник" имеет поля: фамилия, имя, отчество; класс; номер телефона; оценки по предметам (математика, физика, русский язык, литература). Вывести все сведения о школьниках, имеющих 2 хотя бы по одному предмету. | | Структура "Студент" имеет поля: фамилия, имя, отчество; домашний адрес; группа; оценки по 5 предмета сессии. Вывести все сведения о студентах имеющих 2 хотя бы по одному предмету. | | Структура "Покупатель" имеет поля: фамилия, имя, отчество; домашний адрес; номер телефона; номер кредитной карточки. Вывести все сведения об покупателе с заданной фамилией. | | Структура "Пациент" имеет поля: фамилия, имя, отчество; домашний адрес; номер медицинской карты; номер страхового полиса, дата рождения. Вывести все сведения о пациентах, имеющих дату выше заданной. | | Структура "Информация" имеет поля: носитель; объем; название; автор. Вывести все сведения о произведениях конкретного автора. | | Структура "DVD-диск" имеет поля: название фильма; режиссер; продолжительность; цена. Вывести все сведения о дисках, имеющих цену ниже средней. | | Структура "DVD- диск" имеет поля: название; режиссер; продолжительность; цена. Вывести все сведения о фильмах конкретного режиссера. | | Структура "Спортивная команда" имеет поля: название; город; количество игроков; количество набранных очков. Вывести все сведения о лидирющих (трех) командах | | Структура "Стадион" имеет поля: название; адрес; вместимо сть;год постройки; виды спорта. Вывести все сведения о стадионах, имеющих дату постройки ниже заданной (старые стадионы). | | Структура "Автомобиль" имеет поля: марка; год выпуска; мощность двигателя; цена; цвет. Вывести все сведения об автомобилях, имеющих цену выше средней. | | Структура "Владелец автомобиля" имеет поля: фамилия, имя, отчество; номер автомобиля; телефон; номер техпаспорта, дата выдачи прав. Вывести все сведения о владельцах автомобилей, имеющих дату сдачи на права выше заданной. | | Структура "Фильм" имеет поля: название; режиссер; год выпуска; стоимость. Вывести все сведения офильмах, стоимость которых выше средней. | | Структура "Книга" имеет поля: название; автор; год издания; количество страниц. Вывести все сведения о книгах, имеющих год издания выше заданного. | | Структура "Фильм" имеет поля: название; режиссер; страна; год выпуска; приносимая прибыль. Вывести все сведения о фильмах, которые приносят прибыль выше средней. | | Структура "Государство" имеет поля: название; государственный язык; денежная единица; численность населения; столица. Вывести все сведения о государствах с численностью населения больше заданной. | | Структура "Автомобиль" имеет поля: марка; серийный номер; регистрационный номер; год выпуска. Вывести все сведения об автомобилях заданной марки. | | Структура "Владелец автомобиля" имеет поля: фамилия, имя, отчество; номер автомобиля; номер техпаспорта; год выпуска;отделение регистрации ГАИ. Вывести все сведения об автомобилях, имеющих год выпуска меньше заданного (старые автомобили). | | Структура "Стадион": имеет поля: название; год постройки; вместимость; количество площадок; виды спорта. Вывести все сведения о стадионах, имющих вместимость меньше заданной. | | Структура "Студент" имеет поля: фамилия, имя, отчество; номер телефона; группа; оценки по 5 предметам сессии. Вывести все сведения о студентах, имеющих 3 только по одному из предметов. | | Структура "Студент" имеет поля: фамилия, имя, отчество; дата рождения; домашний адрес; оценки по 5 предметам сессии. Вывести все сведения о студентах, имеющих 5 по всем предметам. | | Структура "Студент" имеет поля: фамилия, имя, отчество; домашний адрес; группа; оценки по 5 предметам сессии. Вывести все сведения о студентах, имеющих 4 или 5 по предметам. | | Структура "Книга" имеет поля: название; автор; год издания; количество страниц. Вывести все сведения о книгах, имеющих год издания выше заданного. | | Структура "Автомобиль" имеет поля: марка; серийный номер; регистрационный номер; год выпуска. Вывести все сведения об автомобилях, имеющих дату ниже заданной (старые автомобили). | | Структура "Абитуриент" имеет поля: фамилия, имя, отчество;год рождения;оценки вступительных экзаменов (3);средний балл аттестата. Вывести все сведения об абитуриентах, имеющих средний балл выше заданного. | | Структура "Студент" имеет поля: фамилия, имя, отчество; домашний адрес; группа; оценки по 5 предметам сессии. Вывести все сведения о студентах, имеющих 5 по всем предметам. | 2.4.1.2. Пример для варианта 30 Структура "Студент" имеет поля: фамилия, имя, отчество; домашний адрес; группа; оценки по 5 предметам сессии. Вывести все сведения о студентах, имеющих 5 по всем предметам. 2.4.1.3. Программа //Лабораторная работа № 14 //Задание № 1 //Выполнил ст. Иванов А.А. //20 мая 2012 г. #include <iostream.h> #include <string.h> #include <conio.h> // подключение библиотеки функций ввода-вывода int main () { struct strc // Объявление структуры strc { char fam[20]; char im[15]; char otch[20]; char adres[40]; char ngr[9]; int otcen[5]; double sb; } mstud[100]; // Объявление массива структур mstud int nst, i, j; cout < |