Содержание

Слайд 2

Что такое поток? Каждый класс, поддерживающий потоковый ввод-вывод, наследует классы std::istream

Что такое поток?

Каждый класс, поддерживающий потоковый ввод-вывод, наследует классы std::istream (ввод), std::ostream (вывод) или std::iostream (ввод и

вывод). Именно они обеспечивают возможность использования перегруженных операторов '<<' и '>>', форматирования вывода, преобразование чисел в строки и наоборот и т.д.

Библиотека iostream определяет три стандартных потока:
cin  стандартный входной поток (stdin в С)
cout  стандартный выходной поток (stdout в С)
cerr  стандартный поток вывода сообщений об ошибках (stderr в С)
Для их использования необходимо прописать строку:
using namespace std;

Слайд 3

Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига: >> получить

Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига:
>>  получить из

входного потока
<<  поместить в выходной поток
Вывод информации
cout << значение; Здесь значение преобразуется в последовательность символов и выводится в выходной поток:
cout << n;

Как с этим жить?

Слайд 4

Как с этим жить? Особого внимания заслуживает ввод символьных строк. По

Как с этим жить?

Особого внимания заслуживает ввод символьных строк. По умолчанию

потоковый ввод cin вводит строку до пробела, символа табуляции или перевода строки.

#include  using namespace std; int main() {   char s[80];   cin >> s; // Поток ввода   cout << s << endl; // Поток вывода  }

Слайд 5

Как с этим жить? Для ввода текста до символа перевода строки

Как с этим жить?

Для ввода текста до символа перевода строки используется

манипулятор потока getline():

#include  using namespace std; int main() {   char s[80];   cin.getline(s, 80); //Потоком читаем строку   cout << s << endl; }

Слайд 6

Манипуляторы потока Функцию - манипулятор потока можно включать в операции помещения

Манипуляторы потока

Функцию - манипулятор потока можно включать в операции помещения в

поток и извлечения из потока (<<, >>). В С++ имеется ряд манипуляторов. Рассмотрим основные:
Слайд 7

Небольшая проблема - формат double a = -112.234; double b =

Небольшая проблема - формат

  double a = -112.234;   double b = 4.3981;   int c = 18;   cout << endl << "double number:" << endl;   cout << "width(10)" << endl;   cout.width(10);   cout << a << endl << b << endl;   cout << "fill('0')" << endl;   cout.fill('0');   cout.width(10);   cout << a << endl << b << endl;   cout.precision(5);   cout << "precision(5)" << endl << a << endl << b << endl;   cout << "fixed" << endl << fixed << a << endl << b << endl;   cout << "showpos" << endl << showpos << a << endl << b << endl;   cout << "scientific" << endl << scientific << a << endl << b << endl;   cout << endl << "int number:" << endl;   cout << showbase << hex << c << " " << showbase << oct << c << " ";   cout << showbase << dec << c << endl;   cin.get();

Слайд 8

Файловый поток Для программиста открытый файл представляется как последовательность считываемых или

Файловый поток

Для программиста открытый файл представляется как последовательность считываемых или записываемых

данных. При открытии файла с ним связывается поток ввода-вывода. Выводимая информация записывается в поток, вводимая информация считывается из потока.

 — файловый ввод ;
 — файловый вывод.

#include  using namespace std; int main() {   ofstream fout; //Создаем файловый поток   fout.open("file.txt"); //Открываем файловый поток   fout << "Привет, мир!"; //Пишем строку в файл   fout.close(); //Закрываем поток }

Слайд 9

Режимы доступа Режимы открытия файлов устанавливают характер использования файлов. Для установки

Режимы доступа

Режимы открытия файлов устанавливают характер использования файлов. Для установки режима

в классе ios предусмотрены константы, которые определяют режим открытия файлов.
Слайд 10

Как с этим жить? Режимы открытия файлов можно устанавливать непосредственно при

Как с этим жить?

Режимы открытия файлов можно устанавливать непосредственно при создании

объекта или при вызове метода open().
ofstream fout("file.txt", ios::app); fout.open("file.txt", ios::app);
Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции ИЛИ |, например: ios::out | ios::in - открытие файла для записи и чтения.
Слайд 11

Произвольный доступ к файлу Система ввода-вывода С++ позволяет осуществлять произвольный доступ

