Определение в программе переменных и именованных констант. Инициализация переменных копированием и списком.
Данные, значения которых во время выполнения программы можно изменять, называются переменными, неизменяемые данные называются константами. В программе все данные перед их использованием должны быть объявлены или определены. В операторах определения данных указывается тип данных и перечисляется через запятую имена переменных, имеющих данный тип. Отличие объявления от определения заключается в том, что при объявлении переменной ей место в памяти соответствующей функции не выделяется, объявление лишь сообщает компилятору тип переменной. Место же для значения переменной запрашивается в другой функции. К объявлениям относятся, например, перечисление имен переменных в списке параметров функции.
Определение переменных имеет следующий формат:
[спецификатор класса памяти] спецификатор типа идентификатор [=начальное значение];
Идентификатор может быть записан с квадратными скобками, круглыми скобками или перед ним может быть один или несколько знаков *.
Спецификатор типа – это одно или несколько ключевых слов, определяющих тип переменной. Язык Си определяет стандартный набор основных типов данных (int, char, double). При определении переменных им можно присвоить начальное значение.
Четыре ключевых слова: auto, extern, register, static определяют класс памяти. Если ключевое слово, определяющее класс памяти, опущено, то класс памяти определяется по контексту.
Определение и объявление переменных рекомендуется размещать в начале программного модуля.
Именованная константа – это имя, которому присваивается постоянное значение. Такая константа в отличие от значения переменной не может изменяться по мере выполнения программы. Именованная константа создается с использованием директивы препроцессора #define. Например, следующий оператор определяет именованную константу z как значение 50. #define z = 50. После того, как константа определена, можно использовать ее значение на протяжении всей программы, просто обращаясь к имени значения константы.
Спецификация типа – имя типа, присваиваемого объекту. В некоторых случаях спецификация типа может быть опущена. В языке С++ определен набор базовых типов данных.
Базовые типы: целые: спецификация типов:
signed char – знаковый символьный;
signed int – знаковый целый;
signed short int – знаковый короткий целый;
signed long int – знаковый длинный целый;
unsigned char- беззнаковый символьный;
unsigned int- беззнаковый целый;
unsigned short int – беззнаковый короткий целый;
unsigned long int – беззнаковый длинный целый.
Базовые типы: плавающие: спецификация типов:
float – плавающий одинарной точности;
double – плавающий двойной точности;
long float – длинный плавающий одинарной точности;
long double – длинный плавающий двойной точности.
Базовые типы: прочие: спецификация типов:
void– пустой;
enum– перечислимый.
Типы char, int, short, long имеют две формы – знаковую (signed) и беззнаковую (unsigned). В совокупности они образуют целый тип. Перечислимый тип также служит для представления целых значений, однако переменная перечислимого типа может принимать значения только из набора, заданного в ее объявлении. Спецификации типов float и double относятся к плавающему типу.
Тип void (пустой) имеет специальное назначение. Указание спецификации типа void в объявлении функции означает, что функция не возвращает значений. Указание типа void в списке объявлений аргументов в объявлении функции означает, что функция не принимает аргументов. Тип void может быть указан в операции приведения типа. Приведение значения выражения к типу void явно указывает на то, что это значение не используется. Нельзя объявить переменную типа void.
При записи спецификаций целого и плавающего типов допустимы сокращения. Например, в целых типах ключевое слово signed может быть опущено. Если ключевое слово unsigned отсутствует в записи спецификации типа short, int, long, то тип целого будет знаковым, даже если опущено ключевое слово signed.
Инициализация копированием — это инициализация одного объекта с использованием другого объекта. Она выполняется в следующих случаях:
-Переменная инициализируется с помощью знака равенства.
-Аргумент передается в функцию.
-Объект возвращается функцией.
-Возникает или перехватывается исключение.
-Нестатический элемент данных инициализируется с помощью знака равенства.
Инициализация списком выполняется, когда переменная инициализируется с помощью списка инициализации в фигурных скобках. Списки инициализации в фигурных скобках можно использовать в следующих случаях:
-Инициализируется переменная.
-Класс инициализируется с помощью ключевого new слова
-Объект возвращается функцией.
-Аргумент передается функции.
-Один из аргументов при прямой инициализации.
-В инициализаторе нестатических элементов данных.
-В списке инициализации конструктора.
Выражения. Арифметические выражения. Логические выражения. Выражения с символами и строками. Выражения и преобразования типов.
Арифметические операции:
Логические операции:
Операции сравнения и логические операции в результате дают значение типа bool, то есть true или false. Если же такое выражение встречается в контексте, требующем целого значения, true преобразуется в 1, а false – в 0.
Представим себе следующий оператор присваивания:
int ival = 0;
// обычно компилируется с предупреждением
ival = 3.541 + 3;
В результате ival получит значение 6. Вот что происходит: мы складываем литералы разных типов – 3.541 типа double и 3 типа int. C++ не может непосредственно сложить подобные операнды, сначала ему нужно привести их к одному типу. Для этого существуют правила преобразования арифметических типов. Общий принцип таков: перейти от операнда меньшего типа к большему, чтобы не потерять точность вычислений.
В нашем случае целое значение 3 трансформируется в тип double, и только после этого производится сложение. Такое преобразование выполняется независимо от желания программиста, поэтому оно получило название неявного преобразования типов.
Результат сложения двух чисел типа double тоже имеет тип double. Значение равно 6.541. Теперь его нужно присвоить переменной ival. Типы переменной и результата 6.541 не совпадают, следовательно, тип этого значения приводится к типу переменной слева от знака равенства. В нашем случае это int. Преобразование double в int производится автоматически, отбрасыванием дробной части (а не округлением). Таким образом, 6.541 превращается в 6, и этот результат присваивается переменной ival. Поскольку при таком преобразовании может быть потеряна точность, большинство компиляторов выдают предупреждение.
Так как компилятор не округляет числа при преобразовании double в int, при необходимости мы должны позаботиться об этом сами. Например:
double dva1 = 8.6;
int iva1 = 5;
ival += dva1 + 0.5; // преобразование с округлением
При желании мы можем произвести явное преобразование типов:
// инструкция компилятору привести double к int
ival = static_cast< int >( 3.541 ) + 3;
В этом примере мы явно даем указание компилятору привести величину 3.541 к типу int, а не следовать правилам по умолчанию.
В этом разделе мы детально обсудим вопросы и неявного (как в первом примере), и явного преобразования типов (как во втором).
Операторы языка. Операторы преобразования данных.
Категории операторов:
-Операторы выражений. Эти операторы вычисляют выражение для определения побочных эффектов и возвращаемого значения.
-Операторы NULL. Эти операторы могут указываться в тех случаях, когда синтаксис C++ требует использования оператора, однако никакие действия не требуются.
-Составные операторы. Эти операторы представляют собой группы операторов, окруженные фигурными скобками ({ }). Их можно во всех случаях, где может использоваться отдельный оператор.
-Операторы выбора. Эти операторы выполняют проверку, а затем, если проверка дает результат true (ненулевое значение), выполняют один из участков кода. Если проверка даст результат false, может выполняться другой участок кода.
-Операторы итерации. Эти операторы вызывают повторное выполнение блока кода до тех пор, пока не будет выполнен заданный критерий завершения.
-Операторы перехода. Эти операторы либо передают управление непосредственно в другое место функции, либо возвращают управление из функции.
-Операторы объявления. Объявления вводят имя в программу.
Операторы преобразования (conversion operator) определяют преобразование объекта одного типа в другой. Они имеют следующий общий синтаксис:
operator тип() const;
В данном случае тип - это тот тип, в который надо преобразовать. В качестве типа нельзя использовать массив или функцию, хотя указатель на функцию вполне можно использовать.
Операции преобразования не должны изменять преобразуемый объект, поэтому функции операторов определяются с ключевым словом const.
Операции преобразования также могут быть явными. В этом случае операторы определяются с ключевым словом explicit. Здесь в классе Counter определен оператор преобразования объекта из типа Counter в тип Clock, то есть по сути из секунд необходимо получить часы, минуты и секунды. Этот оператор определен как явная операция преобразования:
explicit operator Clock() const
{
int h = seconds / 3600;
int m = (seconds - h * 3600) / 60;
int s = seconds - h*3600 - m*60;
return Clock(h, m, s);
}
Алгоритмическая схема «развилка». Условные операторы. Неполная форма. Вложенные условные операторы.
Условный оператор относится к операторам управления работой программы и реализует алгоритмическую схему развилка и соответственно имеет две формы.
Полная форма: if (условное выражение) оператор 1; else оператор 2;
Неполная форма: if (условное выражение) оператор;
Вложенные условные операторы:
Если оператор 1 или оператор 2 в полной форме или оператор в сокращенной форме являются также условными операторами, то эти операторы называются вложенными условными операторами, которые также имеют прямую и альтернативную ветвь.
При определении, к какому условному оператору какая относится альтернативная ветвь, существует правило: рассматриваются слева направо каждый else. Очередная альтернативная ветвь else принадлежит к ближайшему к ней, свободному (не связанному с другим else) оператору if.
Рассмотрим пример:
if (x = =1) if (у = =1) cout << ''x =1 и y =1''; else cout<< ''x! = 1'';
Условный оператор составлен неправильно!
Действительно, при значениях x=1 и y! =1, будет выведена не правильная фраза ''x! =1''
Ниже представлены два варианта правильно составленных операторов:
if (x = = 1) {if (у = = 1) cout<< ''x =1 и y =1'';} else cout<<''x!= 1'';
или
if (x= =1) if (y= =1) cout<<'' x =1 и y =1 ''; else; else cout<<''x! = 1'';
Операторы выбора. Две формы алгоритма (переключатель, выбор варианта)
Switch Позволяет выбирать между несколькими разделами кода в зависимости от значения целочисленного выражения.
Форма переключателя:
switch (переключающее выражение)
{ case константное варажение1: операторы1;
…
case константное выражение N: операторы N;
default: операторы;
};
Здесь:
- переключающее выражение может быть любого перечисляемого типа: целочисленного или символьного;
- константные выражения должны быть того же типа (или приводящимися к нему), что и переключающее выражение и различны по значению;
- для каждой ветви алгоритма возможно использовать несколько константных выражений, например,
сase1 :case 5: операторы;
Сначала вычисляется переключающее выражение. Полученное значение сравнивается со значениями константных выражений.
Если совпадает значение, то выполняются операторы данного варианта и операторы всех последующих вариантов, включая и вариант с меткой default.
Если значение не совпало ни с одним значением константных выражений, выполняется вариант с меткой default.
Вариант default может располагаться в любой части внутри фигурных скобок, а может просто отсутствовать и тогда при отсутствии совпадения не выполняется ничего.
Операторы циклов.
Циклы реализуют алгоритмическую схему повторения обработки данных.
В С++ определены три разных цикла:
цикл с предусловием:
while (выражение-условие)
тело_цикла;
цикл с постусловием:
do тело_цикла
while (выражение-условие);
цикл с параметром:
for (инициализация_цикла; выражение-условие; выражения коррекции)
тело_ цикла
Тело_цикла - это отдельный оператор, который всегда завершается точкой с запятой, либо составной оператор, либо блок.
Только описание или определение не может быть телом цикла. Операторы цикла задают многократное выполнение операторов тела цикла.
Выражение-условие – во всех операторах скалярное (чаще всего логическое или арифметическое) определяет условие продолжение повторения обработки, если оно истинно (отлично от нуля).
Прекращение выполнения цикла происходит в случаях:
ложное (нулевое) значение выражения-условия;
выполнение в теле цикла оператора передачи управления за пределы тела цикла.
Оператор while- оператор цикла с предусловием.
При входе в цикл вычисляется условие, если оно отлично от нуля, выполняется тело_цикла.
Затем вычисление выражения-условия и выполнение тела_цикла повторяются, пока условие не станет ложным.
Следующая функция подсчитывает длины строки, заданной с помощью адресующего ее указателя – параметра функции:
int lt (char*stroka)
{int ln = 0;
while (*stroka++) ln++;
return ln;}
Ниже приведены некоторые выражения условия:
while (a<b), while (point! = nullptr ) // (point-указатель),
while(point), while (point! = 0).
Если в теле цикла не изменяется выражение-условие, могут возникнуть бесконечные циклы или ''зацикливание''.
Пример бесконечного цикла, с пустым оператором в теле:
while (1);
Такой цикл может быть закончен за счет событий, явно непредусмотренных в программе. Например, событие – указание операционной системе ''снять задачу''.
Оператор do while является оператором цикла с постусловием.
При входе в цикл выполняется тело_цикла.
Затем проверяется выражение-условие и, если его значение истинно, вновь выполняется тело цикла и так далее.
К выражению-условию требования те же: оно должно изменяться при итерациях за счет операторов тела циклов.
do ; while (1); //бесконечный цикл
Цикл for– цикл с параметром.
Заголовок цикла после зарезервированного слова for в круглых скобках включает три части: инициализация_цикла, выражение-условие и список выражений для коррекции, которые разделяются двумя знаками ';'.
Каждая из этих частей может отсутствовать, но даже если все они отсутствуют, два разделителя - ';' должны присутствовать в заголовке.
Инициализация_цикла – это выражение, или определения объектов одного типа.
Вычисляется один раз при входе в цикл.
Заканчивается точкой с запятой.
Как правило, определяются и инициализируются параметры цикла.
Выражение-условие - логическое выражение, проверяется на каждой итерации цикла.
Если его нет, полагают, что оно истинно.
В этом случае сохраняется следующая за условием точка с запятой.
Выражения коррекции – список выражений, разделенных запятыми, которые вычисляются на каждой итерации после выполнения тела_цикла до следующей проверки условия.
Тело_цикла – может быть отдельным простым оператором, составным оператором или блоком.
При входе в цикл один раз вычисляются выражения из секции инициализация_цикла.
Вычисляется значение выражения-условия, если оно истинно, выполняются операторы тела_цикла и вычисляются выражения коррекции.
Далее цепочка повторяется, пока выражение-условие не станет ложным.
for – цикл с заданным числом повторений, для контроля числа итераций используется управляющая переменная – параметр цикла.
Вложенные циклы.
Разрешено вложение любых циклов в любые циклы.
Действует следующее правило: для каждой итерации внешнего цикла выполняются все итерации внутреннего цикла.
… void main()
{ for (int i =0 ; i < 3 ; i ++ ) // внешний цикл
{ cout <<’\n’<< i ; // переменная i действует до конца блока
// функции main
for ( int i = 6 ; i>3 ; i-- ) cout << i ; //переопределение
// другой переменной с тем же именем до конца блока
// внешнего цикла
cout << i ;
}
} 0 6 5 4 3
1 6 5 4 3
2 6 5 4 3
Операторы передачи управления.
К операторам передачи управления относятся:
- оператор безусловного перехода goto,
- оператор возврата из функции return,
- оператор выхода из цикла или переключателя break,
- оператор перехода к следующей итерации цикла continue.
goto A; //- ошибка
float x = 1.2;
goto A; //- допустимо
{int n=2;
x*=n;}
A: cout <<x;
Форма оператора безусловного перехода:
goto идентификатор метки;
Передача управления разрешена на любой оператор, помеченный меткой.
Имя метки действует и уникально в теле функции, где расположен оператор.
Существует запрет: нельзя передавать управление через определение, содержащее инициализацию объекта, но можно обходить вложенные блоки, содержащие определение с инициализацией.
При использовании оператора goto рекомендуется:
не входить внутрь блока извне;
не входить внутрь условного оператора;
не входить извне внутрь переключателя;
не передавать управление внутрь цикла;
Есть случаи, когда использование оператора goto обеспечивает наиболее простое решение:
выход из нескольких вложенных циклов или переключателей;
к одному участку программы перейти из разных мест функции;
Оператор возврата из функции имеет вид:
return выражение; или return;
Возвращает в точку вызова функции значение выражения, которое, если присутствует, может быть только скалярным.
Если выражение в операторе return отсутствует, то возвращаемое функцией значение имеет тип void.
