- •Розділ 1. Основи платформи .Net
- •1.1. Основи платформи .Net
- •1.2. Загальні відомості об'єктно-орієнтованого програмування
- •1.3. Середовище Visual Studio .Net
- •1.4 Консольні додатки
- •Розділ 2. Основні поняття мови
- •2.1. Склад мови
- •2.1.1 Алфавіт і лексеми
- •2.1.2. Ідентифікатори і ключові слова
- •2.1.3. Знаки операцій і роздільники
- •2.1.4. Літерали
- •Константи в с#
- •Суфікси цілих і дійсних констант
- •Управляючі послідовності у с#
- •2.1.5. Коментарі
- •2.2. Типи даних
- •2.2.1. Класифікація типів
- •2.2.2. Типи літералів
- •2.2.3. Типи-значення і посилальні типи
- •2.2.4. Упаковка і розпаковування
- •2.3. Рекомендації по програмуванню
- •Розділ 3. Змінні, іменовані константи, операції і вирази
- •3.1. Змінні і іменовані константи
- •3.2. Операції і вирази
- •3.2.1. Перетворення вбудованих арифметичних типів-значень
- •3.2.2. Введення у виключення
- •3.2.3. Основні операції с#
- •Операнд_1 ? операнд_2 : операнд_3.
- •3.3. Лінійні програми (програмування лінійних обчислювальних процесів)
- •3.3.1. Просте введення-виведення даних
- •3.3.2. Математичні функції - клас Math
- •Розділ 4. Оператори
- •4.1. Вирази, блоки
- •4.2. Оператори розгалуження
- •4.2.1. Умовний оператор if
- •4.2.1. Умовний оператор switch
- •4.3. Оператори циклу
- •4.3.1. Цикл з передумовою while
- •4.3.2. Цикл з постумовою do
- •4.3.3. Цикл з параметром for
- •For ( ініціалізація; вираз; модифікації ) оператор;
- •4.3.4. Цикл перебору foreach
- •4.3.5. Рекомендації по вибору оператора циклу
- •4.4. Обробка виняткових ситуацій
- •4.4.1. Оператор try
- •Try блок [ блоки catch ] [ блок finally ]
- •4.4.2. Оператор throw
- •Throw [ вираз ];
- •4.4.3. Клас Exception
- •4.4.4. Оператори checked и unchecked
- •4.5. Рекомендації по програмуванню
- •Розділ 5. Класи: основні поняття
- •5.1. Привласнення і порівняння об'єктів
- •5.2. Дані: поля і константи
- •5.3. Методи
- •5.3.1. Параметри методів
- •5.3.2. Параметри-значення
- •5.3.3. Параметри-посилання
- •5.3.4. Вихідні параметри
- •5.4. Ключове слово this
- •5.5. Конструктори
- •5.6. Властивості
- •[ Атрибути ] [ специфікатори ] тип ім’я_властивості
- •[ Get код_доступа ] [ set код_доступа ]
- •5.7. Рекомендації по програмуванню
- •Розділ 6. Масиви і рядки
- •6.1. Одновимірні масиви
- •6.2. Прямокутні масиви
- •6.3. Ступінчасті масиви
- •6.4. Клас System.Array
- •6.5. Клас Random
- •6.6. Оператор foreach
- •6.7. Масиви об’єктів
- •6.8. Символи і рядки
- •6.8.1. Символи
- •6.8.2. Масиви символів
- •6.8.3. Рядки типу string
- •6.8.4. Форматування рядків
- •6.8.5. Рядки типу StringBuilder
- •6.9. Рекомендації з програмування
- •Розділ 7. Класи: подробиці
- •7.1. Перевантаження методів
- •7.2. Рекурсивні методи
- •7.3. Методи із змінною кількістю аргументів
- •7.4. Метод Main
- •7.5. Індексатори
- •7.6. Операції класу
- •7.6.1. Унарні операції
- •7.6.2. Бінарні операції
- •7.6.3. Операції перетворення типу
- •7.7. Деструктор
- •7.8. Вкладені типи
- •7.9. Рекомендації по програмуванню
- •Розділ 8. Ієрархії класів
- •8.1. Спадкоємство
- •8.2. Віртуальні методи
- •8.3. Абстрактні класи
- •8.4. Безплідні класи
- •8.5. Клас object
- •8.6. Рекомендації по програмуванню
- •Розділ 9. Інтерфейси і структурні типи
- •9.1. Синтаксис інтерфейсу
- •9.2. Реалізація інтерфейсу
- •9.3. Робота з об'єктами через інтерфейси. Операції is і as
- •9.4. Інтерфейси і спадкоємство
- •9.5. Стандартні інтерфейси .Net
- •9.5.1. Порівняння об'єктів (інтерфейс iComparable)
- •9.5.2 Сортування по різних критеріях (інтерфейс iComparer)
- •9.5.3 Перевантаження операцій відношення
- •9.5.4. Клонування об'єктів (інтерфейс iСloneable)
- •9.5.5. Перебір об'єктів (інтерфейс iEnumerable) і ітератори
- •9.6. Структури
- •9.7. Перелічення
- •9.7.1 Операції з переліченнями
- •9.7.2. Базовий клас System.Enum
- •9.8. Рекомендації по програмуванню
- •Розділ 10. Делегати, події і потоки виконання
- •10.1. Делегати
- •10.1.1. Опис делегатів
- •10.1.2. Використання делегатів
- •10.1.3. Патерн “спостерігач”
- •10.1.4. Операції
- •10.1.5. Передача делегатів в методи
- •10.1.6. Обробка виключень при виклику делегатів
- •10.3. Багатопотокові додатки
- •10.3.1. Клас Thread
- •Lock ( вираз ) блок_операторів
- •10.3.2. Асинхронні делегати
- •10.4. Рекомендації по програмуванню
- •Розділ 11. Робота з файлами
- •11.1. Потоки байтів
- •11.2. Асинхронне уведення-виведення
- •11.3. Потоки символів
- •11.4. Двійкові потоки
- •11.5. Консольне уведення-виведення
- •11.6. Робота з каталогами і файлами
- •11.7. Збереження об'єктів (серіалізація)
- •11.8. Рекомендації по програмуванню
- •Розділ 12. Збірки, бібліотеки, атрибути, директиви
- •12.2. Створення бібліотеки
- •12.3. Рефлексія
- •12.4. Атрибути
- •12.5. Простір імен
- •12.6. Директиви препроцесора
- •# Константний_вираз
- •[ #Elif константний_вираз
- •[ #Elif константний_вираз
- •Розділ 13. Структури даних, колекції і класи-прототипи
- •13.1. Абстрактні структури даних
- •13.2. Простір імен System.Collections
- •13.3. Клас ArrayList
- •13.4. Класи-прототипи
- •13.5. Створення класу-прототипу
- •13.6. Узагальнені методи
- •13.7. Часткові типи
- •13.8. Типи, що обнуляються
- •13.9. Рекомендації по програмуванню
- •Розділ 14. Додаткові засоби с#
- •14.1. Небезпечний код
- •Unsafe блок
- •14.1.1. Синтаксис вказівок
- •14.1.2. Перетворення та ініціалізація вказівок
- •14.1.3. Операції з вказівками
- •14.2. Регулярні вирази
- •14.2.1. Метасимволи
- •14.2.2. Класи бібліотеки .Net для роботи з регулярними виразами
- •14.3. Документування у форматі xml
- •Лабораторні роботи
- •Лабораторна робота 5. Одновимірні масиви
- •Лабораторна робота 6. Двовимірні масиви
- •Лабораторна робота 7. Рядки
- •Лабораторна робота 8. Класи і операції
- •Лабораторна робота 9. Спадкоємство
- •Лабораторна робота 10. Структури
- •Лабораторна робота 11. Інтерфейси і параметризовані колекції
- •Список літератури
- •Додатки Додаток 1. Специфікатори формату для рядків с#
3.2.3. Основні операції с#
Інкремент і декремент
Операції інкремента (++) і декремента (--), називаються також операціями збільшення і зменшення на одиницю, мають дві форми запису - префіксну, коли знак операції записується перед операндом, і постфіксну. У префіксній формі спочатку змінюється операнд, а потім його значення стає результуючим значенням виразу, а в постфіксній формі значенням виразу є початкове значення операнда, після чого він змінюється. Лістинг 3.2 ілюструє ці операції.
Лістинг 3.2. Операції інкремента і декремента
using System;
namespace ConsoleApplicationl
{class Classl
{
static void Main( )
{
int x = 3, y = 3;
Console.Write("Значення префіксного виразу: ");
Console.WriteLine(++x);
Console.Write("Значення х після приросту: ");
Console.WriteLine(x);
Console.Write("Значення постфіксного виразу: ");
Console.WriteLine(y++);
Console.Write("Значення у після приросту: ");
Console.WriteLine(y);
}}}
Результат роботи програми:
Значення префіксного виразу: 4
Значення х після приросту: 4
Значення постфіксного виразу: 3
Значення у після приросту: 4
Стандартні операції інкремента існують для цілих, символьних, дійсних і фінансових величин, а також для перелічень. Операндом може бути змінна, властивість або індексатор (ми розглянемо властивості і індексатори в подальших розділах.
Операція new
Операція new служить для створення нового об'єкту. Формат операції:
new тип ( [ аргументи ] )
За допомогою цієї операції можна створювати об'єкти як посилальних, так і значущих типів, наприклад:
object z = new object();
int i = new int(); // те ж саме, що int i = 0;
Об'єкти посилального типу зазвичай формують саме цим способом, а змінні значущого типу частіше створюються так, як описано раніше в розділі “Змінні”.
При виконанні операції new спочатку виділяється необхідний об'єм пам'яті (для посилальних типів в хіпові, для значущих - в стеку), а потім викликається так званий конструктор за умовчанням, тобто метод, за допомогою якого ініціалізувався об'єкт. Змінною значущого типу привласнюється значення за умовчанням, яке дорівнює нулю відповідного типу. Для посилальних типів стандартний конструктор ініціалізував значеннями за умовчанням всі поля об'єкту.
Якщо необхідний для зберігання об'єкту об'єм пам'яті виділити не вдалося, генерується виключення Outofmemoryexception.
Операції заперечення
Арифметичне заперечення (унарний мінус -) міняє знак операнда на протилежний. Стандартна операція заперечення визначена для типів int, long, float, double і decimal. До величин інших типів її можна застосовувати, якщо для них можливе неявне перетворення до цих типів (див. рис. 3.1). Тип результату відповідає типу операції.
Для значень цілого і фінансового типів результат досягається відніманням початкового значення з нуля. При цьому може виникнути переповнювання. Чи буде при цьому викинуто виключення, залежить від контексту. Логічне заперечення (!) визначене для типу bool. Результат операції - значення false, якщо операнд рівний true, і значення true, якщо операнд рівний false. Порозрядне заперечення (~), часто зване побітовим, інвертує кожен розряд в двійковому представленні операнда типу int, uint, long або ulong.
Операції заперечення представлені в лістингу 3.3.
Лістинг 3.3. Операції заперечення using System;
using System;
namespace Consoleapplicationl
{
class Classl
{
static void Main( )
{
sbyte a = 3, b = -63, c = 126;
bool d = true;
Console.WriteLine( -a); // Результат -3
Console.WriteLine( -c); // Результат -126
Console.WriteLine( !d); // Результат false
Console.WriteLine( ~a); // Результат -4
Console.WriteLine( ~b); // Результат 62
Console.WriteLine( ~c); // Результат -127
}
}
}
Явне перетворення типу
Операція використовується, як і виходить з її назви, для явного перетворення величини з одного типу в іншій. Це потрібно у тому випадку, коли неявного перетворення не існує. При перетворенні з довшого типу в коротший можлива втрата інформації, якщо початкове значення виходить за межі діапазону результуючого типу. Формат операції:
( тип ) вираз
В даному разі тип - це ім'я того типу, в який здійснюється перетворення, а вираз найчастіше є ім'ям змінної, наприклад:
long b = 300;
int а = (int) b; // дані не втрачаються
byte d = (byte) а; // дані втрачаються
Множення, ділення і залишок від ділення
Операція множення (*) повертає результат перемножування двох операндів. Стандартна операція множення визначена для типів int, uint, long, ulong, float, double і decimal. До величин інших типів її можна застосовувати, якщо для них можливе неявне перетворення до цих типів (див. рис. 3.1). Тип результату операції дорівнює “найбільшому” з типів операндів, але не менше int. Якщо обидва операнди цілочисельні або типу decimal і результат операції перевищує допустиме значення, то генерується виключення System OverflowException. Всі можливі значення для дійсних операндів приведені в таблиці 3.2. Символами х і у позначені кінцеві додатні значення, символом z - результат операції дійсного множення. Якщо результат дуже великий, він приймається рівним значенню “нескінченність”, якщо дуже малий, він приймається за 0. NAN (not а number) означає, що результат не є числом.
Таблиця 3.2.
Результати дійсного множення
* |
+y |
-у |
+0 |
-0 |
+∞ |
-∞ |
NaN |
+x |
+z |
-z |
+0 |
-0 |
+∞ |
-∞ |
NaN |
-x |
-z |
+z |
-0 |
+0 |
-∞ |
+∞ |
NaN |
+0 |
+0 |
-0 |
+0 |
-0 |
NaN |
NaN |
NaN |
-0 |
-0 |
+0 |
-0 |
+0 |
NaN |
NaN |
NaN |
+∞ |
+∞ |
-∞ |
NaN |
NaN |
+∞ |
-∞ |
NaN |
-∞ |
-∞ |
+∞ |
NaN |
NaN |
-∞ |
+∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Операція ділення (/) визначена для типів int, uint, long, ulong, float, double і decimal. Якщо обидва операнди цілочисельні, результат операції округляється вниз до найближчого цілого числа. Якщо дільник дорівнює 0, генерується виключення System. DivideByZeroException.
Якщо хоч би один з операндів дійсний, дробова частина результату ділення не відкидається, а всі можливі значення приведені в таблиці 3.3. Символами х і у позначені кінцеві додатні значення, символом z - результат операції дійсного ділення. Якщо результат дуже великий він приймається рівним значенню “нескінченність”, якщо дуже малий, він приймається за 0.
Таблиця 3.3.
Результати дійсного ділення
/ |
+y |
-у |
+0 |
-0 |
+∞ |
-∞ |
NaN |
+х |
+z |
-z |
+∞ |
-∞ |
+0 |
-0 |
NaN |
-х |
-z |
+z |
-∞ |
+∞ |
-0 |
+0 |
NaN |
+0 |
+0 |
-0 |
NaN |
NaN |
+0 |
-0 |
NaN |
-0 |
-0 |
+0 |
NaN |
NaN |
-0 |
+0 |
NaN |
+∞ |
+∞ |
-∞ |
+∞ |
-∞ |
NaN |
NaN |
NaN |
-∞ |
-∞ |
+∞ |
-∞ |
+∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Для фінансових величин (тип decimal) при діленні на 0 і переповнюванні генеруються відповідні виключення, при зникненні порядку результат рівний 0.
Операція залишку від ділення (%) також інтерпретується по-різному для цілих, дійсних і фінансових величин. Якщо обидва операнди цілочисельні, результат операції обчислюється за формулою
х - (х / у) * у.
Якщо дільник дорівнює нулю, генерується виключення System.DivideByZeroException. Тип результату операції дорівнює “найбільшому” з типів операндів, але не менше int.
Для фінансових величин (тип decimal) при отриманні залишку від ділення на 0 і при переповнюванні генеруються відповідні виключення, при зникненні порядку результат дорівнює 0. Знак результату дорівнює знаку першого операнда. Якщо хоч би один з операндів дійсний, результат операції обчислюється за формулою
х - n * у,
де n - найбільше ціле, яке менше або дорівнює результату ділення х на у. Всі можливі комбінації значень операндів приведені в таблиці 3.4. Символами х і у позначені кінцеві додатні значення, символом z - результат операції залишку від ділення.
Таблиця 3.4.
Результати дійсного залишку від ділення
% |
+y |
-у |
+0 |
-0 |
+∞ |
-∞ |
NaN |
+x |
+z |
z |
NaN |
NaN |
x |
x |
NaN |
-x |
-z |
-z |
NaN |
NaN |
-x |
-x |
NaN |
+0 |
+0 |
+0 |
NaN |
NaN |
+0 |
+0 |
NaN |
-0 |
-0 |
-0 |
NaN |
NaN |
-0 |
-0 |
NaN |
+∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
-∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Приклад застосування операцій множення, ділення і отримання залишку представлений в лістингу 3.4.
Лістинг 3.4. Операції множення, ділення і отримання залишку
using System;
namespace Consoleapplicationl
{
class Classl
{
static void Main( )
{
int x = 11, у = 4;
float z = 4;
Console.WriteLine(z * у ) ; // Результат 16
Console.WriteLine(z * 1e308 ); // Результат "нескінченність"
Console.WriteLine(x / у ); // Результат 2
Console. WriteLine(x / z ); // Результат 2.75
Console.WriteLine(x% у ); // Результат 3
Console.WriteLine(1e-324 / 1e-324 ); // Результат NaN
}
}
}
Декілька операцій одного пріоритету виконуються зліва направо. Для прикладу розглянемо вираз 2 / х • у. Ділення і множення мають один і той же пріоритет, тому спочатку 2 ділиться на х, а потім результат множиться на у. Якщо ж ми хочемо, щоб вираз х • у був в знаменнику, слід укласти його в круглі дужки або спочатку поділити чисельник на х, а потім на у:
2 / (х • у) или 2 / х /у.
Операції складання і віднімання
Операція складання ( + ) повертає суму двох операндів. Стандартна oneрація складання визначена для типів int, uint, long, ulong, float, double і decimal. До величин інших типів її можна застосовувати, якщо для них існує неявне перетворення до цих типів (див. рис. 3.1). Тип результату операції дорівнює “найбільшому” з типів операндів, але не менше int. Якщо обидва операнди цілочисельні або типу decimal і результат операції дуже великий для уявлення за допомогою заданого типу, генерується виключення System.OverflowException.
Можливі значення для дійсних операндів приведені в таблиці 3.5. Якщо результат дуже великий для заданого типу, він приймається рівним значенню “нескінченність”, якщо дуже малий, він приймається за 0.
Таблиця 3.5.
Результати дійсного складання
+ |
y |
+0 |
-0 |
+∞ |
-∞ |
NaN |
x |
z |
x |
x |
+∞ |
-∞ |
NaN |
+0 |
У |
+0 |
+0 |
+∞ |
-∞ |
NaN |
-0 |
У |
+0 |
-0 |
+∞ |
-∞ |
NaN |
+∞ |
+∞ |
+∞ |
+∞ |
+∞ |
NaN |
NaN |
-∞ |
-∞ |
-∞ |
-∞ |
NaN |
-∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Операція віднімання (- ) повертає різницю двох операндів. Стандартна операція віднімання визначена для типів int, uint, long, ulong, float, double і decimal. До величин інших типів її можна застосовувати, якщо для них існує неявне перетворення до цих типів (див. рис. 3.1). Тип результату операції дорівнює “найбільшому” з типів операндів, але не менше int. Якщо обидва операнди цілочисельні або типу decimal і результат операції дуже великий то генерується виключення System.OverflowException. Всі можливі значення результату віднімання для дійчних операндів приведені в таблиці 3.6. Символами х і у позначені кінцеві додатні значення, символом z - результат операції дійсного віднімання. Якщо х і у рівні, результат дорівнює додатному нулю. Якщо результат дуже великий для заданого типу, він приймається рівним значенню “нескінченність” зі знаком, що і х - у, якщо дуже малий, він приймається за 0 з тим же знаком, що й х - у.
Таблиця 3.6.
Результати дійсного віднімання
- |
y |
+0 |
-0 |
+∞ |
-∞ |
NaN |
x |
z |
x |
x |
-∞ |
+∞ |
NaN |
+0 |
-у |
+0 |
+0 |
-00 |
+∞ |
NaN |
-0 |
-у |
-0 |
+0 |
-00 |
+∞ |
NaN |
+v |
+∞ |
+∞ |
+∞ |
NaN |
+∞ |
NaN |
-∞ |
-∞ |
-∞ |
-∞ |
-∞ |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
Операції зсуву
Операції зсуву (<< і >>) застосовуються до цілочисельних операндів. Вони зрушують двійкове представлення першого операнда вліво або вправо на кількість двійкових розрядів, задану другим операндом. При зрушенні розряди, що звільнилися вліво (<<) , обнуляються. При зсуву біти, що звільнилися управо (>>), заповнюються нулями, якщо операнд додатний або беззнакового типу. Для від’ємних чисел вони заповнюються одиницею (1). Операції зсуву ніколи не приводять до переповнювання і втрати значущості. Стандартні операції зсуву визначені для типів int, uint, long і ulong.
Приклад застосування операцій зсуву представлений в лістингу 3.5.
Лістинг 3.5. Операції зсуву
using System;
namespace Consoleapplicationl
{
class Classl
{
static void Main( )
{
byte a = 3, b = 9;
sbyte с = 9, d = -9;
Console.WriteLine( a << 1 ); // Результат 6
Console.WriteLine( a << 2 ); // Результат 12
Console.WriteLine( b >> 1 ); // Результат 4
Console.WriteLine( с >> 1 ); // Результат 4
Console.WriteLine( d >> 1 ); // Результат -5
}
}
}
Операції відношення і перевірки на рівність
Операції відношення (<, <=, >, >=, ==, != ) порівнюють перший операнд з другим. Операнди мають бути арифметичного типу. Результат операції - логічного типу, рівний true або false. Правила обчислення результатів приведені в таблиці 3.7.
Таблиця 3.7.
Результати операцій відношення
Операція |
Результат |
x = =y |
true, якщо х рівне у, інакше false |
x != y |
true, якщо х не рівне у, інакше false |
x<y |
true, якщо х менше у, інакше false |
x<=y |
true, якщо х менше або рівно у, інакше false |
x>=y |
true, якщо х більше або рівно у, інакше false |
Порозрядні логічні операції
Порозрядні логічні операції (&, |, ^) застосовуються до цілочисельних операндів і працюють з їх двійковими уявленнями. При виконанні операцій операнди зіставляються побітно (перший біт першого операнда з першим бітом другого, другий біт першого операнда з другим бітом другого і т. д.). Стандартні операції визначені для типів int, uint, long і ulong.
При порозрядній кон'юнкції, або порозрядному І (операція позначається &), біт результату дорівнює 1 тільки тоді, коли відповідні біти обох операндів дорівнюють 1.
При порозрядній диз'юнкції, або порозрядному АБО (операція позначається |),біт результату дорівнює 1 тільки тоді, коли біт хоч би одного з операндів рівний 1.
При порозрядному виключаючому АБО (операція позначається ^), біт результату дорівнює 1 тільки тоді, коли біт тільки одного з операндів рівний 1.
Приклад застосування порозрядних логічних операцій представлений в лістингу 3.6.
Лістинг 3.6. Порозрядні логічні операції
using System;
namespace Consoleapplicationl
{
class Classl
{
static void Main( )
{
Console.WriteLine(6 & 5); // Результат 4
Console.WriteLine(6 | 5 ); // Результат 7
Console.WriteLine(6 ^ 5 ); // Результат 3
}
}
}
Умовні логічні операції
Умовні логічні операції І (&&) і АБО (||) найчастіше використовуються з операндами логічного типу. Результатом логічної операції є true або false. Результат операції логічне І має значення true, якщо обидва операнди мають значення true. Результат операції логічне АБО має значення true якщо хоч би один з операндів має значення true.
Якщо значення першого операнда досить, щоб визначити результат операціїі, другий операнд не обчислюється. Наприклад, якщо перший операнд операції І рівний false, результатом операції буде false незалежно від значення другого операнда, тому він не обчислюється.
Приклад застосування умовних логічних операцій представлений в лістингу 3.7.
Лістинг 3.7. Умовні логічні операції
using System;
namespace Consoleapplicationl
{
class Classl
{
static void Main( )
{
Console.WriteLine( true && true ); // Результат true
Console.WriteLine( true && false ); // Результат false
Console.WriteLine( true || true ); // Результат true
Console.WriteLine( true || false ); // Результат true
}
}
}
Умовна операція
Умовна операція (? :) має формат: