Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Обращение к полям структуры и оператор «точка»Содержание книги
Поиск на нашем сайте Тема 12. СТРУКТУРЫ Зачем нужны структуры? Одна из задач любого языка программирования заключается в предоставлении программисту инструментов, позволяющих представлять данные в удобной для работы форме. Структуры являются одним из таких инструментов, который хорошо подходит в ряде случаев, когда сложно обойтись только переменными и массивами. Некоторые языки программирования, например, Паскаль, применительно к структурам используют термин запись (record), тем не менее, принципы работы с записями и структурами одинаковы. Предположим, что перед нами стоит задача реализовать базу данных, предназначенную для работы с информацией о сотрудниках некоторой фирмы. С каждым сотрудником связан набор разнотипных данных, таких как имя (name), возраст (age), зарплата (salary) и др. Чтобы решить эту задачу, можно описать несколько массивов, каждый из которых будет отвечать за свою характеристику сотрудника:
char name[][20]; float salary[]; int age[];
Однако такой способ совсем неудобен при большом количестве характеристик товара и, следовательно, большом количестве массивов. Представьте себе, как будет выглядеть сортировка десяти массивов, если понадобится упорядочить сотрудников по возрасту; очевидно, что сортировать массивы придется синхронно, чтобы элементы с одинаковыми индексами относились к одному человеку.
Более естественным способом организации данных является представление всех сотрудников в виде массива записей, каждая из которых содержит всю необходимую информацию о сотруднике. Другими словами, вместо трех одномерных массивов следует воспользоваться одним массивом, где каждый из элементов является записью с тремя полями. Структура как раз и представляет собой запись, состоящую из разнотипных данных, относящихся к одному объекту.
Создание структуры
Рассмотрим, как описать структуру для представления сотрудника:
struct Worker { stirng name; float salary; int age; };
В данном фрагменте кода struct – это ключевое слово, информирующее о начале описания структуры. Далее указывается имя структуры Worker, а затем в фигурных скобках перечисляются переменные, входящие в структуру, и указывается их тип; применительно к структурам такие переменные называются полями. Описав структуру Worker, мы фактически определили новый составной тип данных, называемый Worker. После его определения можно описать переменную этого типа:
Worker director;
При описании также можно задать значения полей структуры, перечислив эти значения в том порядке, который указан при описании структуры:
Worker director = {"Андрей", 34, 1000.6};
Заметим, что при описании структуры Worker память под нее не выделяется; это происходит только при описании переменной director типа Worker, которая занимает столько места, сколько ее поля все вместе. Проверим это с помощью оператора sizeof:
cout << "Тип\tРазмер\n"); cout << "----------------------\n"; cout << 20*sizeof(char) << endl; cout << sizeof(int) << endl; cout << sizeof(float) << endl; cout << "----------------------\n"); cout << sizeof(Worker) << endl;
Строка длины 20 занимает 20 байт; целое и вещественное числа занимают по 4 байта; итого получается 28 байт:
Обратите внимание на то, что во избежание путаницы имена структур следует начинать с заглавной буквы, а имена переменных – со строчной. Такое соглашение позволяет к тому же объявлять переменные и структуры с «почти» одинаковыми именами, поскольку язык Си различает регистр букв:
Worker worker;
Обращение к полям структуры и оператор «точка» Обратиться к значению, которое хранит переменная, можно, просто написав ее имя. Структура является не просто переменной, а в некотором смысле составной переменной, поэтому для обращения к данным, которые хранит структура необходимо указать ее имя и имя поля. Для этого существует специальный оператор «точка», который разделяет имена структуры и ее полей. Рассмотрим пример использования этого оператора для того, чтобы присвоить значения элементам структуры:
Worker manager;
manager.name = "Сергей"; manager.salary = 1000.55; manager.age = 33;
Обратите внимание на то, что поля manager.salary и manager.age являются обычными переменными, и работать с ними нужно, как с переменными. Поле manager.name является строкой.
Вложенные структуры Пусть для каждого сотрудника требуется хранить его адрес, который состоит из нескольких полей: улица (street), номер дома (house) и номер квартиры (flat). В таком случае адрес разумно также представить в виде структуры
struct Address { char street[50]; int house; int flat; };
и одним из полей структуры Worker сделать структуру Address
struct Worker { char name[20]; int age; float salary; Address address; };
Обращение к полям вложенной структуры Address происходит через поля структуры Worker; например, задать адрес сотрудника и вывести его на экран можно так:
strcpy(manager.address.street, "Ленина"); manager.address.house = 10; manager.address.flat = 7;
printf("Улица: %s\n", manager.address.street); printf("Дом: %d\n", manager.addrress.house); printf("Квартира: %d\n",manager.address.flat);
Массив структур Как мы отмечали в самом начале, важной причиной введения структур является желание работать со списком записей. Такой список представляется в виде массива структур. Аналогично обычному массиву, где элементами являются числа или символы, в массиве структур элементами являются структуры. Рассмотрим, как объявляется массив структур, в котором будет храниться информация о сотрудниках.
#define SIZE 5 Worker workers[SIZE];
Значения полям элементов массива структур можно задать при его объявлении, перечислив поля в том порядке, который указан при объявлении структуры:
Worker workers[SIZE] = { {"Андрей", 30, 5000}, {"Светлана", 51, 2000}, {"Дмитрий", 45, 3000}, {"Анна", 28, 4000}, {"Василий", 37, 1000} };
а можно и после объявления:
strcpy(workers[0].name, "Игорь"); workers[0].age = 53; workers[0].salary = 2500;
strcpy(workers[1].name, "Демьян"); workers[1].age = 57; workers[1].salary = 1500;
Причем грамотная группировка элементов выглядит именно так, как показано выше, а не так:
//Неправильная группировка! strcpy(workers[0].name, "Игорь"); strcpy(workers[1].name, "Демьян");
workers[0].age = 53; workers[1].age = 57;
workers[0].salary = 2500; workers[1].salary = 1500;
поскольку структура предполагает группировку разнотипных данных, относящихся к одному объекту, а не группировку данных согласно их типу.
Сортировка массива структур Алгоритмы сортировки применимы к любым объектам, в том числе и к структурам. Рассмотрим особенности, которые нужно учитывать при сортировке массива структур. Во-первых, структуры сортируются по какому-то полю, поэтому сравнение нужно указывать это поле:
if (workers[j] .age < workers[j+1] .age) { … }
Во-вторых, в отличие от строк, структуры можно присваивать друг другу напрямую, поэтому перестановка двух структур выглядит следующим образом:
Worker temp = workers[j]; workers[j] = workers[j+1]; workers[j+1] = temp;
Алгоритм пузырьковой сортировки массива структур выглядит следующим образом:
for (int i=1; i<SIZE; i++) { for (int j=SIZE-2; j>=0; j--) { if (workers[j].age < workers[j+1].age) { worker temp = workers[j]; workers[j]=workers[j+1]; workers[j+1]=temp; } } }
Результат сортировки по возрасту:
Примеры решения задач Задача 1. Объявите структуру Vector (Вектор) с вещественными полями x, y и z, которые задают координаты этого вектора в трёхмерном пространстве. Создайте функцию, которая принимает два аргумента типа Vector и возвращает их скалярное произведение.
#include <iostream> using namespace std; struct Vector { float x; float y; float z; }; float getScalarProduct(Vector v1, Vector v2) { return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; } int main() { Vector vect1 = {12.3, 45.3, 2.3}; Vector vect2 = {11.2, 35.2, 17.8}; cout << getScalarProduct(vect1, vect2) << endl; return 0; }
Задача 2. Объявите структуру Point (Точка) с вещественными полями x и y, которые задают её координаты на плоскости. Объявить также структуру Circle (Окружность) с полем center типа Point, которое задает координаты центра этой окружности, и вещественным полем radius, определяющим её радиус. Создайте функцию, которая принимает в качестве аргументов окружность и точку, а возвращает true, если точка находится внутри окружности, и false – иначе.
#include <iostream> using namespace std; struct Point { float x; float y; }; struct Circle { Point center; float radius; }; float getDistance(Point p1, Point p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)); } bool isInside(Point p, Circle c) { float dist = getDistance(p, c.center); return dist < c.radius; } int main() { Circle circle; circle.center.x = 12.3; circle.center.y = 10.1; circle.radius = 7.8; Point point; point.x = 15; point.y = 11; IsInside(point, circle)? cout << "Внутри\n": cout << "Снаружи\n"; return 0; } Задача 3. Объявите структуру «Книга», имеющую 5 полей: название, автор, тираж, количество страниц и цена. Задайте в коде программы массив из структур и выведите их в виде таблицы.
#include <iostream> using namespace std; struct Book { char name[100]; char author[100]; int nCopies; int nPages; float price; }; Book books[] = { {"Пиковая дама", "Пушкин", 10000, 70, 300}, {"Идиот", "Достоевский", 20000, 490, 600}, {"Мастер и Маргарита", "Булгаков", 40000,340,500}, {"Совершенный код", "Макконнел", 4000,800, 900}, {"Криптография", "Смарт", 3000, 400, 550} }; int main() { setlocale(LC_ALL, "Russian"); printf("%-20s %-12s %-7s %-5s %-5s\n", "Название", "Автор", "Тираж", "Стр.", "Цена"); printf("------------------------------------\n"); for (int i=0; i<5; i++) { printf("%-20s %-12s %-7d %-5d %-5.2f\n", books[i].name, books[i].author, books[i].nCopies, books[i].nPages, books[i].price); } printf("------------------------------------\n"); return 0; }
Задача 4. На основе предыдущей программы реализовать меню из следующих пунктов: 1 – Вывод массива в виде таблицы, 2 – Сортировка массива по второму полю, 3 – Сортировка массива по третьему полю, 4 – Запись содержимого массива в файл, 0 – Выход. Каждый пункт меню реализовать в виде отдельной функции.
#include <iostream> using namespace std; struct Book { char name[100]; char author[100]; int nCopies; int nPages; float price; }; const int n=5; Book books[n] = { {"Пиковая дама", "Пушкин", 10000, 70, 300}, {"Идиот", "Достоевский", 20000, 490, 600}, {"Мастер и Маргарита", "Булгаков", 40000, 340, 500}, {"Совершенный код", "Макконнел", 4000, 800, 900}, {"Криптография", "Смарт", 3000, 400, 550} }; void printBooks() { printf("%-25s %-15s %-7s %-10s %-10s\n", "Название", "Автор", "Тираж", "Страниц", "Цена"); for (int i=0; i<5; i++) { printf("%-25s %-15s %-7d %-10d %-10.2f\n", books[i].name, books[i].author, books[i].nCopies, books[i].nPages, books[i].price); } } #define NAME 1 #define AUTHOR 2 #define N_COPIES 3 #define N_PAGES 4 #define PRICE 5 bool isGreater(Book b1, Book b2, int field) { switch(field) { case NAME: return strcmp(b1.name, b2.name) > 0; case AUTHOR: return strcmp(b1.author, b2.author) > 0; case N_COPIES: return b1.nCopies > b2.nCopies; case N_PAGES: return b1.nPages > b2.nPages; case PRICE: return b1.price > b2.price; default: return true; } } void sortBooks(int field) { for (int i=0; i<n-1; i++) { int max = i; for (int j=i+1; j<n; j++) { if (isGreater(books[max], books[j], field)) { max = j; } } Book temp = books[max]; books[max] = books[i]; books[i] = temp; } } void intoFile() { FILE* dataFile = fopen("books.txt", "w"); for (int i=0; i<5; i++) { fprintf(dataFile, "%s\n%s\n%d\n%d\n%f\n", books[i].name, books[i].author, books[i].nCopies, books[i].nPages, books[i].price); } fclose(dataFile); } int main() { setlocale(LC_ALL, "Russian"); while (true) { system("cls"); printf("1 - Вывод всех книг\n"); printf("2 - Сортировка по названию\n"); printf("3 - Сортировка по автору\n"); printf("4 - Сортировка по тиражу\n"); printf("5 - Сортировка по числу страниц\n"); printf("6 - Сортировка по цене\n"); printf("7 - Запись в файл\n"); printf("0 - Выход\n"); int choice; cin >> choice; switch (choice) { case 1: printBooks();break; case 2: sortBooks(NAME);break; case 3: sortBooks(AUTHOR);break; case 4: sortBooks(N_COPIES);break; case 5: sortBooks(N_PAGES);break; case 6: sortBooks(PRICE);break; case 7: intoFile();break; case 0: exit(EXIT_SUCCESS);break; default: printf("Ошибка\n"); } system("pause"); } return 0; }
КОНТРОЛЬНЫЕ ВОПРОСЫ
Тема 12. СТРУКТУРЫ Зачем нужны структуры? Одна из задач любого языка программирования заключается в предоставлении программисту инструментов, позволяющих представлять данные в удобной для работы форме. Структуры являются одним из таких инструментов, который хорошо подходит в ряде случаев, когда сложно обойтись только переменными и массивами. Некоторые языки программирования, например, Паскаль, применительно к структурам используют термин запись (record), тем не менее, принципы работы с записями и структурами одинаковы. Предположим, что перед нами стоит задача реализовать базу данных, предназначенную для работы с информацией о сотрудниках некоторой фирмы. С каждым сотрудником связан набор разнотипных данных, таких как имя (name), возраст (age), зарплата (salary) и др. Чтобы решить эту задачу, можно описать несколько массивов, каждый из которых будет отвечать за свою характеристику сотрудника:
char name[][20]; float salary[]; int age[];
Однако такой способ совсем неудобен при большом количестве характеристик товара и, следовательно, большом количестве массивов. Представьте себе, как будет выглядеть сортировка десяти массивов, если понадобится упорядочить сотрудников по возрасту; очевидно, что сортировать массивы придется синхронно, чтобы элементы с одинаковыми индексами относились к одному человеку.
Более естественным способом организации данных является представление всех сотрудников в виде массива записей, каждая из которых содержит всю необходимую информацию о сотруднике. Другими словами, вместо трех одномерных массивов следует воспользоваться одним массивом, где каждый из элементов является записью с тремя полями. Структура как раз и представляет собой запись, состоящую из разнотипных данных, относящихся к одному объекту.
Создание структуры
Рассмотрим, как описать структуру для представления сотрудника:
struct Worker { stirng name; float salary; int age; };
В данном фрагменте кода struct – это ключевое слово, информирующее о начале описания структуры. Далее указывается имя структуры Worker, а затем в фигурных скобках перечисляются переменные, входящие в структуру, и указывается их тип; применительно к структурам такие переменные называются полями. Описав структуру Worker, мы фактически определили новый составной тип данных, называемый Worker. После его определения можно описать переменную этого типа:
Worker director;
При описании также можно задать значения полей структуры, перечислив эти значения в том порядке, который указан при описании структуры:
Worker director = {"Андрей", 34, 1000.6};
Заметим, что при описании структуры Worker память под нее не выделяется; это происходит только при описании переменной director типа Worker, которая занимает столько места, сколько ее поля все вместе. Проверим это с помощью оператора sizeof:
cout << "Тип\tРазмер\n"); cout << "----------------------\n"; cout << 20*sizeof(char) << endl; cout << sizeof(int) << endl; cout << sizeof(float) << endl; cout << "----------------------\n"); cout << sizeof(Worker) << endl;
Строка длины 20 занимает 20 байт; целое и вещественное числа занимают по 4 байта; итого получается 28 байт:
Обратите внимание на то, что во избежание путаницы имена структур следует начинать с заглавной буквы, а имена переменных – со строчной. Такое соглашение позволяет к тому же объявлять переменные и структуры с «почти» одинаковыми именами, поскольку язык Си различает регистр букв:
Worker worker;
Обращение к полям структуры и оператор «точка» Обратиться к значению, которое хранит переменная, можно, просто написав ее имя. Структура является не просто переменной, а в некотором смысле составной переменной, поэтому для обращения к данным, которые хранит структура необходимо указать ее имя и имя поля. Для этого существует специальный оператор «точка», который разделяет имена структуры и ее полей. Рассмотрим пример использования этого оператора для того, чтобы присвоить значения элементам структуры:
Worker manager;
manager.name = "Сергей"; manager.salary = 1000.55; manager.age = 33;
Обратите внимание на то, что поля manager.salary и manager.age являются обычными переменными, и работать с ними нужно, как с переменными. Поле manager.name является строкой.
|
||
|
Последнее изменение этой страницы: 2016-04-23; просмотров: 1884; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.102 (0.006 с.) |