Тема 2.2. Типы данных 2.2.webp
Целочисленный тип

Объявление и инициализация переменных

Переменная — это некое пространство памяти, которому присвоено имя и в которое могут помещаться определенные данные.

Прежде чем использовать переменные, их нужно объявить, указав имя переменной и тип данных. Объявлять переменные можно в любом месте программы, но лучше в самом ее начале. Тип уже объявленной переменной потом изменить нельзя.

Знак  =  это оператор присваивания в C++. Переменную необходимо сразу инициализировать – т.е. присвоить ей первоначальное значение.

Пример:

Объявления и инициализации переменных:

221_01

Если переменную не инициализировать, то она будет хранить "мусор", т.е. остатки данных, которые хранились в этом участке памяти до того, как там расположилась переменная. Среда разработки Visual Studio не позволит использовать такую переменную:

221_02

Имя переменной должно быть содержательным – т.е. из названия переменой должно быть понятно, что в ней хранится. Имя переменной должно начинаться с маленькой буквы. Если имя состоит из нескольких слов, то следует использовать стиль camelCase: второе, третье и т.д. слова должны начинаться с большой буквы, например:

221_03

Так нельзя:

221_04

Другие стили кода:

змеиный_стиль puch_something_to_first_queue Удобный, когда имя переменной короткое. Но длинный как чертова змея, когда слов много. СтильПаскаля GetItem, SetItem, Convert Паскаль вообще был сильным. Этот способ выглядит очень приятно, но мало где используется. верблюжийСтиль puch, reverse, beginBuildingApp Очень распространён С одним словом выглядит вообще отлично, но когда слов много, непонятно, почему первое обидели. шашлычный-стиль start-cooking-kebab, are-you-insane Выглядит аппетитно и легко читается. Но любой здравомыслящий язык программирования не примет вас с таким стилем. СТИЛЬ_КРИЧАЩЕЙ_ЗМЕИ LOOK_AT_THIS, MY_CODE_IS_AMAZING Показывает ваше привосходство в коде. Пусть все знают, кто тут самый крутой программист! Но при чтении вытекают глаза. безстиля abstohoiytvkbsshhhbut Выглядит профессионально. Но на самом деле нет, просто остановитесь уже.

Нежелательно объявлять несколько переменных одной строкой, т.к. это может привести к путанице (особенно, если объявляются указатели):

221_06

Нельзя писать несколько инструкций в одну строку:

221_07

Каждая инструкция должна занимать отдельную строку кода:

221_08

Константы и переменные вместо "магических чисел"

Использование констант оправдано несколькими факторами. Во-первых, имя константы более информативно, чем число. Во-вторых, если требуется поменять это значение, то проще изменить значение одной константы, чем выискивать и изменять "магическое число" во всей программе. Чтобы добавить константу, используется ключевое слово const. Пример:

221_09

Так нельзя:

221_10

Простые типы данных

Математические операции

Бинарными называются операторы, которые имеют два аргумента.

  • В выражении –x оператор унарный.
  • В выражении x – y оператор бинарный.

Унарный плюс, унарный минус

221_11

В зависимости от задачи можно записать результат вычисления в отдельную переменную или сразу выполнить вычисления на выводе:

221_12
221_13

% (бинарный)Остаток от деления

Этот оператор означает получение остатка от деления. Например, 5 входит в 14 два раза, и остаток при этом составляет 4. Т.е., остаток от деления 14 на 5 равно 4.

Пошаговое решение:

  1. 14 % 5 равно 14 – (14 / 5) * 5
  2. 14 – 2 * 5
  3. 14 – 10
  4. 4
221_14

Для переменных вещественного типа оператор получения остатка от деления не предназначен, поскольку он целиком основан на использовании округления до целых (14 / 5 = 2).

Операторы инкремента и декремента могут находиться либо перед аргументом (префиксная форма), либо после него (постфиксная форма).

221_15
221_16

Переменной y присваивается уже увеличенное префиксным оператором инкремента значение x, а переменной b передается еще не увеличенное постфиксным оператором значение a.

Команды инкремента и декремента выполняются быстрее, чем команды сложения и вычитания.

221_17_1
221_17_2
221_17_3

При выполнении инкремента инкрементируемой переменной присваивается новое значение. При выполнении операции сложения без оператора присваивания значение переменной остается прежним. 

Пример:

221_18

Сокращенные операторы (неинформативные идентификаторы здесь и далее использованы с целью упрощения чтения кода):

221_19
221_20

Ограничения, налагаемые на целые числа

