Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Обращение к полям структуры и оператор «точка»↑ Стр 1 из 3Следующая ⇒ Содержание книги
Поиск на нашем сайте
Тема 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; просмотров: 1754; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 52.14.7.53 (0.011 с.) |