Переменные-структуры можно передавать в качестве аргументов функций. Следующий фрагмент кода демонстрирует определение функции printWorker(), которая принимает структуру Worker в качестве аргумента и выводит ее на экран:
void printWorker(Worker worker) {
printf("%s\n", worker.name);
printf("%d\n", worker.age);
printf("%g\n", worker.salary);
}
Вызвать эту функцию можно, передав в нее структуру типа Worker, например, элемент массива workers:
printWorker(workers[1]);
Возврат структуры в качестве значения функции
Переменные-структуры можно возвращать в качестве значения функции. Следующая функция принимает две структуры типа Worker и возвращает сотрудника с большей зарплатой:
Worker getWellPaid(Worker w1, Worker w2) {
return w1.salary > w2.salary? w1: w2;
}
Обратите внимание на то, что здесь используется сокращенная запись оператора if-else, эквивалентная такой конструкции:
Worker getWellPaid(Worker w1, Worker w2) {
if (w1.salary > w2.salary) {
return w1;
} else {
return w2;
}
}
При вызове функции getWellPaid() совместно с функцией printWorker()
Worker director = {"Андрей", 30, 5000};
Worker manager = {"Сергей", 35, 3000};
printf("Сотрудник\n\n");
printWorker(getWellPaid(director, manager));
printf("\nЗарабатывает больше\n");
получается следующий результат:
Передача структуры в качестве аргумента функции
Рассмотрим следующую задачу. Объявить структуру Point (Точка) с вещественными полями x, y и z, которые задают координаты этой точки в трехмерном пространстве. Написать функцию, которая принимает два аргумента типа Point и возвращает расстояние между ними.
#include "stdafx.h"
#include <iostream>
using namespace std;
struct Point {
float x;
float y;
float z;
};
float sqr(float number) {
return number*number;
}
float getDistance(Point p, Point q) {
return sqrt(sqr(p.x-q.x) +
sqr(p.y-q.y) +
sqr(p.z-q.z));
}
int main() {
Point p = {1,2,3};
Point q = {2,3,4};
cout << getDistance(p,q)) << endl;
}
Возврат структур в качестве значения функции
Создадим функцию, которая принимает две точки и возвращают ту из них, которая отстоит дальше от начала координат.
#include <iostream>
using namespace std;
struct Point {
float x;
float y;
float z;
};
float sqr(float number) {
return number*number;
}
float getDistance(Point p, Point q) {
return sqrt(sqr(p.x-q.x) +
sqr(p.y-q.y) +
sqr(p.z-q.z));
}
Point farPoint(Point p1, Point p2) {
Point zero = {0,0,0};
float d1 = getDistance(zero, p1);
float d2 = getDistance(zero, p2);
return d1>d2? p1: p2;
}
int main() {
Point p = {1,2,3};
Point q = {2,3,4};
Point far = farPoint(p,q);
cout << far.x << " " << far.y << endl;
}
Примеры решения задач
Задача 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;
}
КОНТРОЛЬНЫЕ ВОПРОСЫ
- Зачем нужны структуры?
- Как определить новую структуру и объявить переменные-структуры?
- Как инициализировать структуру?
- Как объявить массив структур?
- Что такое поле структуры и как к ним обращаться?
- Что такое вложенные структуры?
- Как вывести содержимое массива структур в виде таблицы?
- Можно ли передавать структуры в качестве аргументов функций и возвращать структуры в качестве значений функций?