Значения полей существующей структуры можно изменить, например, так:
strcpy(w1.fio, "Petrov");
w1.date = 17;
w1.code = 334;
w1.salary = 5100.28;
Можно создать структурструктуру в динамической памяти и работать с ней при помощи указателя:
ps1 = new Worker;
strcpy(ps1->fio, "Sidorov");
ps1->date = 22;
ps1->code = 123;
ps1->salary = 1000.00;
Членами структуры могут быть массивы, а также структуры. Если членом структуры является другая структура, она называется вложенной:
struct adr {
char street[20]; // Название улицы
int index; // Почтовый индекс
};
struct stud {
char name[30]; // Фамилия студента
adr adress; // Вложенная структура (адрес)
double pay; // Размер стипендии
};
...
stud a;
a.adress.index = 141050;
Структура adress вложена в структуру stud. Структура stud имеет три поля. Первым из них является массив символов name, вторым – структура типа adr, а третьим – переменная pay. В данном фрагменте программы элементу index структуры adress присваивается значение 141050.
Члены каждой структуры указываются слева направо в соответствии с глубиной вложения (от внешней к внутренней). В языке С++ допускается до 256 уровней вложения.
В функцию можно передавать члены структуры. Структуру можно передавать в функцию и возвращать в качестве значения функции.
Рассмотрим пример решения задачи с выводом текущего системного времени, представленного в виде структуры.
// Структура в файле time.h
struct tm {
int tm_sec; // seconds after the minute - [0,59]
int tm_min; // minutes after the hour - [0,59]
int tm_hour; // hours since midnight - [0,23]
int tm_mday; // day of the month - [1,31]
int tm_mon; // months since January - [0,11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0,6]
int tm_yday; // days since January 1 - [0,365]
int tm_isdst; // daylight savings time flag
};
// Листинг 8.1
#include <iostream>
#include <ctime> // Для использования структуры tm
using namespace std;
int main() {
setlocale(LC_ALL, "Russian");
struct tm *pt;
time_t szClock; // __int64 или long integer
time(&szClock); // Получение времени в секундах
// Конвертирование time в структуру tm form
pt = localtime(&szClock);
cout << "Текущее время: " << pt->tm_hour
<< ":"<< pt->tm_min << ":" << pt->tm_sec
<<"; год "<< pt->tm_year + 1900 << endl;
// __TIME__ – глобальный идентификатор,
// содержащий время начала процесса обработки
// исходного файла
cout << "Time1 = " << __TIME__ << endl;
getch();
// Определение текущего системного времени
time(&szClock);
// Конвертирование в структуру
pt = localtime(&szClock);
// Новое время
cout << "Текущее время: " << pt->tm_hour
<< ":" << pt->tm_min <<":" << pt->tm_sec
<< "; месяц " << pt->tm_mon + 1 << endl;
cout << "Time2 = " << __TIME__ << endl;
return 0;
}
Рассмотрим ещё один пример: описать структуру с именем employee, содержащую следующие поля:
name – фамилия;
pay – заработная плата.
Создать массив office из структур employee, число элементов в массиве задаётся в процессе выполнения программы. Заполнить массив считыванием информации из файла inform.txt. Вычислить среднюю зарплату сотрудников.
// Листинг 8.2
#include <iostream>
#include <fstream>
using namespace std;
struct employee {
char name[20]; // Фамилия сотрудника
double pay; // Зарплата сотрудника
};
int main() {
setlocale(LC_CTYPE, "Russian");
int n, i;
double s = 0;
cout << "Введите размер массива структур\n";
cin >> n; // Число элементов в массиве структур
// Выделение динамической памяти для массива
// структур
employee * office = new employee[n];
// Открытие файла для ввода
ifstream instr("inform.txt");
if (!instr){//Проверка корректного открытия файла
cout << "Файл не может быть открыт\n";
return 1; // Выход из программы
}
// Заполнение массива считыванием из файла
for (i = 0; i < n; ++i) {
instr >> office[i].name >> office[i].pay;
cout << office[i].name <<" " // Вывод на экран
<< office[i].pay << "\n";
}
// Закрытие файла
instr.close();
// Вычисление средней заработной платы
for (i = 0; i < n; ++i)
s += office[i].pay;
s /= n;
cout << "Средняя зарплата = " << s << "\n";
delete [] office; // Освобождение динамич. памяти
return 0;
}
Форматный ввод/вывод данных в стиле языка С
Форматный вывод (в стандартный поток вывода stdout, связанный с экраном) осуществляется функцией printf библиотеки языка С (файл <stdio.h>, <cstdio>).
Формат описания:
int printf(строка_форматир-я [, список_переменных]);
Строка_форматирования задаёт формат вывода значений переменных, перечисленных в списке_переменных, и помимо спецификаторов формата может содержать текст и управляющие (escape-) символы.
Например:
printf("Решение задачи:\n");
printf("\n");
Спецификатор формата приводится для каждой переменной из списка и имеет вид:
%[флаги][ширина][.точность] [h|l|ll|I|I32|i64]
Спецификатор
Обязательными являются символ «%» и спецификатор, который указывает способ интерпретации переменной (табл. 8.1).
Для вывода символа % в строке форматирования необходимо использовать сдвоенный символ %%, символы «"»и «'» предварять обратным слэшем (\" и \'). Например,
int i = 12, proc = 25;
double x = -2.15, y = 1.e-4;
printf("| %2i | %6.2f | %12.6e |", i, x, y);
...
printf ("Начислено %d%%\n", proc);
Поле вывода для вещественной переменной x (%6.2f):
+/- | . |
Таблица 8.1. Спецификаторы типа переменной, используемые в функциях printf(), sprintf() и fprintf()
Спецификатор | Тип | Формат вывода |
c | int | символ (переменная привод-ся к типу unsigned char) |
d, i | int | знаковое десятичное целое число |
o | int | беззнаковое восьмеричное целое число |
u | int | беззнаковое десятичное целое число |
x | int | беззнаковое шестнадцатеричное целое число (в качестве цифр от 10 до 15 используются буквы “abcdef”) |
X | int | беззнаковое шестнадцатеричное целое число (в качестве цифр от 10 до 15 используются буквы “ABCDEF”) |
e, E | float, double | знаковое число с плавающей точкой в формате [–]m.ddde±xxx, где m – одна десятичная цифра, ddd – ноль и более десятичных цифр (количество определяется значением поля точность, нулевая точность подавляет вывод десятичной точки, по умолчанию точность = 6), e (или E) – символ экспоненты, xxx – ровно три десятичные цифры (показатель) |
f | float, double | знаковое число с плавающей точкой в формате [–]mmm.ddd, где mmm – одна или более десятичных цифр, ddd – 0 или более десятичных цифр (их кол-во определяется значением поля точность, нулевая точность подавляет вывод десятичной точки, по умолчанию точность = 6) |
g, G | float, double | знаковое число с плавающей точкой в формате f или e (для G – E); формат e (E), выбирается, если показатель экспоненты меньше –4 или больше либо равен значению поля точность; десятичная точка не ставится, если за ней не следуют значащие цифры; хвостовые нули не выводятся |
n | int * | ничего не выводится; количество символов, выведенных к данному моменту функцией, записывается в переменную |
p | void * | адрес, содержащийся в указателе (отображается в формате X) |
s | char * | строка символов; вывод осуществляется до тех пор, пока не будет обнаружен символ ‘\0’ или число символов не станет равным значению поля точность |
В спецификаторе формата необязательное поле ширина задаёт минимальную ширину поля вывода. Если количество выводимых символов меньше указанного значения, поле дополняется слева или справа пробелами или нулями в зависимости от установленных флагов. Если больше, ширина игнорируется и значение выводится целиком.
Необязательное поле точность интерпретируется следующим образом:
- при выводе чисел формата e, E и f определяет количество цифр после десятичной точки (последняя цифра числа округляется);
- при выводе чисел формата g и G определяет количество значащих цифр (по умолчанию 6);
- при выводе целых чисел определяет минимальное количество цифр (если цифр недостаточно, число дополняется ведущими нулями);
- при выводе строк определяет максимальное количество символов, лишние символы отбрасываются (по умолчанию строка выводится, пока не встретится символ ‘\0’).
Поля ширина и точность могут быть заданы с помощью символа-заменителя *. В этом случае в списке переменных должны быть указаны их настоящие значения.
Необязательное поле флаги определяет дополнительные особенности вывода (табл. 8.2).
Необязательные модификаторы – префиксы [h|l|ll|I|I32|I64] определяют размерность целочисленной переменной: h соответствует ключевому слову short, l – long, ll – long long, I – _int32 для 32-разрядной и _int64 для 64-разрядной платформ, I32 – _int32, I64 –_int64.
Пример использования различных форматов вывода:
int a1 = 66000, b1 = 12;
printf("1 Результат сложения: %hd + %hd = %hd\n",
a1, b1, a1+b1);
// При выводе переменной a1 и вычислении суммы
// использованы только 2 младших байта (как short)
// из 4-х (в int): 66000 – 65536 = 464
short a2 = 60000, b2 = 6000;
printf("2 Результат сложения: %ld + %ld = %ld\n",
a2, b2, a2+b2);
unsigned short a3 = 60000, b3 = 6000;
printf("3 Результат сложения: %ld + %ld = %ld\n",
a3, b3, a3+b3);
double a4 = 1.5e30;
float b4 = 6.e-5;
printf("4 double %%f 1.5e30 = %f\n", a4);
printf("5 double %%e 1.5e30 = %e\n", a4);
printf("6 float %%f 6.e-5 = %f\n", b4);
printf("7 float %%e 6.e-5 = %e\n", b4);
Результат выполнения программы:
1 Результат сложения: 464 + 12 = 476
2 Результат сложения: -5536 + 6000 = 464
3 Результат сложения: 60000 + 6000 = 66000
4 double %f 1.5e30 = 1499999999999999900000000000000.000000
5 double %e 1.5e30 = 1.500000e+030
6 float %f 6.e-5 = 0.000060
7 float %e 6.e-5 = 6.000000e-005
Форматный ввод (из стандартного потока ввода stdin, связанного с клавиатурой) осуществляется функцией scanf() библиотеки языка С (файл <stdio.h>, <cstdio>).
Формат описания:
int scanf(const char * строка_форматирования,
список_адресов_переменных);
Таблица 8.2. Флаги в функциях printf(), sprint() и fprintf()
Флаг | Назначение |
– | если число выведенных символов оказывается меньше указанных, результат выравнивается по левому краю поля вывода (по умолчанию принято правостороннее выравнивание) |
+ | при выводе знаковых чисел знак отображается всегда (по умолчанию знак ставится только перед отрицательными числами) |
если значению поля ширина предшествует символ ‘0’, выводимое число дополняется ведущими нулями до минимальной ширины поля вывода (по умолчанию заполнителями являются пробелы); при левостороннем выравнивании игнорируется | |
пробел | если выводится положительное знаковое число, перед ним ставится пробел (по умолчанию пробел в таких случаях не ставится); игнорируется при наличии флага + |
# | для чисел формата o, x, X означает добавление ведущих 0, 0x и 0X соответственно (по умолчанию отсутствуют); для чисел формата e, E, g, G и f задаёт присутствие десятичной точки, даже когда за ней не следуют значащие цифры (по умолчанию точка не ставится); для чисел формата g и G предотвращает отбрасывание хвостовых нулей (по умолчанию отбрасываются) |
Функция вводит с клавиатуры значения переменных в соответствии с указанными в строке_форматирования спецификаторами формата (табл. 8.3).
Таблица 8.3. Спецификаторы формата функции scanf()
Спецификатор | Тип вводимых данных |
%i | десятичное число со знаком |
%d | - “ - |
%u | беззнаковое целое десятичное число |
%f | вещественное число типа float |
%lf | вещественное число типа double |
%e | вещественное число в exp-формате |
%s | строка символов |
%c | символ |
В перечне список_адресов_переменных указываются адреса переменных, предназначенных для ввода данных. Например:
int ivalue;
char * psz = new char [10];
double d;
scanf("%2d %5s %6f", &ivalue, psz, &d);
Рассмотрим программу с использованием форматированного ввода:
// Листинг 8.3
#include <iostream> // Для setlocale
//#include <cstdio> // Если не нужна кириллица
using namespace std;
int main() {
// Для использования кириллицы
setlocale(LC_ALL, "Russian");
int res;
char message1[20] = "Ответ правильный";
char * message2 = "Ответ неверный";
printf("\n 2 + 2 = "); // Вопрос
scanf("%d", &res); // Ввод ответа
if (res == 4)
message2 = message1;
printf("\n %s\n", message2);
return 0;
}
Во внутреннем представлении массив символов "Ответ правильный" будет занимать не 16, а 17 знаков, так как в конце данного сообщения добавится символ ‘\0’. Это необходимо учитывать при задании размера массива.
Существуют аналогичные консольным функциям форматного ввода/вывода функции форматного ввода/вывода в строку sscanf() и sprint(). Например, в листинге 8.3 вывод на экран
printf("\n %s\n", message2);
можно заменить выводом в строку:
char answer[20] = {0};
sprintf(answer, "\n %s\n", message2);
Задание. Выполнить задание со структурами согласно своему варианту. Число элементов в массиве структур вводить при выполнении программы и с помощью оператора new создавать динамический массив структур. Вывод на экран элементов массива структур осуществлять в виде таблицы с использованием функции форматного вывода printf().
Вариант 1
1. Описать структуру с именем STUDENT, содержащую следующие поля:
- NAME – фамилия;
- GROUP – номер группы;
- SES – успеваемость (массив из пяти элементов – оценок по предметам).
2. Создать программу, выполняющую:
- ввод из файла данных в массив STUD1, состоящий из n структур типа STUDENT;
- упорядочение массива STUD1 по возрастанию содержимого поля GROUP;
- вывод на экран упорядоченного массива;
- вывод на экран фамилий, номеров групп и успеваемости для всех студентов, включенных в массив, если средний балл студента > 4,0; если таких нет, вывести сообщение.
Вариант 2
1. Описать структуру с именем NOTE, содержащую следующие поля: - NAME – фамилия;
- PHONE – номер телефона;
- BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BLOCKNOTE, состоящий из n структур типа NOTE;
- упорядочение массива BLOCKNOTE, записи разместить в алфавитном порядке (по полю NAME);
- вывод на экран упорядоченного массива;
- вывод на экран информации о людях, чьи дни рождения приходятся на месяц, значение которого введено с клавиатуры; если таких нет, вывести соответствующее сообщение.
Вариант 3
1. Описать структуру с именем AEROFLOT, содержащую следующие поля: - TIP – тип самолета;
- NAZN – название пункта назначения рейса;
- NUMBER – номер рейса.
2. Создать программу, выполняющую:
- ввод из файла данных в массив AIRPORT, состоящий из n структур типа AEROFLOT;
- упорядочение массива AIROPORT по номеру рейса;
- вывод на экран упорядоченного массива;
- вывод на экран номеров рейсов и типов самолетов, вылетающих в пункт назначения, название которого совпало с названием, введенным с клавиатуры; если таких рейсов нет вывести соответствующее сообщение.
Вариант 4
1. Описать структуру с именем ZNAK, содержащую следующие поля: - NAME – фамилия;
- ZODIAK – название знака зодиака;
- BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BOOK, состоящий из n структур типа ZNAK;
- упорядочение массива BOOK по фамилиям;
- вывод на экран упорядоченного массива;
- вывод на экран информацию о людях, родившихся под знаком, наименование которого введено с клавиатуры; если таких нет, вывести соответствующее сообщение.
Вариант 5
1. Описать структуру с именем MARSH, содержащую следующие поля:
- BEGST – название начального пункта маршрута;
- TERMST – название конечного пункта маршрута;
- NUMBER – номер маршрута.
2. Создать программу, выполняющую:
- ввод из файла данных в массив TRAFIC, состоящий из n структур типа MARSH;
- упорядочение массива TRAFIC по названиям начальных пунктов маршрутов;
- вывод на экран упорядоченного массива;
- вывод на экран информации о маршруте, номер которого введён с клавиатуры; если такого маршрута нет, вывести соответствующее сообщение.
Вариант 6
1. Описать структуру с именем TRAIN, содержащую следующие поля:
- DEST – название пункта назначения;
- NUMBER – номер поезда;
- TIME – время отправления.
2. Создать программу, выполняющую:
- ввод из файла данных в массив SCHEDULE, состоящий из n структур типа TRAIN;
- упорядочение массива SCHEDULE, записи должны быть размещены в алфавитном порядке по названиям пунктов назначения;
- вывод на экран упорядоченного массива;
- вывод на экран информации о поездах, отправляющихся после введённого с клавиатуры времени; если таких поездов нет, вывести соответствующее сообщение.
Вариант 7
1. Описать структуру с именем ORDER, содержащую следующие поля:
- PAYER – расчётный счёт плательщика;
- ADDRR – расчётный счёт получателя;
- SUMMA – перечисляемая сумма в руб.
2. Создать программу, выполняющую:
- ввод из файла данных в массив LIST, состоящий из n структур типа ORDER;
- упорядочение массива LIST по расчётным счетам;
- вывод на экран упорядоченного массива;
- вывод на экран информации о сумме, снятой с расчётного счёта плательщика, введённого с клавиатуры; если такого расчётного счёта нет, вывести сообщение.
Вариант 8
1. Описать структуру с именем PRICE, содержащую следующие поля:
- GOODS – название товара;
- SHOP – название магазина, в котором продается товар;
- COST – стоимость товара в руб.
2. Создать программу, выполняющую:
- ввод из файла данных в массив LIST, состоящий из n структур типа PRICE;
- упорядочение массива LIST, записи разместить в алфавитном порядке по названиям магазинов (полю SHOP);
- вывод на экран упорядоченного массива;
- вывод на экран информации о товарах, продающихся в магазине, название которого введено с клавиатуры; если такого нет, вывести соответствующее сообщение.
Вариант 9
1. Описать структуру с именем WORKER, содержащую следующие поля: - NAME – фамилия работника;
- POST – название занимаемой должности;
- YEAR – год поступления на работу.
2. Создать программу, выполняющую:
- ввод из файла данных в массив TABL, состоящий из n структур типа WORKER;
- упорядочение массива TABL, записи должны быть размещены в алфавитном порядке (по полю NAME);
- вывод на экран упорядоченного массива;
- вывод на экран фамилий работников, чей стаж работы в организации превышает значение, введённое с клавиатуры; если таких нет, вывести об этом сообщение.
Вариант 10
1. Описать структуру с именем STUDENT, содержащую следующие поля: - NAME – фамилия;
- GROUP – номер группы;
- SES – успеваемость (массив из пяти элементов – оценок по предметам).
2. Создать программу, выполняющую:
- ввод из файла данных в массив STUD1, состоящий из n структур типа STUDENT;
- упорядочение массива STUD1 по среднему баллу;
- вывод на экран упорядоченного массива;
- вывод на экран фамилий, номеров групп и успеваемости для всех студентов, имеющих оценки 4 и 5; если таких нет, вывести соответствующее сообщение.
Вариант 11
1. Описать структуру с именем MARSH, содержащую следующие поля: - NUMBER – номер маршрута;
- BEGST – название начального пункта маршрута;
- TERMST – название конечного пункта маршрута.
2. Создать программу, выполняющую:
- ввод из файла данных в массив TRAFIC, состоящий из n структур типа MARSH;
- упорядочение массива TRAFIC по номерам маршрутов;
- вывод на экран упорядоченного массива;
- вывод на экран информации о маршрутах, которые начинаются или заканчиваются в пункте, название которого введено с клавиатуры; если таких маршрутов нет, вывести соответствующее сообщение.
Вариант 12
1. Описать структуру с именем ZNAK, содержащую следующие поля: - NAME – фамилия;
- ZODIAK – название знака зодиака;
- BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BOOK, состоящий из n структур типа ZNAK;
- упорядочение массива BOOK по датам дней рождения;
- вывод на экран упорядоченного массива;
- вывод на экран информации о человеке, чья фамилия введена с клавиатуры; если такого нет, вывести сообщение.
Вариант 13
1. Описать структуру с именем NOTE, содержащую следующие поля: - NAME – фамилия;
- PHONE – номер телефона;
- BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BLOCKNOTE, состоящий из n структур типа NOTE;
- упорядочение массива BLOCKNOTE по датам рождения;
- вывод на экран упорядоченного массива;
- вывод на экран информации о человеке, номер телефона которого введён с клавиатуры; если такого нет, вывести соответствующее сообщение.
Вариант 14
1. Описать структуру с именем TRAIN, содержащую следующие поля: - DEST – название пункта назначения;
- NUMBER – номер поезда;
- TIME – время отправления.
2. Создать программу, выполняющую:
- ввод из файла данных в массив SCHEDULE, состоящий из n структур типа TRAIN;
- упорядочение массива SCHEDULE по времени отправления;
- вывод на экран упорядоченного массива;
- вывод на экран информации о поездах, направляющихся в пункт, название которого введено с клавиатуры; если таких нет, вывести соответствующее сообщение.
Вариант 15
1. Описать структуру с именем AEROFLOT, содержащую следующие поля: DEST – название пункта назначения рейса; NUMBER – номер рейса; TYPE – тип самолета.
2. Создать программу, выполняющую:
- ввод из файла данных в массив AIRPORT, состоящий из n структур типа AEROFLOT;
- упорядочение массива AIROPORT (в алфавитном порядке по названиям пунктов назначения);
- вывод на экран упорядоченного массива;
- вывод на экран пунктов назначения и номеров рейсов, обслуживаемых самолетом, тип которого введён с клавиатуры; если таких нет, вывести сообщение.
Вариант 16
1. Описать структуру с именем STUDENT, содержащую следующие поля:
- NAME – фамилия;
- GROUP – номер группы;
- SES – успеваемость (массив из пяти элементов – оценок по предметам).
2. Создать программу, выполняющую:
- ввод из файла данных в массив STUD1, состоящий из n структур типа STUDENT;
- упорядочение массива STUD1 по возрастанию содержимого поля NAME (в алфавитном порядке);
- вывод на экран упорядоченного массива;
- вывод на экран фамилий, номеров групп и успеваемости для всех студентов, имеющих хотя бы одну оценку 2; если таких нет, вывести соответствующее сообщение.
Вариант 17
1. Описать структуру с именем ZNAK, содержащую следующие поля:
- NAME – фамилия;
- ZODIAK – название знака зодиака;
- BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BOOK, состоящий из n структур типа ZNAK;
- упорядочение массива BOOK по знакам зодиака;
- вывод на экран упорядоченного массива;
- вывод на экран информации о людях, родившихся в месяц, значение которого введено с клавиатуры; если таких нет, вывести соответствующее сообщение.
Вариант 18
1. Описать структуру с именем PRICE, содержащую следующие поля: GOODS – название товара; COST – стоимость товара в руб; SHOP – название магазина, где продаётся товар.
2. Создать программу, выполняющую:
- ввод из файла данных в массив LIST, состоящий из n структур типа PRICE;
- упорядочение массива LIST, записи разместить в алфавитном порядке по названиям товара (полю GOODS);
- вывод на экран упорядоченного массива;
- вывод на экран информации о товаре, название которого введено с клавиатуры; если таких нет, вывести сообщение.
Вариант 19
1. Описать структуру с именем TRAIN, содержащую следующие поля: - DEST – название пункта назначения;
- NUMBER – номер поезда;
- TIME – время отправления.
2. Создать программу, выполняющую:
- ввод из файла данных в массив SCHEDULE, состоящий из n структур типа TRAIN;
- упорядочение массива SCHEDULE по номерам поездов;
- вывод на экран упорядоченного массива;
- вывод на экран информации о поезде, номер которого введён с клавиатуры; если таких поездов нет, вывести соответствующее сообщение.
Вариант 20
1. Описать структуру с именем NOTE, содержащую следующие поля: NAME – фамилия; PHONE – номер телефона;
BDAY – день рождения (массив из трёх чисел).
2. Создать программу, выполняющую:
- ввод из файла данных в массив BLOCKNOTE, состоящий из n структур типа NOTE;
- упорядочение массива BLOCKNOTE по трём первым цифрам номера телефона;
- вывод на экран упорядоченного массива;
- вывод на экран информации о человеке, чья фамилия введена с клавиатуры; если та кого нет, вывести сообщение.