Произвольный доступ к файлу

Система ввода-вывода С++ позволяет осуществлять произвольный доступ с

использованием методов seekg() и seekp().
ifstream &seekg(Смещение, Позиция);
ofstream &seekp(Смещение, Позиция);
Смещение определяет область значений в пределах файла (long int). Система ввода-вывода С++ обрабатывает два указателя, ассоциированные с каждым файлом:
get pointer g - определяет, где именно в файле будет производиться следующая операция ввода;
put pointer p - определяет, где именно в файле будет производиться следующая операция вывода.
Слайд 12

Произвольный доступ к файлу char s[80]; fstream inOut; inOut.open("file.txt", ios::out); inOut > s; inOut.close(); cout

Произвольный доступ к файлу

char s[80];   fstream inOut;   inOut.open("file.txt", ios::out);   inOut << "строчка текста" << endl;   inOut.seekp(8, ios::beg);   inOut << "еще строчка текста";   inOut.close();   inOut.open("file.txt", ios::in);   inOut.seekg(-6, ios::end);   inOut >> s;   inOut.close();   cout << s;   cin.get();

Слайд 13

Задача Нужно заполнять таблицу Алгоритм решения задачи следующий: формируем очередную строку

Задача

Нужно заполнять таблицу

Алгоритм решения задачи следующий:
формируем очередную строку для вывода
открываем файл

для чтения, считываем из него данные и сохраняем их в массив строк
закрываем файл
открываем файл для записи
выводим "шапку" таблицы
выводим новую строку
выводим все сохраненные строки обратно в файл, начиная со строки после шапки
Слайд 14

Целочисленные алгоритмы (язык Си) Тема: Длинные числа

Целочисленные алгоритмы (язык Си)

Тема: Длинные числа

Слайд 15

Что такое длинные числа? Задача. Вычислить (точно) 100! = 1·2·3·...·99·100 Проблема:

Что такое длинные числа?

Задача. Вычислить (точно)
100! = 1·2·3·...·99·100
Проблема: это число содержит

более 100 цифр…
Решение: хранить цифры в виде массива, по группам (например, 6 цифр в ячейке).

100! < 100100

201 цифра

201/6 ≈ 34 ячейки

Слайд 16

Хранение длинных чисел 1234 568901 734567 = = 1234·10000002 + 568901·10000001

Хранение длинных чисел

1234 568901 734567 =
= 1234·10000002 +
568901·10000001

+
734567·10000000

Хранить число по группам из 6 цифр – это значит представить его в системе счисления с основанием d = 1000000.

{A} = 1;
for ( k = 2; k <= 100; k ++ )
{ A} = {A} * k;
... // вывести { A}

Алгоритм:

{A} – длинное число, хранящееся как массив

умножение длинного числа на «короткое»

Слайд 17

Умножение длинного числа на короткое 1234 568901 734567 × 3 3703

Умножение длинного числа на короткое

1234 568901 734567
× 3
3703 706705

203701

k

a0

a1

a2

c0

c1

c2

734567·3 = 2 203701

c0

перенос, r1

568901·3 + 2 = 1 706705

c1

r2

1234·3 + 1 = 3703

c2

c0 = ( a0·k + 0) % d
r1 = ( a0·k + 0) / d
c1 = ( a1·k + r1) % d
r2 = ( a1·k + r1) / d
c2 = ( a2·k + r2) % d
r3 = ( a2·k + r2) / d
...

Слайд 18

Вычисление 100! const int d = 1000000; // основание системы int

Вычисление 100!

const int d = 1000000; // основание системы
int A[40] =

{1}, // A[0]=1, остальные A[i]=0
s, r; // произведение, остаток
int i, k, len = 1; // len – длина числа
for ( k = 2; k <= 100; k ++ ) {
i = 0;
r = 0;
while ( i < len || r > 0 ) {
s = A[i]*k + r;
A[i] = s % d; // остается в этом разряде
r = s / d; // перенос
i ++;
}
len = i; // новая длина числа
}

пока не кончились цифры числа {A} или есть перенос

Слайд 19

