Як читати введення користувача в C за допомогою scanf

1

Константи зручні. Вони статичні. Але вони також нудні.

Програма, яка завжди складає 5 та 7, робить рівно одну річ. Вона не адаптується. Вона не взаємодіє. Щоб зробити код C дійсно корисним для кінцевих користувачів, потрібно перестати жорстко задавати значення і почати прислухатися.

Інструмент для цього завдання – scanf.

Від жорстко заданих значень до динамічних

У попередньому прикладі змінні a та b, ймовірно, ініціалізувалися фіксованими числами. Логіка була твердою. Висновок був передбачуваним. Якщо ви хотіли змінити додавання, вам доводилося редагувати вихідний код, перекомпілювати його та запускати знову.

Це незручно для користувача.

Щоб виправити це, нам потрібно захоплювати введення з консолі. Стандартна бібліотека stdio.h обробляє як висновок (printf), так і введення (scanf). Перехід від констант до значень, що визначається користувачем, перетворює програму з демонстрації калькулятора на простий утиліту.

Синтаксис scanf

Ось код, який це реалізує:

`

Логіка проста. Вона лінійна.

  1. Програма запитує перше ціле число.
  2. scanf очікує введення.
  3. Користувач вводить число та натискає Enter.
  4. Значення зберігається в a.
  5. Повторюється для b.
  6. Складає їх.
  7. Виводить результат.

Плутанина з амперсандом (&)

Найпоширеніша точка відмови для початківців тут – символ &.

Подивіться на цей рядок:
`scanf(“%d”, &a);

Чому тут є амперсанд? Чому не просто scanf("%d", a);?

Змінні в C це не просто імена. Це адреси пам’яті. Коли ви повідомляєте int a, ви резервуєте фрагмент оперативної пам’яті. scanf не хоче * значення * a, тому що a в даний момент порожня (або містить сміття). scanf потрібна адреса, за якою вона може записати нове значення.

& – це оператор “адреса змінної”. Він передає scanf місце у пам’яті, щоб він міг безпосередньо змінювати a. Без нього ви вказуєте scanf на випадковий фрагмент пам’яті. Програма швидше за все аварійно завершиться або, що гірше, зіпсує ваші дані.

Ключова думка: printf використовує значення. scanf потребує адреси.

Специфікатори формату

Ви використовували %d в printf для відображення цілого числа. Ви повинні використовувати %d у scanf для його читання.

Невідповідність цих специфікаторів призводить до невизначеної поведінки. Якщо ви спробуєте прочитати ціле число, використовуючи %f (число з плаваючою комою), дані будуть інтерпретовані неправильно. Структура пам’яті числа з плаваючою комою відрізняється від структури цілого числа. scanf запише сирі біти числа з плаваючою комою

Як scanf та printf обробляють змінні у C

Компіляція та запуск коду – це момент, коли теорія зустрічається з реальністю. Якщо пропустити цей крок, ви просто гадаєте. Функція scanf працює аналогічно printf щодо форматних рядків, але висуває більш суворі вимоги до введення. Перед змінними типами char, int, float та структурами необхідно ставити оператор адреси (& ). Без нього програма аварійно завершує роботу.

Чому scanf вимагає оператора адреси

Знак амперсанда не є необов’язковим. Він вказує компілятору зберігати введені дані безпосередньо на адресу пам’яті змінної. Якщо його опустити, то виникає помилка часу виконання. Спробуйте навмисно прибрати його. Спостереження за аварійним завершенням роботи програми є більш повчальним, ніж читання про це. Це наочно демонструє, наскільки тендітним може бути C при неправильній роботі з адресами пам’яті.

Як printf форматує висновок для користувача

printf надсилає текст у стандартний висновок. Найпростіша версія виглядає так:

`

Вона виводить слово Hello без перекладу рядка. Порівняйте це з:

`

\n додає символ перекладу рядка. Він завершує поточний рядок. Без нього наступний висновок з’явиться на тому ж рядку. Це невелика деталь, яка погіршує читання, якщо її ігнорувати.

Як вбудовувати змінні в рядки printf

Щоб вивести змінну, використовується заповнювач (плейсхолдер). Специфікатор %d замінює себе значенням цілісної змінної. Розглянемо приклад:

`

Можна використовувати послідовні виклики printf для змішування тексту та змінних, але це неефективно:

`

Чистіший підхід полягає у вбудовуванні заповнювача безпосередньо в рядок:

`

Також можна використовувати кілька наповнювачів:

`

Кількість заповнювачів має точно відповідати кількості змінних. Типи також мають збігатися. Три специфікатори %d вимагають трьох параметрів типу int, перерахованих у тому порядку. Невідповідність типів чи кількості параметрів призводить до невизначеної поведінки.

Які заповнювачі обробляють різні типи C

printf підтримує стандартні типи C за допомогою певних специфікаторів формату:

  • int використовує %d
  • float використовує %f
  • char використовує %c
  • рядки символів використовують %s

Детальну документацію можна знайти, ввівши команду man 3 printf на машині з UNIX. Інші компілятори надають аналогічні довідкові сторінки чи файли допомоги.

Поширені помилки в C, яких слід уникати

Регістр символів має суворе значення. Printf або PRINTF призведуть до помилки. Функція повинна бути записана малими літерами: printf.

  • Забутий & в scanf викликає аварійне завершення роботи під час виконання.
  • Невідповідність кількості параметрів в printf або scanf призводить до викривлення виведення.
  • Використання неоголошених змінних викликає помилки компіляції.

Налагодження цих проблем часто зводиться до перевірки синтаксису насамперед. Компілятор зазвичай точно вказує, де є невідповідність. Вам залишається лише прочитати повідомлення про помилку.