- •1.1 Перші кроки
- •1.2 Змінні й арифметичні вирази
- •1.3 Твердження for
- •1.4 Символічні константи
- •1.5 Ввід і вивід знаків
- •1.5.1 Копіювання файла
- •1.5.2 Відлік символів
- •1.5.3 Відлік рядків
- •1.6 Масиви
- •1.7 Функції
- •1.8 Аргументи - виклик за значенням
- •1.9 Символьні масиви
- •1.10 Зовнішні змінні й область дії
- •2.1 Назви змінних
- •2.2 Типи даних і розміри
- •2.3 Константи
- •2.4 Оголошення
- •2.5 Арифметичні операції
- •2.6 Реляційні та логічні оператори
- •2.7 Перетворення типів
- •2.8 Оператори приросту та спаду
- •2.9 Розрядні оператори
- •2.10 Оператори та вирази присвоєння
- •2.11 Вирази умов
- •2.12 Пріоритет і послідовність обчислення
- •3.1 Вирази та блоки
- •3.3 Else if
- •3.4 Switch
- •3.5 Цикли while та for
- •3.6 Цикли do-while
- •3.7 Break і continue
- •3.8 Goto та мітки
- •4.1 Основні знання про функції
- •4.2 Функції, які не повертають цілих
- •4.3 Зовнішні змінні
- •4.4 Правила області дії
- •4.5 Файли заголовка
- •4.6 Статичні змінні
- •4.7 Регістрові змінні
- •4.8 Структура блоків
- •4.10 Рекурсія
- •4.11 Препроцесор c
- •4.11.1 Включення файлів
- •4.11.2 Заміна макросів
- •4.11.3 Обумовлене включення файлів
- •5.1 Покажчики й адреси
- •5.2 Покажчики й аргументи функцій
- •5.3 Покажчики та масиви
- •5.4 Арифметика адрес
- •5.5 Покажчики на символи та функції
- •5.6 Масив покажчиків; покажчики на покажчики
- •5.7 Багатовимірні масиви
- •5.8 Ініціалізація масиву покажчиків
- •5.9 Покажчики в порівнянні з багатовимірними масивами
- •5.10 Аргументи командного рядка
- •5.11 Покажчики на функції
- •5.12 Складні оголошення
- •6.1 Основні поняття про структури
- •6.2 Структури та функції
- •6.3 Масиви структур
- •6.4 Покажчики на структури
- •6.5 Структури зі зворотнім звертанням
- •6.6 Пошук по таблиці
- •6.7 Typedef
- •6.8 Сполуки
- •6.9 Розрядні поля
- •7.1 Стандартний ввід і вивід
- •7.2 Форматований вивід - printf
- •7.3 Списки аргументів довільної довжини
- •7.4 Форматований ввід - scanf
- •7.5 Доступ до файлів
- •7.6 Обробка помилок - stderr і exit
- •7.7 Ввід і вивід рядків
- •7.8 Додаткові функції
- •7.8.1 Операції з ланцюжками
- •7.8.2 Перевірка і перетворення класів символів
- •7.8.3 Ungetc
- •7.8.4 Виконання команд
- •7.8.5 Керування пам'яттю
- •7.8.6 Математичні функції
- •7.8.7 Генератор випадкових чисел
- •8.1 Дескриптори файлів
- •8.2 Низькорівневий ввід/вивід - read і write
- •8.3 Open, creat, close, unlink
- •8.4 Довільний доступ - lseek
- •8.5 Приклад: втілення fopen і getc
- •8.6 Приклад - перелік вмісту каталогів
- •8.7 Приклад - розподільник пам'яті
1.6 Масиви
Тепер, напишімо програму, яка підрахує кількість кожної цифри, пропусків (пробіл, табуляція і знак нового рядка) і решти знаків. Це трохи штучно, але дозволяє проілюструвати декілька аспектів C в одній програмі.
У нас буде дванадцять категорій можливого вводу, тож має зміст використати масив для утримування числа повторень тієї самої цифри, замість десяти окремих змінних. Ось одна з можливих версій програми:
#include <stdio.h>
/* лічить цифри, пропуски та інші знаки */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
Вивід самої програми може виглядати як
digits = 9 3 0 0 0 0 0 0 0 1, white space = 123, other = 345
Оголошення
int ndigit[10];
описує ndigit, як масив з 10-и цілих. Індексація масивів завжди починається з нуля в C, тож елементами будуть ndigit[0], ndigit[1], ..., ndigit[9]. Це відображено у циклах for, які ініціалізують і виводять масив.
Індексом може бути будь-який вираз типу int, включаючи цілочисельну змінну, як от i, та цілочисельні константи.
Ця програма покладається на символьне представлення цифр. Так, наприклад, перевірка
if (c >= '0' && c <= '9')
визначає, чи символ, який міститься в c є цифрою. Якщо так, числовим значенням цієї цифри буде
c - '0'
Це працює тільки за умови, що символи '0', '1', ..., '9' мають послідовно-зростаючі значення. На щастя, це справджується в усіх наборах символів.
За означенням, char — це просто малі цілі, тож змінні і сталі типу char тотожні int в арифметичних виразах. Це природньо та зручно; наприклад, c - '0' є цілочисельним виразом зі значенням між 0 і 9, що відповідають знакам від '0' до '9', збереженим у c, тож чинним індексом масиву ndigit.
Рішення того, чи знак є цифрою, пропуском, чи чимось іншим здійснюється послідовністю
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
Конструкція
if (умова1)
твердження1
else if (умова2)
твердження2
...
...
else
твердження
зустрічається доволі часто в програмах, як один з способів виразити розгалуження рішень. Умови розглянуто по-порядку, починаючи зверху, до тих пір, доки одна з умов не справдиться, у разі чого буде виконано відповідне твердження, і ціла конструкція закінчить своє існування. Якщо жодна з умов не є істинною, тоді буде виконано твердження після останнього else, якщо таке існує. Якщо ж останнє else і відповідне твердження відсутні, як у випадку з програмою відліку слів, тоді жодної дії не відбудеться. Можна використати будь-яку кількість
else if (умова)
твердження
груп, між початковим if і кінцевим else.
Щодо стилю, то радимо форматувати цю конструкцію саме так, як ми показали; якби кожний ifвирівнювався з попереднім else, довга черга розгалужень змістилась би до правого боку сторінки.
Твердження switch, яке буде розглянуто у Розділі 4, — це інший спосіб написання розгалуження рішень, особливо корисне у випадку, коли умова складається з якогось цілого чи символьного виразу, який порівнюється з набором констант. Для контрасту, у Розділі 3.4 ми представимо switch-версію цієї програми.
Вправа 1-13. Напишіть програму, яка би виводила гістограму довжин слів вводу. Гістограму легко намалювати горизонтальними стрижнями; вертикальну орієнтацію гістограми втілити трохи складніше.
Вправа 1-14. Напишіть програму виводу гістограми частоти різних знаків вводу.