1. Округление до целых значений

Требуется вычислить среднее трех чисел: a, b и c. Среднее значение вычисляется по формуле:

(a + b + c)/3

Например, если a=1; b=2 и c=2, то среднее будет равно 1 целая и 2/3 или 1,666... Полученный результат приводится к целому значению, просто отбрасывая его дробную часть. При этом 1,666 утратит свой “дьявольский” остаток и превратится в 1.

Даже если попытаться решить эту задачу иным способом, получится еще хуже:

a/3 + b/3 + c/3 = 0 + 0 + 0 = 0

Поэтому для задач с делением, выведением из-под корня и т.п. лучше использовать вещественные числа.

2. Ограничения диапазона

Максимальным значением обычной целочисленной переменной является число 2 147 483 647, минимальным – - 2 147 483 647, т.е. общий диапазон (от -(232) до +232-1) – около 4 млрд. чисел (зависит от компилятора). Максимальное число (около 2 млрд.) может оказаться недостаточным.

C++ позволяет объявлять целые числа как беззнаковые. Целое число типа unsigned int может принимать значения от 0 до +4 294 967 295. Можно объявить переменную просто как unsigned, опустив объявление int, которое подразумевается неявно.

Целочисленное переполнение

221_21

Если целочисленной переменной задать максимальное значение, а потом прибавить к нему единицу, то значение сбрасывается на минимум. 

Пример:

с типом unsigned:

221_22

Если к максимальному прибавить 2, то значение будет равно минимум+1 и т.д.

Пример:

с типом int:

221_23
221_24

В информации, которая выводится на экран монитора, всегда должны быть пояснения для пользователя: что именно выводится, и какие действия пользователь должен выполнить.

Программный код следует делить на блоки с помощью пустых строк.

Пример:

221_25

То же самое можно вывести, используя только один "cout". Сравните с предыдущим листингом:

221_26

Объект cin >>

221_27

Объект std::cin забирает вводимую пользователем информацию из стандартного потока ввода, которым обычно является клавиатура.

221_28

Функция Sleep()для паузы

Функция Sleep() отсчитывает время в миллисекундах. Для ее использования необходимо подключить библиотеку windows.h.

Пример:

221_29

Практическое занятие Написание программ с целыми числами

Написать программы, которые решают следующие задачи:

1. У Маши было 12 конфет. У Миши было 10 конфет. У Саши – 2, а у Кеши – ни одной. Маша и Миша отдали, соответственно,  Саше и Кеше по 3 конфеты.

Программа должна посчитать и вывести, сколько конфет стало у каждого.

Пример вывода:

222_01

2. Известно, что автомобиль ехал без остановки 3 часа со скоростью 60 км/ч.

Какое расстояние проехал автомобиль?

222_02

3. Известно, что длины смежных сторон прямоугольника равны 5 см и 7 см.

Вывести периметр и площадь этого прямоугольника.

4. Написать программу для перевода количества лет, введенного пользователем, в секунды.

222_03

5. Написать программу, в результате работы которой значения двух переменных действительно поменяются местами.

Выставить задержку вывода – 7 секунд.

222_04

6. Дано натуральное (т.е. целое положительное) число.

Вывести его последнюю цифру.

222_05

7. Дано трехзначное число.

Найти сумму его цифр.

222_06

8. Даны две обыкновенные дроби (введены пользователем).

Написать программу, которая делит первую дробь на вторую. Вывод должен быть следующим:

222_07

Вещественный тип

Число с плавающей запятой (или число с плавающей точкой) — форма представления вещественных чисел, в которой число хранится в форме мантиссы и показателя степени. 

Название "плавающая запятая" происходит от того, что запятая в позиционном представлении числа может быть помещена где угодно относительно цифр в строке. Представление числа в форме с плавающей запятой может рассматриваться как компьютерная реализация экспоненциальной записи чисел.

Основные типы вещественных чисел: double, long double и float. У типа double бóльшая точность (кол-во знаков после запятой). Для вещественного типа не предусмотрен unsigned.

Число с плавающей запятой состоит из:

  • Знака мантиссы (указывающего на отрицательность или положительность числа);
  • Мантиссы (выражающей значение числа без учёта порядка);
  • Знака порядка;
  • Порядка (выражающего степень основания числа, на которое умножается мантисса).

В вычислительных машинах показатель степени принято отделять от мантиссы буквой «E» (exponent). Например, число 1,528535047·10−25 в большинстве языков программирования высокого уровня записывается как 1.528535047E-25.

