Функція Scanf C: опис
Функція scanf C - опис
scanf() – це функція, розташована в заголовочном файлі stdio.h(C) і cstdio(C++), вона також називається форматованим введення даних в програму. scanf читає символи з стандартного потоку вводу (stdin) і перетворює їх у відповідності з форматом, після чого записує в зазначені змінні. Формат – означає, що дані при вступі наводяться до певного виду. Таким чином, функція scanf C описується:scanf("%формат", &переменная1[, &переменная2,[…]]), де змінні передаються у вигляді адрес. Причина такого способу передачі змінних в функцію очевидна: в результаті роботи вона повертає значення, що вказує на наявність помилок, тому єдиним способом змінювати значення змінних є передача за адресою. Також, завдяки такому способу, функція може обробляти дані будь-яких типів. Деякі програмісти з-за аналогією з іншими мовами називають функції, подібні scanf() або printf(), процедурами. Scanf дозволяє здійснювати введення всіх базових типів мови: char, int, float, string і т. д. У випадку з змінними типу string немає потреби вказувати знак адреси - «&», так як змінна типу string є масивом, і ім'я її є адреса першого елемента масиву в пам'яті комп'ютера.
Формат введення даних або керуюча рядок
Почнемо з розгляду приклад використання функції scanf C з опису. #include
int main()
{
int x;
while (scanf("%d", &x) == 1)
printf("%dn", x);
return 0; //вимога linux-систем
}
Формат вводу складається з наступних чотирьох параметрів: %
У загальному випадку символи, складові рядок формату, поділяються на:
- специфікатори формату – все, що починається з символу %;
- розділові або пробільні символи - ними вважаються пробіл, табуляція(t), нова рядок (n);
- символи, відмінні від пробільних.
Функція може виявитися небезпечною.
Використовуйте замість scanf() функцію scanf_s().
(повідомлення від Visual Studio)
Тип, або специфікатори формату, або літери перетворення, або контролюючі символи
Опис scanf C зобов'язане містити, як мінімум, спецификатор формату, який вказується в кінці виразів, що починаються з символу «%». Він повідомляє програмі тип даних, який слід очікувати при введенні з клавіатури. Список всіх спецификаторов формату в таблиці нижче.
№ | Тип | Значення |
1 | %c | Програма очікує введення символу. Змінна для запису повинна мати символьний тип char. |
2 | %d | Програма очікує введення десяткового числа цілого типу. Змінна повинна мати тип int. |
3 | %i | Програма очікує введення десяткового числа цілого типу. Змінна повинна мати тип int. |
4 | %e, %E | Програма очікує введення числа з плаваючою точкою (комою) в експоненційної формі. Змінна повинна мати тип float. |
5 | %f | Програма очікує введення числа з плаваючою точкою (комою). Змінна повинна мати тип float. |
6 | %g, %G | Програма очікує введення числа з плаваючою точкою (комою). Змінна повинна мати тип float. |
7 | %a | Програма очікує введення числа з плаваючою точкою (комою). Змінна повинна мати тип float. |
8 | %o | Програма очікує введення восьмеричного числа. Змінна повинна мати тип int. |
9 | %s | Програма очікує введення рядка. Рядком вважається набір символів до першого зустрінутого розділового символу. Змінна повинна мати тип string. |
10 | %x %X | Програма очікує введення шістнадцяткового числа. Змінна повинна мати тип int. |
11 | %p | Змінна очікує введення покажчика. Змінна повинна мати тип покажчика. |
12 | %n | Записує в змінну ціле число, рівне кількості лічених до поточного моменту символів функцією scanf. |
13 | %u | Програма зчитує беззнакове ціле число. Тип змінної повинен бути unsigned integer. |
14 | %b | Програма очікує введення двійкового числа. Змінна повинна мати тип int. |
15 | %[] | Набір сканованих символів. Програма очікує введення символів, з обмеженого пулу, зазначеного між квадратними дужками. scanf буде працювати до тих пір, поки на потоці вводу знаходяться символи з вказаної множини. |
16 | %% | Знак «%». |
Символи в рядку формату
Символ зірочки (*)
Зірочка (*) – це прапор, який вказує, що операцію присвоєння треба придушити. Зірочка ставиться відразу після символу «%». Наприклад,
scanf("%d%*c%d", &x, &y); //ігнорувати символ між двома цілими числами.
scanf("%s%*d%s", str, str2); //ігнорувати ціле число, між двома рядками.
Тобто, якщо ввести в консолі рядок «45-20» програма зробить наступне:
<script type="text/javascript">
var blockSettings2 = {blockId:"R-A-70350-2",renderTo:"yandex_rtb_R-A-70350-2",async:!0};
if(document.cookie.indexOf("abmatch=") >= 0){
blockSettings2 = {blockId:"R-A-70350-2",renderTo:"yandex_rtb_R-A-70350-2",statId:70350async:!0};
}
!function(a,b,c,d,e){a[c]=a[c]||[],a[c].push(function(){Ya.Context.AdvManager.render(blockSettings2)}),e=b.getElementsByTagName("script")[0],d=b.createElement("script"),d.type="text/javascript",d.src="//an.yandex.ru/system/context.js",d.async=!0e.parentNode.insertBefore(d,e)}(this,this.document,"yandexContextAsyncCallbacks");
- Змінної «x» буде присвоєно значення 45.
- Змінної y буде присвоєно значення 20.
- А знак мінус(тире) «-» буде проігноровано завдяки «%c».
Ширина (або ширина поля)
Це ціле число між знаком «%» і специфікатором формату, яке визначає максимальну кількість символів для зчитування за поточну операцію читання.
scanf(" s", str); //прочитати перші 20 символів з потоку вводу
Слід мати на увазі кілька важливих моментів:
- scanf припинить свою роботу, якщо зустріне розділовий символ, навіть якщо не вважав 20 символів.
- Якщо на введення подається більше 20 символів, в змінну str будуть записані лише перші 20 з них.
Модифікатори типу (або точність)
Це спеціальні прапори, які модифікують тип даних, очікуваних до введення. Прапор вказується зліва від специфікатора типу:
<script type="text/javascript">
var blockSettings3 = {blockId:"R-A-70350-3",renderTo:"yandex_rtb_R-A-70350-3",async:!0};
if(document.cookie.indexOf("abmatch=") >= 0){
blockSettings3 = {blockId:"R-A-70350-3",renderTo:"yandex_rtb_R-A-70350-3",statId:70350async:!0};
}
!function(a,b,c,d,e){a[c]=a[c]||[],a[c].push(function(){Ya.Context.AdvManager.render(blockSettings3)}),e=b.getElementsByTagName("script")[0],d=b.createElement("script"),d.type="text/javascript",d.src="//an.yandex.ru/system/context.js",d.async=!0e.parentNode.insertBefore(d,e)}(this,this.document,"yandexContextAsyncCallbacks");
- L або l (маленька L) При використанні «l» з спецификаторами d, i, o, u, x, прапор повідомляє програмі, що очікується введення даних типу long int. При використанні «l» зі специфікатором e або f, прапор повідомляє програмі, що вона повинна чекати введення значення типу double. Використання «L» повідомляє програмі, що очікується значення типу long double. Використання «l» з спецификаторами «c» і «s» повідомляє програмі, що очікуються двобайтові символи типу wchar_t. Наприклад, "%lc", "%ls", "%l[asd]".
- h – прапор, який вказує на тип short.
- hh – означає, що змінна є покажчиком на значення типу signed char або unsigned char. Прапор можна використовувати з спецификаторами d, i, o, u, x, n.
- ll (дві маленькі L) – означає, що змінна є покажчиком на значення типу signed long long int або unsigned long long int. Прапор використовується з спецификаторами: d, i, o, u, x, n.
- j – означає, що змінна є покажчиком на тип intmax_t або uintmax_t з заголовкого файлу stdint.h. Використовується з спецификаторами: d, i, o, u, x, n.
- z – означає, що змінна є покажчиком на тип size_t, визначення якого знаходиться в stddef.h. Використовується з спецификаторами: d, i, o, u, x, n.
- t – позначає, що змінна є покажчиком на тип ptrdiff_t. Визначення на цей тип знаходиться в stddef.h. Використовується з спецификаторами: d, i, o, u, x, n.
Більш явно картину з модифікаторами можна представити у вигляді таблиці. Такий опис scanf C для програмістів буде зрозуміліше.
Інші символи
Будь-які символи, які будуть зустрінуті в форматі, будуть відкидатися. При цьому варто зазначити, що наявність у керуючої рядку пробільних або розділових символів (нова рядок, пробіл, табуляція) може призводити до різної поведінки функції. В одній версії scanf() буде читати без збереження будь-яку кількість роздільників до моменту, поки не зустріне символ, відмінний від роздільника, а в іншій версії – пробіли (тільки вони) не грають ролі і вираз "%d + %d" еквівалентно "%d+%d".
Приклади
Розглянемо ряд прикладів, що дозволяють помізкувати і точніше зрозуміти роботу функції.
scanf("%3s", str); //якщо ввести в консолі рядок «1d2s3d1;3», str запишеться тільки «1d2»
scanf("%dminus%d", &x, &y); //символи «minus» між двома числами будуть відкинуті
scanf("%5[0-9]", str); //введення символів у str буде відбуватися до тих пір, поки їх не буде 5 і символи є числами від 0 до 9.
scanf("%lf", &d); //очікується введення даних типу double
scanf("%hd", &x); //очікується число типу short
scanf("%hu", &y); //очікується число типу unsigned short
scanf("lx", &z); //очікується число типу long int
З наведених прикладів видно, як змінюється очікуване число з використанням різних символів.