Последовательно выполняемые операторы
Каждый оператор языка Си++ заканчивается и идентифицируется разделителем «точка с запятой». Любое выражение, после которого поставлен символ «точка с запятой», воспринимается компилятором как отдельный оператор.
До сих пор все программы, приведённые в примерах, являлись набором последовательно выполняющихся операторов, в том числе и вызовы функций. Действительно, операторы выполнялись последовательно друг за другом так, как они были записаны в тексте программы.
Специальным случаем оператора служит пустой оператор. Он, как и разделитель, представляется символом «точкай с запятой», перед которым нет никакого выражения или не завершённого разделителем оператора. Пустой оператор не выполняет никаких действий. Он используется там, где синтаксис языка требует присутствие оператора, а по смыслу программирования никакие действия не должны выполняться.
Перед каждым оператором может быть помещена метка, отделяемая от оператора двоеточием. Область действия метки - тело функции. В качестве имени метки используется произвольно выбранный программистом уникальный идентификатор:
D1: x= x*sin(x);; //D1 – метка. Выражение x= x*sin(x); - оператор.
D2: ; // D2 – метка. Символ «точка с запятой» - пустой оператор.
Составным оператором является набор операторов, заключённых в фигурные скобки. Если среди операторов, находящихся в фигурных скобках, имеются определения переменных, то составной оператор превращается в блок, где локализованы все определенные в нём объекты. Синтаксически и блок, и составной оператор являются отдельными операторами. Однако ни блок, ни составной оператор не должны заканчиваться точкой с запятой. Для них ограничителем служит закрывающая фигурная скобка. Внутри блока (и составного оператора) любой оператор должен оканчиваться точкой с запятой.
{ int f; char st = ‘0’; а = (int)st; } // блок (присутствует определение )
{sin(2*x); x= x-4;} // составной оператор
Так как и блок, и составной оператор пользуются правами операторов, то разрешено их вложение, причем на глубину вложения синтаксис не накладывает ограничения.
Операторы выбора
К операторам выбора относят: условный оператор (if … else) и переключатель (switch). Каждый из них служит для разветвления пути выполнения программы.
Синтаксис условного оператора:
if( выражение) оператор_1
else {оператор_2}
Выражение должно быть скалярным и может иметь арифметический тип или тип указателя. Если оно не равно нулю (или не есть пустой указатель), то условие считается истинным и выполняется оператор_1. В противном случае, выполняется оператор_2. Оператор_1 и оператор_2 могут быть представлены оператором, составным оператором или блоком. На рис. 4.1 изображено общепринятое обозначение условного оператора на блок-схеме.
Рис. 4.1. Обозначение условного оператора на блок схеме
Допустима сокращённая форма условного оператора, в которой отсутствует else и оператор_2. В этом случае при ложности (равенстве нулю) проверяемого условия никакие действия не выполняются и управление передаётся оператору, сразу следующему за оператором условия. Блок-схема условного оператора, в котором ртсутствует else будет выглядеть так, как показано на рис. 4.2.
Рис. 4.2. Обозначение условного оператора на блок-схеме
В свою очередь, операторы_1 и оператор_2 могут быть условными, что позволяет организовать цепочку проверок условий любой глубины вложенности. В этих цепочках каждый из условных операторов может быть, как полным условным, так и иметь сокращённую форму записи.
При этом могут возникать ошибки неоднозначного сопоставления if и else. Синтаксис языка предполагает, что при вложенных условных операторах каждое else соответствует ближайшему к нему предшествующему if. Приведем два примера:
Int x = 1, y =2;
//пример 1
if(x==1) // 1
if(y==1) cout<<” х равно 1 и y равно 1”; // 2
else cout<<” x не равно 1”; // 3
//пример 2
if(x==1){ // 4
if(y==1) cout<<” х равно 1 и y равно 1”; // 5
}
else cout<<” x не равно 1”; // 6
В первом примере else относится к if , записанному во второй строке. Во втором примере else относится к if , записанному в четвёртой строке. С точки зрения логики программы второй пример правилен, а первый нет, так как при x, равном единице, в первом примере может быть напечатана строка “x не равно 1”. Хотя с точки зрения компилятора (синтаксиса языка) все строки в обеих примерах записаны верно. Таким образом, с помощью фигурных скобок была ограничена область действия внутреннего условного оператора. Блок-схемы примеров приведены ниже на рис. 4.3.
Рис. 4.3. Блок-схема первого примера
Рис. 4.4 Блок-схема второго примера
Переключатель switch является наиболее удобным средством для организации мультиветвления. Синтаксис переключателя таков:
switch ( переключающее_выражение){
case константное_выражение_1: оператор_1;
case константное_выражение_2: оператор_2;
…
case константное_выражение_N: оператор_N;
default: операторы;
}
где оператор_1 … оператор_N – одиночный, составной или блочный оператор. Управляющая конструкция switch передаёт управление к тому из помеченных с помощью case операторов, для которого значение константного выражения совпадает со значением переключающего выражения. Переключающее выражение должно быть целочисленным или его значение приводится к целому. Значение константных выражений, помещённых за служебным словом case, приводится к типу переключающего выражения. В одном переключателе все константные выражения должны иметь различные значения, но быть одного типа. Любой из операторов, помещенный в фигурные скобки, после конструкции switch( ) может быть помечен одной или несколькими метками вида
case константное_выражение:
Если значение переключающего выражения не совпадает ни с одним из константных выражений, то выполняется переход к оператору, отмеченному меткой default:. В каждом переключателе должно быть не больше одной метки default, однако эта метка может и отсутствовать. В случае отсутствия метки default при несовпадении переключающего выражения ни с одним из константных выражений, помещаемых вслед за case, в переключателе не выполняется ни один из операторов.
Сами по себе метки case константное_выражение: и default: не изменяют последовательности выполнения операторов. Если не предусмотрены переходы или выходы из переключателя с помощью break, goto, return, то в нём последовательно выполняются все операторы, начиная с той метки, на которую передано управление. Пример программы с переключателем:
//Программа 4.1
#include "stdafx.h"
#include <iostream> //1
void main(){ //2
int ic; //3
std::cout<<"\n Input any decimal digit: "; //4
std::cin >> ic; //5
switch(ic%2){ //6
case 0: std::cout<< "\n Input an even number"; break;//7
case 1: std::cout<< "\n Input an odd number"; break;//8
default: std::cout<< "\n it is not known ic = "<<ic; //9
} //10
getchar();
} //11
Программа выводит на экран строку о том, чётное или нечётное число введено с клавиатуры. Забегая вперёд, скажем, что с помощью оператора break передаётся управление на оператор, сразу следующий за телом переключателя switch, т.е. на строку 11.
Операторы цикла
Операторы цикла задают многократное исполнение операторов тела цикла. Определены три разных оператора цикла:
цикл с предусловием и его блок-схема:
while(выражение_ условие) {тело цикла;}
Рис. 4.5. Блок-схема цикла с предусловием
Цикл с постусловием и его блок-схема:
do{
тело цикла;
}
while (выражение_ условие);
Рис. 4.6. Блок-схема цикла с постусловием
Итерационный цикл и его блок-схема:
for(инициализация_цикла; выражение_условия; список выражений)
{
тело цикла;
}
Рис. 4.7. Блок-схема итерационного цикла
Тело цикла - это либо отдельный (в том числе пустой) оператор, который всегда завершается точкой с запятой, либо составной оператор, либо блок. Выражение условия – это скалярное или логическое выражение, определяющее условие продолжения итераций. Если значение выражения условия равно нулю, то итерации (многократное выполнения одних и тех же операторов, в данном случае выполнение операторов тела цикла) прекращаются, если не равно нулю - итерации продолжаются.
Прекращение выполнения цикла возможно в следующих случаях:
нулевое значение проверяемого выражения;
выполнение в теле цикла оператора передачи управления (break; goto; return) за пределы цикла.
Последнюю из указанных возможностей проиллюстрируем позже, рассматривая особенности операторов передачи управления.
Оператор while называется оператором цикла с предусловием. При входе в цикл вычисляется выражение_условие. Если его значение отлично от нуля, то выполняется тело цикла. Затем снова проверяется выражение-условие и если его значение снова отлично от нуля, то опять выполняется тело цикла и т.д. до тех пор, пока значение выражения_условия не станет равным нулю. Если значение выражения_условия при проверке оказалось равным нулю, то управление передаётся на оператор, стоящий сразу за телом цикла. Приведём примеры программ с циклом предусловия:
//Программа 4.2
#include "stdafx.h"
#include <iostream>
//Подсчёт количества символов в строке
void main( ){
std::cout<<"Input string = ";
char buf[100]; //buf[i] i = от 0 до N-1
std::cin>>buf;
long len =0;
while (buf[len]) {len++;} /*Тело цикла – один оператор (len++) */
std::cout<<"\n The number of symbol are = "<<len;
getchar();
}
Как известно, строка в Си++ заканчивается нулевым символом. Поэтому, перебрав посимвольно всю строку и найдя нулевой символ, можно подсчитать количество символов в строке, что и делается с помощью цикла в примере.
Часто в качестве выражения условия в цикле может вступать логическое выражение. Например, следующая последовательность операторов вычисляет сумму квадратов первых N натуральных чисел (членов натурального ряда):
int i =0;
long s = 0;
long N = 6;
while(i < N) s+=++i*i;// Тело цикла - один оператор s+=++i*i;
cout<<s;
Цикл завершится тогда, когда логическое выражение i < N станет ложным.
Может ли цикл выполнятся бесконечно? Да, может. Во всяком случае до тех пор, пока программист искусственно с помощью горячих клавиш (Ctrl+Break) или выключения питания компьютера не прервёт его выполнение. Самым простым примером бесконечного цикла может служить такая запись:
while(1) ; // Бесконечный цикл с пустым оператором в качестве тела.
Поэтому значение выражения_условия не должно быть константой и должно меняться во время выполнения итераций.
Оператор
do тело цикла while (выражение _условие);
называется оператором цикла с постусловием. При входе в цикл с постусловием выполняется тело цикла. Затем вычисляется выражение_условие и если его значение не равно нулю, то вновь выполняется тело цикла. Если выражение_условие равно нулю, то управление передаётся следующему оператору за циклом в тексте программы. Таким образом, тело цикла с постусловием в любом случае выполняется хотя бы один раз.
Бесконечный цикл можно записать так:
do ; while(1);
Поэтому к выражению условия требования те же, что и для цикла while c предусловием – оно должно изменяться при итерациях либо за счёт операторов тела цикла, либо при вычислениях.
Оператор итерационного цикла for имеет формат:
for( инициализация_цикла; выражение_условие; список_выражений)
{тело_цикла;}
где тело_цикла может быть блоком, отдельным оператором, составным оператором или пустым оператором; инициализация_цикла – последовательность определений (описаний) и выражений, разделяемых запятыми (чаще всего здесь устанавливаются начальные значения счётчиков и параметров цикла); выражение_условие – такое же, как и в циклах while и do: если оно равно нулю, то выполнение цикла прекращается; список_выражений – список выражений, записанных через запятую и выполняемых на каждой итерации.
Цикл for работает следующим образом: при входе в цикл происходит инициализация_цикла и проверка значения выражения_условия. Если оно истинно (не равно 0), выполняется тело_цикла, если нет - управление передаётся оператору, стоящему сразу за телом цикла в программе. После выполнения тела цикла выполняется список_выражений, далее опять проверяется выражение_условие и по его значению определяется, делать новую итерацию или нет.
Цикл for можно записать, опустив и/или инициализацию_цикла, выражение_условие, список_выражений, в виде:
for( ; ;); // бесконечный цикл с пустым оператором в качестве тела.
for( ;1;); // бесконечный цикл с пустым оператором в качестве тела.
В этом случае точки с запятой должны оставаться. Значение выражения_условия считается равным единице.
Приведём примеры использования цикла for для решения задачи суммирования квадратов первых N =5 членов натурального ряда:
for( int i =1, s = 0; i <= N; i++) s=s+ i*i;
for ( int i = 0, s = 0; i <=N ; s +=++i*i);
for ( int i = 0, s = 0; i <=N ;) s +=++i*i;
for ( int i = 0, s = 0; i <=N ; ) {int j; j = ++ i; s +=j*j;}
В проекте языка Си++ нет специальных соглашений относительно области действия имён, определенных в инициализирующей части оператора цикла. В конкретных реализациях компилятора принято, что область действия таких имён – от места размещения цикла for до конца блока, в котором этот цикл используется.
Разрешено и широко используется вложение любых циклов в любые циклы. Например, вывод на экран элементов квадратной матрицы может быть реализован с помощью вложенных циклов:
//Программа 4.3
#include "stdafx.h"
#include <iostream> //1
void main (){ //2
int A[3][3]; //3
for(int i = 0; i < 3; i++){/*4 Начало тела первого цикла*/
std::cout<<"\n"; //5
for(int k = 0; k < 3; k++) //6
std::cout<<"\t"<<(A[i][k]=i+k);/*7 Тело вложенного цикла */
} //8 Конец тела первого цикла
getchar();
} //9
В инициализации циклов определены переменные i и k. Область существования переменной i с 4 по 9 строку программы. Область существования переменной k – с 6 по 8 строку программы.
Дата добавления: 2020-12-11; просмотров: 432;