Десятичные числа могут не иметь дробной части, оставаясь при этом вещественными (например, действительное число 5.0).

Тип данных float

  • занимает в памяти 4 байта
  • имеет диапазон значений примерно от 3.4Е-38 до 3.4Е+38 

это (-2 147 483 648.0  / 2 147 483 647.0)

  • точность от 6 до 9 цифр

Пример:

223_01

Тип данных double

  • занимает в памяти 8 байт
  • имеет диапазон значений примерно от ±2.23Е-308 до 1.8Е+308

это (-9 223 372 036 854 775 808 .0   /   9 223 372 036 854 775 807.0)

  • точность от 15 до 18 цифр

Тип double обеспечивает по меньшей мере такую же точность, как float; представление значений типов определяется реализацией.

223_02

Пример:

  • 1 000 000 = 1.0 * 106 = 1.0E6
  • 0, 000 001 (одна миллионная) = 1.0. * 10-6 = 1.0E-6
  • 0.00345 = 345.0 * 10-5 = 34.5 * 10-4 = 3.45E-3

Ограничения, налагаемые на числа с плавающей точкой

  1. Вещественные числа не могут использоваться для перечисления. C++ требует использовать при перечислении только целые значения.
  2. Процессор компьютера выполняет операции с целыми числами гораздо быстрее, чем с действительными. Для сложения 1000 целых чисел процессору может потребоваться столько же времени, сколько для выполнения лишь 200 вычислений с плавающей точкой.
  3. Вещественные числа тоже страдают от ошибок округления. Если усреднить числа 1.0, 2.0, 2.0, то получится не математически точное 1,(6), а приблизительное значение 1.666667.

Переполнение вещественного типа осуществить невозможно:

223_03

Часто приходится задать определенное количество цифр в выводимом вещественном числе:

223_04

Выражения смешанного типа

C++ позволяет использовать в одном выражении переменные разных типов.

Пример:

Можно складывать целые и вещественные переменные:

  • int x = 5;
  • double y = x + 1.0;

Тип генерируемого в результате значения будет соответствовать более мощному типу операнда. В этом выражении перед выполнением операции сложения значение x преобразуется к типу double.

По тому же принципу выражение одного типа может быть присвоено переменной другого типа.

Пример:

  • double y = 1.9;
  • int x = y;

В этом выражении целая часть y сохраняется в x.

Если переменная в левой стороне равенства относится к типу менее мощному, чем переменная справа, то при таком присвоении можно потерять точность значений.

Преобразование типа большего размера в меньший называется понижающим приведением (demotion), а обратное преобразование – повышающим приведением (promotion).

Иногда действительно необходимо выполнить приведение типа, но в таком случае лучше использовать явное приведение, чтобы показать, что эта операция выполняется не ошибочно, а осознанно.

Пример:

явное повышающее приведение типа:

  • int x = 5;
  • double y = (double) x + 1.0;

явное понижающее приведение типа:

  • double y = 1.9;
  • int x = (int) y;

Оператор typedef

Язык С++ позволяет определять новые имена типов данных с помощью ключевого слова typedef. На самом деле здесь не создается новый тип данных, а определяется новое имя существующему типу. Он позволяет облегчить создание машинно-независимых программ. Единственное, что потребуется при переходе на другую платформу, - это изменить оператор typedef. Он также может помочь документировать код, позволяя назначать содержательные имена стандартным типам данных. Стандартный вид оператора typedef следующий:

typedef тип имя;

где тип — это любой существующий тип данных, а имя - это новое имя для данного типа. Новое имя определяется в дополнение к существующему имени типа, а не замещает его.

Пример:

223_05

Здесь sum – это другое имя для int в этой программе.

Написание программ с вещественными числами

Написать программы, которые решают следующие задачи:

1. У Кати 3,5 кг сахара. У Пети 4 кг сахара. У Марины 700 грамм сахара. А у Кирилла 1 кг 400 грамм сахара. Программа должна посчитать и вывести, во сколько раз у Кати больше сахара, чем у Марины, а также на сколько килограмм сахара больше у Пети, чем у Кирилла.

Пример вывода:

224_01

2. Написать программу, которая запрашивает у пользователя три вещественных числа и выводит их среднее арифметическое.

Пример вывода:

224_02

3. Создать программу для автоматизации процесса перевода старой русской меры веса в современную. Программа должна позволить пользователю ввести два числа (пуды и фунты) и сообщить, каково значение в килограммах (1 пуд = 40 фунтам = 16,38 кг).

Пример вывода:

224_03

Символьный тип

