У мовах програмування C і C ++, яка різниця між використанням кутових дужок та використанням лапок у include
виписці, як це відбувається?
#include <filename>
#include "filename"
У мовах програмування C і C ++, яка різниця між використанням кутових дужок та використанням лапок у include
виписці, як це відбувається?
#include <filename>
#include "filename"
Відповіді:
На практиці різниця полягає в розташуванні, де препроцесор шукає включений файл.
Для #include <filename>
препроцесора здійснюється пошук залежно від реалізації, як правило, в каталогах пошуку, попередньо призначених компілятором / IDE. Цей метод зазвичай використовується для включення стандартних файлів заголовків бібліотеки.
Для #include "filename"
препроцесор пошуків перших в тому ж каталозі, що і файл , який містить директиву, а потім прямує шляхом пошуку , використовуваний для #include <filename>
форми. Цей метод зазвичай використовується для включення файлів заголовків, визначених програмістом.
Більш повний опис є в документації GCC про пошукові шляхи .
#include <...>
використовував пакет, встановлений у системі, і #include "..."
використовував прилеглу до нього версію сховища. Я, можливо, матиму це назад. У будь-якому випадку, включити захист в упакованому заголовку встановлено з підкресленням. (Це може бути умовою для пакетів або, можливо, способом навмисно запобігти змішуванню обох, хоча кваліфікуючі версії мали б для мене більше сенсу.)
Єдиний спосіб знати - це прочитати документацію вашої реалізації.
У розділі 6.10.2 стандарту C , параграфах 2 - 4 зазначено:
Директива щодо попередньої обробки форми
#include <h-char-sequence> new-line
здійснює пошук послідовності місць, визначених реалізацією, для заголовка, визначеного однозначно вказаною послідовністю між
<
і>
роздільниками роздільником, і викликає заміну цієї директиви на весь вміст заголовка . Як визначаються місця або визначається заголовок, визначено реалізацією.Директива щодо попередньої обробки форми
#include "q-char-sequence" new-line
викликає заміну цієї директиви всім вмістом вихідного файлу, ідентифікованим зазначеною послідовністю між
"
роздільниками. Названі вихідному файлі способом, визначеним реалізацією. Якщо цей пошук не підтримується або пошук не вдається, директива переробляється так, ніби вона читається#include <h-char-sequence> new-line
з ідентичною послідовністю, що міститься (включаючи
>
символи, якщо такі є) з оригінальної директиви.Директива щодо попередньої обробки форми
#include pp-tokens new-line
(що не відповідає одній з двох попередніх форм) дозволено. Попередня обробка лексем після
include
директиви обробляється так само, як у звичайному тексті. (Кожен ідентифікатор, визначений в даний час як ім'я макросу, замінюється його списком заміни попередніх обробних жетонів.) Директива, що випливає після всіх замін, повинна відповідати одній з двох попередніх форм. Метод, за допомогою якого послідовність попередньої обробки лексем між a<
і>
парою лексеми попередньої обробки або парою"
символів об'єднується в один заголовок попередньої обробки маркера імені, визначений реалізацією.Визначення:
h-char: будь-який член набору вихідних символів, крім символів нового рядка та
>
q-char: будь-який член набору вихідних символів, крім символів нового рядка та
"
Послідовність символів між <і> однозначно посилається на заголовок, який не обов'язково є файлом. Реалізація майже вільна, щоб використовувати послідовність символів за своїм бажанням. (В основному, однак, просто трактуйте це як ім'я файлу та виконайте пошук у шляху включення , як у інших публікаціях.)
Якщо використовується #include "file"
форма, реалізація спочатку шукає файл із вказаним іменем, якщо воно підтримується. Якщо ні (підтримується), або якщо пошук не вдається, реалізація поводиться так, ніби інша (#include <file>
була використана ) форма.
Також третя форма існує і використовується, коли #include
директива не відповідає жодній із форм, наведених вище. У цій формі деяка основна попередня обробка (наприклад, розширення макросу) виконується на "операндах" #include
директиви, і очікується, що результат відповідає одній з двох інших форм.
<
і >
як ключ для індексації в бібліотеці.
Деякі хороші відповіді тут посилаються на стандарт C, але забули про стандарт POSIX, особливо про особливості поведінки команди c99 (наприклад, компілятор C) .
Відповідно до Технічної бази відкритої групи, випуск 7 ,
-Я каталог
Змініть алгоритм пошуку заголовків, імена яких не є абсолютними іменами шляхів, щоб шукати в каталозі, названому іменем шляху каталогу, перш ніж шукати у звичайних місцях. Таким чином, заголовки, імена яких укладені у подвійні лапки (""), слід шукати спочатку в каталозі файлу з рядком #include , потім у каталогах, названих у параметрах -I , і триватимуть у звичайних місцях. Для заголовків, імена яких укладені в кутових дужках ("<>"), заголовок слід шукати лише в каталогах з іменами -I , а потім у звичайних місцях. Каталоги з іменами -I параметри слід шукати у вказаному порядку. виклику команд c99 .
Отже, в сумісному з POSIX середовищі, сумісному з компілятором C, сумісним з POSIX, спочатку #include "file.h"
буде шукати ./file.h
спочатку, де .
знаходиться каталог, де знаходиться файл із #include
заявою, тоді як #include <file.h>
, ймовірно, /usr/include/file.h
спочатку буде шукатись, де /usr/include
визначена ваша система звичайні місця для заголовків (схоже, це не визначено POSIX).
c99
- що є назвою POSIX для компілятора C. (Стандарт POSIX 2008 навряд чи може посилатися на C11; оновлення 2013 до POSIX 2008 не змінило стандарт C, про який він посилався.)
-L
.
Документація GCC говорить про різницю між ними:
І користувацькі, і файли системних заголовків включаються за допомогою директиви попередньої обробки
‘#include’
. Він має два варіанти:
#include <file>
Цей варіант використовується для файлів заголовків системи. Він шукає файл з іменем файлу в стандартному списку системних каталогів. Ви можете додати каталоги до цього списку за допомогою
-I
параметра (див. Виклик ).
#include "file"
Цей варіант використовується для файлів заголовків вашої власної програми. Він шукає файл з іменем файлу спочатку в каталозі, що містить поточний файл, потім у каталогах цитат, а потім у тих самих каталогах, які використовувались
<file>
. Ви можете додати каталоги до списку цитатних каталогів з-iquote
можливістю. Аргумент‘#include’
, не обмежений цитатами чи кутовими дужками, поводиться як строкова константа, оскільки коментарі не розпізнаються, а назви макросів не розширюються. Таким чином,#include <x/*y>
задається включення файлу системного заголовка з назвоюx/*y
.Однак, якщо нахили нахилу накидаються у файлі, вони вважаються звичайними текстовими символами, а не символами. Жодна послідовність відхилення символів, відповідна константам рядка в С, не обробляється. Таким чином,
#include "x\n\\y"
вказується ім'я файлу, що містить три зворотні риски. (Деякі системи інтерпретують "\" як роздільник імен траєкторії. Усі вони також трактуються‘/’
однаково. Це найбільш портативний варіант використання‘/’
.)Це помилка, якщо в рядку після назви файлу є щось (крім коментарів).
Це робить:
"mypath/myfile" is short for ./mypath/myfile
з .
тим, що це або каталог файлу, де #include
він міститься, та / або поточний робочий каталог компілятора, та / абоdefault_include_paths
і
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
Якщо ./
є <default_include_paths>
, то це не має значення.
Якщо mypath/myfile
в іншому каталогу включення, поведінка не визначена.
#include "mypath/myfile"
не рівнозначно #include "./mypath/myfile"
. Як йдеться у відповіді piCookie, подвійні лапки говорять компілятору шукати визначений реалізацією спосіб - що включає пошук у місцях, визначених для #include <...>
. (Насправді це, мабуть, рівнозначно, але тільки тому, що, наприклад, /usr/include/mypath/myfile
можна згадати як /usr/include/./mypath/myfile
- принаймні на системах, схожих на Unix.)
defaultincludepaths
, на відміну від надання іншого значення .
(як зазначено вище). Це має очікуваний наслідок того, що обидва #include "..."
і #include <...>
шукають у dirpath
<file>
Включає говорить препроцесор для пошуку в -I
каталогах і в зумовлених каталогах перших , то в директорії .c файлу. "file"
Включає говорить препроцесор для пошуку каталогу вихідного файлу першого , а потім повернутися до -I
і визначено. Усі місця пошуку шукають у будь-якому випадку, лише порядок пошуку різний.
Стандарт 2011 року в основному обговорює файли включення у "16.2 Включення вихідних файлів".
2 Директива щодо попередньої обробки форми
# include <h-char-sequence> new-line
здійснює пошук послідовності місць, визначених реалізацією, для заголовка, визначеного однозначно вказаною послідовністю між розділювачами <та>, і викликає заміну цієї директиви на весь вміст заголовка. Як визначаються місця або визначається заголовок, визначено реалізацією.
3 Директива щодо попередньої обробки форми
# include "q-char-sequence" new-line
викликає заміну цієї директиви на весь вміст вихідного файлу, ідентифікованого за вказаною послідовністю між "роздільниками. Названий вихідний файл шукається у визначеному реалізацією способі. Якщо цей пошук не підтримується, або якщо пошук не вдається , директива переробляється так, ніби її читають
# include <h-char-sequence> new-line
з ідентичною послідовністю, що міститься (включаючи> символи, якщо такі є) з оригінальної директиви.
Зверніть увагу, що "xxx"
форма деградує до <xxx>
форми, якщо файл не знайдено. Решта визначається реалізацією.
-I
вказаний цей бізнес?
-I
.
#include <file.h>
повідомляє компілятору шукати заголовок у каталозі "включає", наприклад, для MinGW компілятор шукатиме file.h
в C: \ MinGW \ include \ або там, де встановлений ваш компілятор.
#include "file"
повідомляє компілятору шукати поточний каталог (тобто каталог, у якому знаходиться вихідний файл) file
.
Ви можете використовувати -I
прапор для GCC, щоб сказати, що, коли він стикається з включенням з кутовими дужками, він також повинен шукати заголовки в каталозі після -I
. GCC буде ставитись до каталогу після прапора так, як ніби це includes
каталог.
Наприклад, якщо у вас є файл, викликаний myheader.h
у вашому власному каталозі, ви можете сказати, #include <myheader.h>
якщо ви викликали GCC з прапором -I .
(що вказує на те, що він повинен шукати включає в поточному каталозі).
Без -I
прапора вам потрібно буде #include "myheader.h"
включити файл або перейти myheader.h
до include
каталогу вашого компілятора.
За стандартом - так, вони різні:
Директива щодо попередньої обробки форми
#include <h-char-sequence> new-line
здійснює пошук послідовності місць, визначених реалізацією, для заголовка, визначеного однозначно вказаною послідовністю між роздільниками
<
та>
роздільником, і викликає заміну цієї директиви на весь вміст заголовка. Як визначаються місця або визначається заголовок, визначено реалізацією.Директива щодо попередньої обробки форми
#include "q-char-sequence" new-line
викликає заміну цієї директиви всім вмістом вихідного файлу, ідентифікованим визначеною послідовністю між
"
роздільниками. Шукається в названому вихідному файлі способом, визначеним реалізацією. Якщо цей пошук не підтримується або пошук не вдається, директива переробляється так, ніби вона читається#include <h-char-sequence> new-line
з ідентичною послідовністю, що міститься (включаючи
>
символи, якщо такі є) з оригінальної директиви.Директива щодо попередньої обробки форми
#include pp-tokens new-line
(що не відповідає одній з двох попередніх форм) дозволено. Попередня обробка лексем після
include
директиви обробляється так само, як у звичайному тексті. (Кожен ідентифікатор, визначений в даний час як ім'я макросу, замінюється його списком заміни попередніх обробних жетонів.) Директива, що випливає після всіх замін, повинна відповідати одній з двох попередніх форм. Метод, за допомогою якого послідовність попередньої обробки лексем між a<
і>
парою лексеми попередньої обробки або парою"
символів об'єднується в один заголовок попередньої обробки маркера імені, визначений реалізацією.Визначення:
h-char: будь-який член набору вихідних символів, крім символів нового рядка та
>
q-char: будь-який член набору вихідних символів, крім символів нового рядка та
"
Зауважте, що стандарт не вказує жодного зв'язку між визначеними реалізацією способами. Перша форма здійснює пошук одним способом, визначеним реалізацією, а друга - визначеним варіантом реалізації. Стандарт також визначає, що певні файли включають (наприклад,<stdio.h>
).
Формально вам доведеться прочитати посібник для вашого компілятора, однак зазвичай (за традицією) #include "..."
форма шукає каталог файлу, в якому #include
спочатку було знайдено, а потім у каталогах, які #include <...>
форма шукає (включаючи шлях, наприклад, заголовки системи ).
Дякую за чудові відповіді, esp. Адам Стельмащик і piCookie, і aib.
Як і багато програмістів, я використав неофіційну угоду про використання "myApp.hpp"
форми для файлів конкретних додатків та <libHeader.hpp>
форму для системних файлів бібліотеки та компілятора, тобто файлів, зазначених у /I
таINCLUDE
змінну середовища, в протягом багатьох років , думаючи , що був стандарт.
Однак стандарт C зазначає, що порядок пошуку є специфічним для реалізації, що може ускладнити переносимість. Щоб зробити це гірше, ми використовуємо варення, яке автоматично визначає, де містяться файли. Ви можете використовувати відносні або абсолютні шляхи для файлів, що включають. тобто
#include "../../MyProgDir/SourceDir1/someFile.hpp"
Старіші версії MSVS вимагали подвійних нахилів (\\), але тепер це не потрібно. Я не знаю, коли це змінилося. Просто використовуйте косої риски для сумісності з 'nix (Windows прийме це).
Якщо ви справді переживаєте про це, використовуйте"./myHeader.h"
для файлу включення в тому самому каталозі, що і вихідний код (у мого поточного дуже великого проекту є кілька дублікатів, які містять імена файлів, розкидані навколо - справді проблема управління конфігурацією).
Ось пояснення MSDN, скопійоване тут для вашої зручності).
Цитована форма
Препроцесор здійснює пошук файлів, що включають у цьому порядку:
- У тому самому каталозі, що і файл, що містить оператор #include.
- У каталогах відкритого в даний час включають файли, у зворотному порядку, в якому
вони були відкриті. Пошук починається в каталозі батьківського файлу включення та
продовжується вгору через каталоги будь-яких бабусь і дідусів, що включають файли.- Уздовж шляху, визначеного кожним
/I
варіантом компілятора.- Уздовж шляхів, які задаються
INCLUDE
змінною середовища.Кутово-кронштейна форма
Препроцесор здійснює пошук файлів, що включають у цьому порядку:
- Уздовж шляху, визначеного кожним
/I
варіантом компілятора.- Коли компіляція відбувається в командному рядку, уздовж шляхів, які задаються
INCLUDE
змінною середовища.
Принаймні, для версії GCC <= 3.0, форма кутової дужки не породжує залежність між включеним файлом та включенням одного.
Отже, якщо ви хочете генерувати правила залежності (використовуючи параметр GCC -M для sampleple), ви повинні використовувати цитовану форму для файлів, які повинні бути включені до дерева залежностей.
Для #include ""
компілятора звичайно шукає папку файлу , який містить , які включають і потім інші папки. Для #include <>
компілятора не шукайте папку поточного файлу.
<filename>
і "filename"
пошук місць, визначених реалізацією.
Коли ви використовуєте #include <ім'я файла>, попередній процесор шукає файл у каталозі файлів заголовків C \ C ++ (stdio.h \ cstdio, рядок, вектор тощо). Але, коли ви використовуєте #include "ім'я файлу": по-перше, попередній процесор шукає файл у поточному каталозі, а якщо його тут немає - він шукає його в каталозі файлів заголовків C \ C ++.
#include
директива зовсім не суворо пов'язана з файлами.
#Include з кутовими дужками буде шукати "залежний від реалізації список місць" (що є дуже складним способом сказати "системні заголовки") для включення файлу.
#Include з цитатами буде просто шукати файл (і, "залежно від реалізації", bleh). Це означає, що в звичайній англійській мові вона намагатиметься застосувати шлях / ім’я файлу, який ви кидаєте на нього, і не буде передбачати системний шлях або підробляти його в іншому випадку.
Крім того, якщо #include "" не вдається, воно перечитується як #include <> за стандартом.
Документація gcc містить (специфічний для компілятора) опис, який хоча і є специфічним для gcc, а не стандартом, але набагато простіше зрозуміти, ніж розмова в стилі адвоката про стандарти ISO.
zlib.h
шляхи пошуку в моєму "користувачеві", а в шляху пошуку системи існує інша версія, то чи #include <zlib.h>
включає версію системи та чи #include "zlib.h"
мою власну?
#include "filename" // User defined header
#include <filename> // Standard library header.
Приклад:
Ім'я файлу тут Seller.h
:
#ifndef SELLER_H // Header guard
#define SELLER_H // Header guard
#include <string>
#include <iostream>
#include <iomanip>
class Seller
{
private:
char name[31];
double sales_total;
public:
Seller();
Seller(char[], double);
char*getName();
#endif
У реалізацію класу (наприклад, Seller.cpp
та в інших файлах, які будуть використовувати цей файл Seller.h
) тепер слід включати заголовок, визначений користувачем, таким чином:
#include "Seller.h"
#include <>
призначений для попередньо визначених файлів заголовківЯкщо файл заголовка заздалегідь визначений, ви просто напишіть ім'я файлу заголовка у кутових дужках, і це виглядатиме так (припускаючи, що у нас є попередньо визначене ім'я файлу заголовка iostream):
#include <iostream>
#include " "
є для файлів заголовків, які визначає програмістЯкщо ви (програміст) написали свій власний файл заголовка, то ви б написали ім'я файла заголовка в лапки. Отже, припустимо, що ви написали заголовок, який називається myfile.h
, тоді це приклад того, як ви використовуєте директиву include для включення цього файлу:
#include "myfile.h"
Багато відповідей тут зосереджені на шляхах пошуку компілятора, щоб знайти файл. Хоча це робить більшість компіляторів, відповідний компілятор може бути попередньо запрограмований з ефектами стандартних заголовків і обробляти, скажімо,#include <list>
як комутатор, і він взагалі не повинен існувати як файл.
Це не чисто гіпотетично. Є принаймні один компілятор, який працює таким чином. #include <xxx>
Рекомендується використовувати лише зі стандартними заголовками.
#include <abc.h>
використовується для включення стандартних файлів бібліотеки. Тож компілятор перевірятиме місця, де проживають стандартні заголовки бібліотеки.
#include "xyz.h"
скаже компілятору включити визначені користувачем файли заголовків. Таким чином компілятор перевірятиме наявність цих заголовкових файлів у поточній папці або -I
визначених папках.
В C ++ включайте файл двома способами:
Перший - #include, який вказує препроцесору шукати файл у заздалегідь заданому місці за замовчуванням. Це місце часто є змінною середовища INCLUDE, яка позначає шлях до включення файлів.
Другий тип - це #include "ім'я файлу", яке спонукає препроцесора спочатку шукати файл у поточному каталозі, а потім шукати його у визначених для цього місцях.
По-перше, шукає наявність файлу заголовка в поточному каталозі, звідки викликається директива. Якщо його не знайдено, він здійснює пошук у попередньо налаштованому списку стандартних системних каталогів.
Це шукає наявність файлу заголовка в поточному каталозі, звідки виводиться директива.
Точний перелік каталогів пошуку залежить від цільової системи, налаштування GCC та місця його встановлення. Ви можете знайти список пошукового каталогу вашого компілятора GCC, запустивши його за допомогою параметра -v.
Ви можете додати додаткові каталоги до шляху пошуку, використовуючи - I dir , що призводить до пошуку dir після поточного каталогу (для форми цитування директиви) та попереду стандартних системних каталогів.
В основному форма "xxx" - це не що інше, як пошук у поточному каталозі; якщо його не знайшли, повертаючи форму
#include "header.h"
форми не точний, @personal_cloud. Я вважаю, що відповідь piCookie та Yann Droneaud є найбільш актуальною, оскільки вони визначають, звідки береться їх інформація. Я також не вважаю, що відповідь, який голосує на вершині голосів, є цілком задовільним.
#include <filename>
Використовується , коли файлова система в даний час згадується. Це файл заголовка, який можна знайти в системних місцях за замовчуванням, таких як /usr/include
або /usr/local/include
. Для власних файлів, які потрібно включити до іншої програми, ви повинні використовувати #include "filename"
синтаксис.
"<ім'я файлу>" здійснює пошук у стандартних місцях бібліотеки С
тоді як "ім'я файлу" здійснює пошук і в поточному каталозі.
В ідеалі, ви б використовували <...> для стандартних бібліотек C і "..." для бібліотек, які ви пишете і які присутні у поточному каталозі.
Просте загальне правило - використовувати кутові дужки для включення файлів заголовків, що постачаються разом із компілятором. Використовуйте подвійні лапки, щоб включити будь-які інші файли заголовків. Більшість компіляторів роблять це так.
1.9 - Файли заголовків пояснюють більш докладно про директиви перед процесором. Якщо ви початківець програміст, ця сторінка повинна допомогти вам зрозуміти все це. Я дізнався це звідси, і за цим слідкував за роботою.
#include <filename>
використовується, коли потрібно використовувати файл заголовка системи C / C ++ або бібліотеки компілятора. Ці бібліотеки можуть бути stdio.h, string.h, math.h тощо.
#include "path-to-file/filename"
використовується, коли ви хочете використовувати власний власний файл заголовка, який знаходиться у папці вашого проекту чи десь ще.
Для отримання додаткової інформації про препроцесори та заголовки. Читайте С - попередники .
#include <filename>
#include "filename"
#include <filename>
та шукайте цей заголовок у місці, де зберігаються файли заголовків системи.#include <filename>
.Щоб побачити порядок пошуку у вашій системі за допомогою gcc на основі поточної конфігурації, ви можете виконати таку команду. Більш детально про цю команду ви можете знайти тут
cpp -v /dev/null -o /dev/null
Apple LLVM версія 10.0.0 (clang-1000.10.44.2)
Мета: x86_64-apple-darwin18.0.0
Модель нитки: posix InstalledDir: Бібліотека / Розробник / CommandLineTools / usr / bin
"/ Бібліотека / Розробник / CommandLineTools / usr / bin / clang" -cc1-трипл x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-use -Werror = deprected-objc-isa-use -E -disable-free - enable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-строгий-return -masm-verbose - munwind-table-target-cpu penryn -warf-column-info -debugger-tuning = lldb -target-linker-версія 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 - isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I / usr / local / include -fdebug-compilation-dir / Users / hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extension-block-signature -fobjc-runtime = macosx-10.14.0 -fmax-type-align = 16 -fdiagnostics-show-option -fcolor-діагностика -traditional-cpp -o - -xc / dev / null
clang -cc1 версія 10.0.0 (clang-1000.10.44.2) ціль за замовчуванням x86_64-apple-darwin18.0.0 ігнорування неіснуючого каталогу "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ігнорування неіснуючого каталог "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." пошук починається тут:
#include <...> пошук починається тут:
/ usr / local / include
/ Бібліотека / розробник / CommandLineTools / usr / lib / clang / 10.0.0 / включати
/ Бібліотека / розробник / CommandLineTools / usr / включати
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/ Library / Developer / CommandLineTools / SDK / MacOSX10.14.sdk / Система / Бібліотека / Рамки (рамковий каталог)
Кінець списку пошуку.
Існує два способи написання #include заяви. Це:
#include"filename"
#include<filename>
Сенс кожної форми є
#include"mylib.h"
Ця команда шукатиме файл mylib.h
у поточному каталозі, а також вказаний список каталогів, як згадувалося n, включаючи шлях пошуку, який, можливо, був налаштований.
#include<mylib.h>
Ця команда шукатиме файл лише mylib.h
у вказаному списку каталогів.
Шлях пошуку включити - це не що інше, як список каталогів, в яких можна було б шукати файл, який включається. Різні компілятори C дозволяють вам задати шлях пошуку різними способами.