Урок 2. Переменные, типы, printf и scanf
Переменная — это место в памяти, у которого есть имя и тип. Тип говорит, что в переменной хранится: целое число, дробное число или символ. В C тип указывается заранее и потом не меняется.
#include <stdio.h>
int main(void) {
int age = 15;
double height = 1.72;
char grade = 'A';
printf("Возраст: %d\n", age);
printf("Рост: %f\n", height);
printf("Оценка: %c\n", grade);
age = age + 1;
printf("Через год: %d\n", age);
return 0;
}Возраст: 15
Рост: 1.720000
Оценка: A
Через год: 16Запись int age = 15; объявляет переменную (тип int, имя age) и сразу кладёт в неё значение. Знак = в C означает не равенство, а присваивание: «положить в переменную слева значение справа». Поэтому age = age + 1 читается как «взять age, прибавить 1 и положить обратно».
Имена переменных
- Только латинские буквы, цифры и
_, первой — буква или_:count,max_value,x2. - Большие и маленькие буквы различаются:
sumиSum— разные переменные. - Нельзя брать служебные слова языка:
int,if,for,returnи другие. - Давайте понятные имена:
totalлучше, чемt, если переменная живёт дольше пары строк.
Основные типы
| Тип | Что хранит | Размер на обычном компьютере | printf | scanf |
|---|---|---|---|---|
int | целые от −2 147 483 648 до 2 147 483 647 | 4 байта | %d | %d |
long long | целые примерно до ±9,2·10¹⁸ | 8 байт | %lld | %lld |
double | дробные, 15–16 значащих цифр | 8 байт | %f | %lf |
float | дробные, около 7 значащих цифр | 4 байта | %f | %f |
char | один символ (точнее, маленькое целое число) | 1 байт | %c | %c |
Стандарт C не называет точные размеры типов, он задаёт только наименьшие. Но на всех распространённых компьютерах размеры именно такие. Узнать размер можно оператором sizeof; его результат выводится форматом %zu.
Для дробных чисел берите double: у float мало точности, он нужен там, где важна память. Дробная часть отделяется точкой: 3.14, а не 3,14 — и в программе, и при вводе.
Если число не помещается в int (например, произведение двух чисел около миллиона), берите long long. Что бывает при переполнении — в справке Переполнение int.
Переменная внутри функции без начального значения содержит случайный мусор, а не ноль. Чтение такой переменной — ошибка: программа может выдавать разные ответы при каждом запуске. Ключ -Wall предупреждает об этом сообщением is used uninitialized.
Арифметика
#include <stdio.h>
int main(void) {
int a = 17, b = 5;
printf("%d + %d = %d\n", a, b, a + b);
printf("%d - %d = %d\n", a, b, a - b);
printf("%d * %d = %d\n", a, b, a * b);
printf("%d / %d = %d\n", a, b, a / b);
printf("%d %% %d = %d\n", a, b, a % b);
printf("17.0 / 5 = %f\n", 17.0 / 5);
printf("(double)a / b = %.2f\n", (double)a / b);
return 0;
}17 + 5 = 22
17 - 5 = 12
17 * 5 = 85
17 / 5 = 3
17 % 5 = 2
17.0 / 5 = 3.400000
(double)a / b = 3.40Главное здесь — деление целых: 17 / 5 даёт 3, дробная часть отбрасывается. Остаток от деления даёт оператор %: 17 % 5 равно 2. Чтобы получить 3.4, хотя бы одно число должно быть дробным: 17.0 / 5 или (double)a / b. Запись (double)a называется приведением типа: значение a превращается в double. Подробнее — в справке Почему 5 / 2 равно 2.
Чтобы вывести сам знак процента, в printf пишут %%.
Сокращённые записи: x += 5 — то же, что x = x + 5 (так же -=, *=, /=, %=); x++ увеличивает x на 1, x-- уменьшает на 1.
Дробное число, записанное в переменную типа int, теряет дробную часть без округления: после int n = 3.99; в n будет 3.
Вывод: printf
Первый аргумент printf — строка формата. Обычный текст выводится как есть, а на место каждого спецификатора (%d, %f…) подставляется следующий аргумент по порядку. Число и типы аргументов должны совпадать со спецификаторами — иначе выводится мусор, а -Wall предупреждает. Подробнее — в справке warning: format specifies type.
#include <stdio.h>
int main(void) {
double price = 12.5;
int count = 3;
char currency = 'P';
printf("%d шт. по %.2f = %.2f\n", count, price, count * price);
printf("[%5d]\n", count);
printf("[%-5d]\n", count);
printf("[%8.3f]\n", price);
printf("Символ %c, его код %d\n", currency, currency);
printf("int занимает %zu байта\n", sizeof(int));
return 0;
}3 шт. по 12.50 = 37.50
[ 3]
[3 ]
[ 12.500]
Символ P, его код 80
int занимает 4 байта%.2f— два знака после точки (с округлением), просто%f— всегда шесть знаков.%5d— занять не меньше пяти позиций, выровнять вправо;%-5d— влево.%8.3f— восемь позиций всего, из них три знака после точки.char— это число:%cвыводит символ,%d— его код (у латинскойPкод 80).
Ввод: scanf
scanf читает данные с клавиатуры по такой же строке формата:
#include <stdio.h>
int main(void) {
int a, b;
double r;
scanf("%d %d", &a, &b);
scanf("%lf", &r);
printf("Сумма: %d\n", a + b);
printf("Среднее: %.1f\n", (a + b) / 2.0);
printf("Площадь круга: %.3f\n", 3.14159265358979 * r * r);
return 0;
}7 4
2.5Сумма: 11
Среднее: 5.5
Площадь круга: 19.635Что важно знать про scanf:
- Перед именем переменной ставится
&— «адрес переменной»:scanfдолжен знать, куда записать число. Без&программа обычно падает. Почему так — станет ясно в уроке про указатели. - Для
doubleформат вscanf—%lf, а не%f. Вprintfдляdoubleгодятся оба. Разбор — в справке Чем %f отличается от %lf. - Числа при вводе можно разделять пробелами, табуляцией или переводами строки:
scanf("%d %d", …)прочитает и «7 4», и «7» и «4» на разных строках. scanfвозвращает количество прочитанных значений. Если вместо числа ввести буквы, он вернёт 0, а переменная останется без значения.
В олимпиадных задачах и автоматических проверках не выводите подсказки вроде «Введите число:» — ответ сверяется с образцом до символа, и лишний текст делает его неверным. В учебных программах для себя подсказки, наоборот, удобны.
Константы
Значение, которое не должно меняться, объявляют с const: const double PI = 3.14159265358979;. Попытка присвоить такой переменной новое значение — ошибка сборки. Ещё один старый способ — #define PI 3.14159265358979 в начале файла: перед сборкой каждое PI в тексте заменяется числом.
Коротко
- Переменная объявляется с типом:
int n = 5;.=— присваивание, а не сравнение. - Целые —
int(до ~2,1 млрд) иlong long, дробные —double, символ —charв одинарных кавычках. 17 / 5равно 3,17 % 5равно 2; для дробного результата нужно дробное число:17.0 / 5.printf:%d,%lld,%f,%.2f,%c,%%;scanf: те же, но дляdouble—%lf.- В
scanfперед переменной —&. Переменная без начального значения содержит мусор.