char – символьный тип. Значением переменной может быть символ алфавита, цифра, знак препинания или знак арифметической операции.

Пример:

char c = ‘a’;

Можно вывести символ по его номеру:

225_01

string – строка символов, составляющая предложение.

Пример:

string s = “this is a string”;

Для строк предусмотрены операции сравнения и конкатенации.

Конкатенация:

225_02

Сравнение:

225_03

Чтобы принять слово на русском языке и вывести его на русском:

225_04

Написание программ с использованием символов

1. Написать следующую программу, которая использует переменные типа string и типа char: сохранить в одной переменной name типа данных string свое полное имя, а в переменной gender значение f или m.

Вывести значения переменных.

Пример вывода:

226_01

2. Получить от пользователя символьные и строковые значения на русском языке, записать их в соответствующие переменные и вывести на экран.

Логический тип

Название типа bool происходит от имени Буля, автора символьной логики. Булева переменная может иметь только одно из двух значений – true или false.

227_01

Например, выражение “x == y” может иметь значение true или false.

Логические операции сравнения

ОператорЗначение
a == bРавенство; истинно, когда значение a совпадает со значением b
a != bНеравенство; противоположное равенству

a > b

 a < b

Больше, меньше; истинно, когда значение a больше (меньше) значения b

a >= b 

a <= b

Больше или равно, меньше или равно; истинно, если истиной является > или == (< или ==)

Операторы ==, !=, >, <, >=, <= являются операторами сравнения. Оператор равенства используется для проверки двух значений.

Например, следующее выражение истинно, если значением x является 5, и ложно во всех других случаях: x == 5;

Распространенная ошибка, которую компилятор не посчитает за ошибку и не укажет на нее: использование оператора присваивания вместо оператора равенства.

Составные логические операторы

ОператорЗначениеВозвращает true, если
a && bИаргументы и слева, и справа являются истиной (сокращенное вычисление)
a & bИаргументы и слева, и справа являются истиной
a || bИЛИили левый, или правый, или оба аргумента являются истиной  (сокращенное вычисление)
a | bИЛИили левый, или правый, или оба аргумента являются истиной
a ^ bЛИБОлибо a, либо b, но не обе одновременно равны true  (сокращенное вычисление невозможно)
!aНЕa принимает ложное значение

Сокращенные вычисления в C++

условие1 && условие2

Если условие1 ложно, то результат будет ложным независимо от истинности выражения условие2.

условие1 || условие2

Если условие1 истинно, то результат будет истинными независимо от истинности выражения условие2.

Для экономии времени C++ вычисляет первым условие1, и, в случае, если оно ложно (для оператора &&) или истинно (для оператора ||), выражение условие2 не вычисляется и не анализируется.

Операторы && (И) и || (ИЛИ) обычно сочетаются с другими логическими операторами.

Истинно, если y больше x и меньше z:

  • (x < y) && (y < z)

Истинно, если y больше x или меньше z:

  • (x < y) || (y < z)

Операторы сравнения достаточно взаимозаменяемы.

Например:

  • x <= y эквивалентно (x < y) || (x == y)
  • x == y эквивалентно !(x > y) && !(x < y)

Хранение логических значений

Результат логической операции может быть присвоен переменной типа bool:

  • int n1 = 1;
  • int n2 = 2;
  • bool b = (n1 == n2);

Сравни содержимое целочисленных переменных n1 и n2 и сохрани результат сравнения в логической переменной b”.

По правилу приоритетов операций выражение

b = (n1 == n2); эквивалентно выражению b = n1 == n2;

Для повышения удобочитаемости кода в подобных выражениях следует ставить скобки.

Вывод true и false вместо 0 и 1

Инструкция cout.setf(cout.boolalpha); обеспечивает вывод логического значения в виде строки true или false, а не в виде 1 или 0, как принято по умолчанию.

227_02

Чтобы вывод был иным, следует добавить строку:

227_03

Написание программ с логическими переменными

1. Написать программу с использованием переменных типа данных bool, которая решит следующую задачу.

228_01

У Олега 12 апельсинов, у Дениса 8 апельсинов, у Наташи 10 апельсинов, а у Юли 8 апельсинов. Сравнить, одинаковое ли количество апельсинов у Олега и Наташи, и записать результат в переменную compare1Так же сравнить количество апельсинов у Дениса и Юли и записать результат в переменную compare2. Вывести результат сравнения переменных compare1 и compare2.

2. Написать программу, которая выводит на экран таблицу истинности логических операций. Использовать только две переменные.

Пример вывода:

228_02

Тренажёр