Как вывести длинное число? «Первая мысль»: for ( i = len-1;

Как вывести длинное число?

«Первая мысль»:

for ( i = len-1; i >=

0; i -- )
printf ( "%d", A[i] );

Проблема: как не потерять первые нули при выводе чисел, длина которых менее 6 знаков?
123 000123
Решение:
составить свою процедуру;
использовать формат "%.6d"!

for ( i = len-1; i >= 0; i -- )
if ( i == len-1 ) printf ( "%ld", A[i] );
else printf ( "%.6d", A[i] );

Слайд 20

Задания «4»: Составить программу для вычисления 99!! = 1·3·...·97·99 «5»: То

Задания

«4»: Составить программу для вычисления
99!! = 1·3·...·97·99
«5»: То же

самое, но написать свою процедуру для вывода (не использовать формат "%.6d").
“6": Написать программу для умножения двух длинных чисел (ввод из файла).
“7": Написать программу для извлечения квадратного корня из длинного числа (ввод из файла).
Слайд 21

ООП (язык Си) Тема: Структуры и классы

ООП (язык Си)

Тема: Структуры и классы

Слайд 22

Что такое структуры? Структура в языке C++ представляет собой производный тип

Что такое структуры?

Структура в языке C++ представляет собой производный тип данных,

который представляет какую-то определенную сущность, также как и класс. Нередко структуры применительно к С++ также называют классами. И в реальности различия между ними не такие большие.

Для определения структуры применяется ключевое слово struct, а сам формат определения выглядит следующим образом:

struct person
{
int age;
string name;
}

Слайд 23

Что с ними делать? struct person { int age; string name;

Что с ними делать?


struct person
{
int age;
string name;
}
int main()
{
person man; // Объявим

объект структуры
man.name = “Vasia”; // Присвоим объекту имя man.age = 25; // Присвоим объекту возраст
cout<<“Name: ”<< man.name<<“ Age: ”<< man.age;
}
Слайд 24

Есть ли что-то похожее? Да, есть! class Person { public: //Методы,

Есть ли что-то похожее? Да, есть!


class Person
{
public: //Методы, к которым можно

обращаться извне
    Person(string n, int a)
    {
     name = n; age = a;
    }
    string getName()
    {
        return name;
    }
    int getAge()
    {
        return age;
    }
private: //Внутренние данные, необходимые для работы класса
    string name;
    int age;
 };
Слайд 25

Классы, как быть и куда идти? struct user { public: //Методы,

Классы, как быть и куда идти?


struct user
{
public: //Методы, к которым можно

обращаться извне
    user(string n, int a)
    {
        name = n; age = a;
    }
    string getName()
    {
        return name;
    }
    int getAge()
    {
        return age;
    }
private: //Внутренние данные, необходимые для работы класса
    string name;
    int age;
};
 int main()
{
    user tom("Tom", 22); // Объявим объект структуры
    cout << "Name: " << tom.getName() << "\tAge: " << tom.getAge() ;
    }
Слайд 26

Заголовочные файлы Для удобства описания классов вынося в отдельные файлы с

Заголовочные файлы

Для удобства описания классов вынося в отдельные файлы с расширением

.h от слова header, которые таки и называют «хидеры» или «заголовочные файлы».
Создадим программу, которая будет заниматься учетом успеваемости студентов в группе.
Сформируем заголовочный файл students.h, в котором будет находиться класс Students.
Затем обратимся к нему из главной функции основной программы.
(примеры вынесены в отдельные файлы students.h и main.cpp)
Слайд 27

Задания «4»: Создайте структуру с именем train, содержащую поля: название пункта

Задания

«4»: Создайте структуру с именем train, содержащую поля: название пункта назначения,

номер поезда, время отправления.
Ввести данные из файла (создаем заранее) в массив из пяти элементов типа train, упорядочить элементы по номерам поездов.
Добавить возможность вывода информации о поезде, номер которого введен пользователем.
Добавить возможность сортировки массива по пункту назначения, причем поезда с одинаковыми пунктами назначения должны быть упорядочены по времени отправления.
Слайд 28

Задания «ДЗ»: Создайте класс с именем train, содержащий поля: название пункта

Задания

«ДЗ»: Создайте класс с именем train, содержащий поля: название пункта назначения,

номер поезда, время отправления.
Ввести данные из файла (создаем заранее) в массив из пяти элементов типа train, упорядочить элементы по номерам поездов.
Добавить возможность вывода информации о поезде (метод класса).
Добавить возможность сортировки массива по пункту назначения, причем поезда с одинаковыми пунктами назначения должны быть упорядочены по времени отправления.
Слайд 29

Работа с памятью (язык Си) Тема: Динамическое выделение памяти

Работа с памятью (язык Си)

Тема: Динамическое выделение памяти

Слайд 30

Возможно, кто-то пробовал делать так: int n = 10; int arr[n];

Возможно, кто-то пробовал делать так:
int n = 10;
int arr[n];
И, ясное

дело, из этого ничего не получилось =)
Дело в том, что количество выделяемых в памяти ячеек, согласно синтаксису С++ должно быть обозначено константой, причем целочисленной. Это сделано для того, чтобы избежать случайной потери данных в процессе работы программы.

Основные положения

Слайд 31

Динамическое выделение памяти (указатели) #include using namespace std; int main() {

Динамическое выделение памяти (указатели)

#include
using namespace std;
int main()
{
int *a =

new int; // Объявление указателя для переменной типа int
int *b = new int(5); // Инициализация указателя
*a = 10;
*b = *a + *b;
cout << "b is " << *b << endl;
delete b;
delete a;
}

Выделение памяти осуществляется с помощью оператора new и имеет вид: тип_данных *имя_указателя = new тип_данных;, например int *a = new int;. После удачного выполнения такой операции, в оперативной памяти компьютера происходит выделение диапазона ячеек, необходимого для хранения переменной типа int.
Для того, чтобы освободить память, выделенную оператором new, используется оператор delete.

Слайд 32

Динамическое выделение памяти (указатели) #include using namespace std; int main() {

Динамическое выделение памяти (указатели)

#include
using namespace std;
int main()
{
int num; //

размер массива
cout << "Enter integer value: ";
cin >> num; // получение от пользователя размера массива
int *p_darr = new int[num]; // Выделение памяти для массива
for (int i = 0; i < num; i++) {
// Заполнение массива и вывод значений его элементов
p_darr[i] = i;
cout << "Value of " << i << " element is " << p_darr[i] << endl;
}
delete [ ] p_darr; // очистка памяти
}

Поскольку массивы это тоже переменные, то правила выделения памяти под них остаются прежними, нужно только учесть. Что элементов, как правило, несколько.

Слайд 33

Задания «4»: Найти сумму и среднее арифметическое целочисленных элементов динамического массива.

Задания

«4»: Найти сумму и среднее арифметическое целочисленных элементов динамического массива. Данные

поступают в массив из файла с числами, количество которых заранее неизвестно.
«5»: Заданы два одномерных целочисленных массива А и В, состоящие из N и М элементов соответственно (где 0≤i Сформировать массив С, элементами которого являются натуральные числа – индексы элементов массива А, значения которых равны элементу B[i] (где 0≤i
Слайд 34

Возвращаемся к классам При создании объекта, лучше не копировать память для

Возвращаемся к классам

При создании объекта, лучше не копировать память для него,

а выделять ее в «общей куче» с помощью указателя. И освобождать ее после того, как мы закончили работу с объектом. Реализуем это в нашей программе, немного изменив содержимое файла main.cpp.
(примеры вынесены в отдельные файлы students.h и main2.cpp)

NOTA BENE
При создании статического объекта, для доступа к его методам и свойствам, используют операция прямого обращения — «.» (символ точки). Если же память для объекта выделяется посредством указателя, то для доступа к его методам и свойствам используется оператор косвенного обращения — «->».

Слайд 35

Конструктор и деструктор класса Конструктор класса — это специальная функция, которая

Конструктор и деструктор класса

Конструктор класса — это специальная функция, которая автоматически

вызывается сразу после создания объекта этого класса. Он не имеет типа возвращаемого значения и должен называться также, как класс, в котором он находится. По умолчанию, заполним двойками массив с промежуточными оценками студента.

class Students {
public:
// Конструктор класса Students
Students(int default_score)
{
for (int i = 0; i < 5; ++i) {
scores[i] = default_score;
}
}
private:
int scores[5];
};
int main()
{
Students *student = new Students(2);
}

Слайд 36

Конструктор и деструктор класса Деструктор класса вызывается при уничтожении объекта. Имя

Конструктор и деструктор класса

Деструктор класса вызывается при уничтожении объекта. Имя деструктора

аналогично имени конструктора, только в начале ставится знак тильды ~. Деструктор не имеет входных параметров.

#include
class Students {
public:
// Деструктор
~Students()
{
std::cout << "Memory has been cleaned. Good bye." << std::endl;
}
};
int main()
{
Students *student = new Students;
// Уничтожение объекта
delete student;
}

Слайд 37

Задания «!!!»:Необходимо создать класс — зоомагазин. В классе должны быть следующие

Задания

«!!!»:Необходимо создать класс — зоомагазин. В классе должны быть следующие поля:

животное ( напр. волк, пингвин, собака ), пол, имя , цена, количество. Включить в состав класса необходимый минимум методов, обеспечивающий полноценное функционирование объектов указанного класса:
Конструкторы;
Деструктор;
Предоставить возможность вводить данные с клавиатуры или из файла (по выбору пользователя).
Организовать программу учета выручки с продаж.
Слайд 38

Динамическое выделение памяти (относительные указатели) int main() { int i, j,

Динамическое выделение памяти (относительные указатели)

int main()
{
int i, j, N, M;

int** matrix;
cin >> M >> N;
matrix = new int*[M];
for ( i = 0; i < M; i++)
matrix[i] = new int[N];
for ( i = 0; i < M; i++)
for ( j = 0; j < N; j++)
{
cout << «Element of array " << "[" << i << "][" << j << "] ";
cin >> matrix[i][j];
}
cout << endl;
for ( i = 0; i < M; i++)
{
for ( j = 0; j < N; j++)
cout << matrix[i][j];
сout << endl;
}}
Слайд 39

Динамическое выделение памяти (Функция malloc) Прототип функции malloc: void * malloc(

Динамическое выделение памяти
(Функция malloc)

Прототип функции malloc:
void * malloc( size_t «размер

выделенного блока в байтах»);
Функция malloc выделяет блок памяти, размером sizemem байт, и возвращает указатель на начало блока. Содержание выделенного блока памяти не инициализируется, оно остается с неопределенными значениями.
Слайд 40

Динамическое выделение памяти (Функция malloc) #include #include using namespace std; int

Динамическое выделение памяти
(Функция malloc)

#include
#include
using namespace std;
int main()
{
int

l;
cout << "String length: ";
cin >> l;
char * buf = (char*) malloc(l + 1);
if (buf==0) exit (1);
for (int ix = 0; ix < l; ix++)
buf[ix] ='a' + rand() % 26;
buf[l]='\0';
cout << "Random string: " << buf << "n";
free(buf);
}
Слайд 41

Задания «4»: Дан указатель: double **p = 0; Выполните следующие задания

Задания

«4»: Дан указатель: double **p = 0;
Выполните следующие задания (решения

можно оформлять внутри функции main): * создайте конструкцию, изображенную на рисунке; * выведите число, указанное в квадратике, на экран; * после этого удалите все динамические объекты.
Слайд 42

Задания «5»:Объявите указатель на массив и предложите пользователю выбрать его размер.

Задания

«5»:Объявите указатель на массив и предложите пользователю выбрать его размер. Далее

напишите четыре функции:
первая должна выделить память для массива,
вторая – заполнить ячейки данными,
третья – показать данные на экран,
четвертая – освободить занимаемую память.
Программа должна предлагать пользователю продолжать работу (создавать новые динамические массивы ) или выйти из программы.
Слайд 43

Задания «!!!»: Объявите указатель на массив типа int и выделите память

Задания

«!!!»: Объявите указатель на массив типа int и выделите память для

12-ти элементов. Необходимо написать функцию, которая поменяет значения четных и нечетных ячеек массива. Например есть массив из 4-х элементов:
Слайд 44

Задания «ДЗ»: Объявить и заполнить двумерный динамический массив случайными числами от

Задания

«ДЗ»: Объявить и заполнить двумерный динамический массив случайными числами от 10

до 50. Показать его на экран. Для заполнения и показа на экран написать отдельные функции. (подсказка: функции должны принимать три параметра – указатель на динамический массив, количество строк, количество столбцов). Количество строк и столбцов выбирает пользователь.
Слайд 45

Задания «!!!»:Создайте игру по модели «Морской бой», однако все корабли будут

Задания

«!!!»:Создайте игру по модели «Морской бой», однако все корабли будут одинаковые

по размеру (10 шт), но каждый корабль имеет уровень прочности (задается случайно 50-100 при установке корабля на поле. Игроки ходят по очереди без дублирования ходов (в случае попадания урон вычитается из прочности корабля (рассчитывается случайно, как и прочность)).
Размеры поля задаются при начале игры (динамический массив)
Для описания кораблей (их состояния и координат) использовать структуру или класс
Слайд 46

Динамическое выделение памяти для структур Часто появляется проблема создания дополняемых массивов,

Динамическое выделение памяти для структур

Часто появляется проблема создания дополняемых массивов, размер

которых не имел бы ограничений и изменялся в зависимости от количества введенных данных по мере их поступления.
Чаще всего данные имеют смешанный характер, т.е. являются структурами.
В таком случае алгоритм решения задачи таков:
Формируется структура
Создается массив структур из одного элемента
Заполняется один элемент массива
Затем делается выбор: ввод или выход
Если продолжаем ввод, то создаем дополнительный массив такого-же размера, что и старый и копируем в него данные.
Исходный массив удаляется и заново создается размерностью на 1 больше.
В пп4.
Слайд 47

Задания «4»: Заполнить динамический массив неотрицательными целыми числами. Ввод прекратить при

Задания

«4»: Заполнить динамический массив неотрицательными целыми числами. Ввод прекратить при появлении

первого отрицательного числа. Количество вводимых чисел заранее неизвестно.
«ДЗ»: Обеспечить возможность удаления элемента массива из задания 4 по выбору пользователя.
Слайд 48

Задания «4»: Заполнить динамический структурный массив данными из файла(Имя, год рождения,

Задания

«4»: Заполнить динамический структурный массив данными из файла(Имя, год рождения, возраст).

Ввести возможность упорядочивать данные по всем параметрам. Результат записать в другой файл.
«ДЗ»: Обеспечить возможность поиска элементов в массиве по одному из параметров. Выводить все совпадения в файл.
Слайд 49

Векторы Вектор в C++ — это замена стандартному динамическому массиву, память

Векторы

Вектор в C++ — это замена стандартному динамическому массиву, память для которого

выделяется вручную, с помощью оператора new.

#include
#include
using namespace std;
int main(){
vector A(10);
vector B;
int j=0,N;
cout<<“Insert size of vector”< cin>>N;
while(j {
B.push_back(j);
j++;
}
vector C(10, 3);
}

Основные методы класса vector:
pop_back() — удалить последний элемент
clear() — удалить все элементы вектора
empty() — проверить вектор на пустоту

Слайд 50

Задания «4»: Создать вектор содержащий ФИО людей, размер не определён, заполнение

Задания

«4»: Создать вектор содержащий ФИО людей, размер не определён, заполнение -

вручную, добавить возможность удаления элементов.
«5»: Организовать заполнение вектора из файла с любым количеством строк.
Слайд 51

Операции над векторами #include #include #include using namespace std; int main()

Операции над векторами

#include
#include
#include
using namespace std;
int main()
{
vector names;

string buffer = "";
cout << "Insert names "< do {
getline(cin, buffer);
if (buffer.size() > 0) {
names.push_back(buffer);
}
} while (buffer != "");
cout << "Yours VECTOR:" << endl;
for (int i = 0; i < names.size(); i++) {
cout << names[i] << endl;
}}

Документация по классу vector
http://www.cplusplus.com/reference/vector/vector/

Слайд 52

Двумерные массивы при помощи векторов Для создания двумерного массива при помощи

Двумерные массивы при помощи векторов

Для создания двумерного массива при помощи векторов

необходимо создать вектор из векторов того типа, который требуется для выполнения задачи.
Обращение к элементам происходит аналогично двумерным массивам.

vector> V2D;
// Заполнение вектора
cout<

Слайд 53

Задания «4»: Объявить класс для хранения данных про лампочки (тип (светодиодная,

Задания

«4»: Объявить класс для хранения данных про лампочки (тип (светодиодная, энергосберегающая

или лампа накаливания), мощность (Вт), цвет света, стоимость).
Создать вектор из элементов класса, созданного для хранения информации о лампочках.
«5»: Создать метод TEST для определения и вывода информации. Определить количество ламп с мощностью меньше 40Вт и вывести информацию о них.