Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


For (выражение1; выражение2; выражениеЗ) оператор



где выражение1 задает начальное значение переменной, управляющей циклом, выражение2 является условием продолжения цикла, а выражениеЗ изменяет управляющую переменную. В большинстве случаев структуру for можно представить эквивалентной ей структурой while следующим образом:

Выражение1;

while(Выражение2) {

оператор

Выражение3;

}

Иногда выражение1 и выражение3 представляются как списки выражений, разделенных запятой. В данном случае запятая используется как опе­рация запятая или операция последования, гарантирующая, что список вы­ражений будет вычисляться слева направо. Операция последования имеет самый низкий приоритет среди всех операций C++. Значение и тип списка выражений, разделенных запятыми, равны значению и типу самого правого выражения в списке. Операция последования наиболее часто используется в структуре for. Ее основное назначение — помочь программисту использо­вать несколько выражений задания начальных значений и (или) несколько выражений приращения переменных. Например, в одной структуре for может быть несколько управляющих переменных, которым надо задавать начальное значение и которые надо изменять.

Следует помещать в разделы задания начальных значений и изменения переменных струк­туры for только выражения, относящиеся к управляющей переменной. Манипуляции с другими переменными должны размещаться или до цикла (если они выполняются только один раз подобно операторам задания начальных значений), или внутри тела цикла (если они должны выполняться в каждом цикле, как, например, операторы инкремента или декремента).

Выражения в структуре for являются необязательными. Если выраже-ние2 отсутствует, C++ предполагает, что условие продолжения цикла всегда истинно и таким образом создается бесконечно повторяющийся цикл. Иногда может отсутствовать выражение1 если начальное значение управляющей переменной задано где-то в другом месте программы. Может отсутствовать и выражение3, если приращение переменной осуществляется операторами в теле структуры for или если приращение не требуется. Выражение для при­ращения переменной в структуре for действует так же, как автономный опе­ратор в конце тела for. Следовательно, все выражения

counter = counter + 1

counter += 1

++counter

counter++

эквивалентны в той части структуры for, которая определяет приращение. Многие программисты предпочитают форму counter++, поскольку прираще­ние срабатывает после выполнения тела цикла. Поэтому постфиксная форма представляется более естественной. Поскольку изменяемая переменная здесь не входит в какое-то выражение, обе формы инкремента равноправны. В структуре for должны применяться точки с запятой.

«Приращение» структуры for может быть отрицательным (в этом случае в действительности происходит не приращение, а уменьшение переменной, управляющей циклом).

Если условие продолжения цикла с самого начала не удовлетворяется, то операторы тела структуры for не выполняются и управление передается оператору, следующему за for.

Управляющая переменная иногда печатается или используется в вычис­лениях в теле структуры for, но обычно это делается без изменений ее ве­личины. Чаще управляющая переменная используется только для контроля числа повторений и никогда не упоминается в теле структуры.

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

Оператор цикла do/while

Структура повторения do/while похожа на структуру while. В структуре while условие продолжения циклов проверяется в начале цикла, до того, как выполняется тело цикла. В структуре do/while проверка условия про­должения циклов производится после того, как тело цикла выполнено, сле­довательно, тело цикла будет выполнено по крайней мере один раз. Когда do/while завершается, выполнение программы продолжается с оператора, сле­дующего за предложением while. Отметим, что в структуре do/while нет не­обходимости использовать фигурные скобки, если тело состоит только из одного оператора. Но фигурные скобки обычно все же ставят, чтобы избежать путаницы между структурами while и do/while. Например,

while (условие)

обычно рассматривается как заголовок структуры while. Структура do/while без фигурных скобок и с единственным оператором в теле имеет вид

do

оператор while(условие);

что может привести к путанице. Последняя строка — while (условие); может ошибочно интерпретироваться как заголовок структуры while, содержащий пустой оператор. Таким образом, чтобы избежать путаницы, структура do/while даже с одним оператором часто записывается в виде

do {

оператор } while (условие);

Некоторые программисты всегда включают фигурные скобки в структуру do/while, даже если в них нет необходимости. Это помогает устранить двусмысленность, про­истекающую из совпадения предложений структуры while и структуры do/while, содержащей один оператор.

Следующая программа использует структуру do/while, чтобы напечатать числа от 1 до 10. Обратите внимание, что к управляющей переменной counter в проверке окончания цикла применяется инкремент в префиксной форме. Отметьте также использование фигурных скобок, заключающих единствен­ный оператор в теле do/while.

// Применение структуры повторения do/while

#include < iostream.h>

main() {

int counter = 1;

do {

cout < < counter < < " ";

} while(++counter < = 10);

return 0;

}

Операторы break и continue

Операторы break и continue изменяют поток управления. Когда оператор break выполняется в структурах while, for, do/while или switch, происходит немедленный выход из структуры. Программа продолжает выполнение с пер­вого оператора после структуры. Обычное назначение оператора break — досрочно прерывать цикл или пропустить оставшуюся часть структуры switch.

Оператор continue в структурах while, for или do/while вызывает про­пуск оставшейся части тела структуры и начинается выполнение следующей итерации цикла. В структурах while и do/while немедленно после выпол­нения оператора continue производится проверка условия продолжения цикла. В структуре for выполняется выражение приращения, а затем осу­ществляется проверка условия продолжения. Ранее мы установили, что в большинстве случаев структура while может использоваться вместо for. Единственным исключением является случай, когда выражение приращения в структуре while следует за оператором continue. В этом случае приращение не выполняется до проверки условия продолжения цикла и структура while работает не так, как for.

Оператор выбора if – else

Оператор выбора имеет следующий синтаксис

If (условие) оператор1; else оператор2

Выполняется оператор следующим образом.

Вычисляется выражение, записанное как условие.

Если значение условия - истина, то выполняется оператор1.

Если значение условия - ложь, то выполняется оператор2.

Пример 1.

x=0.2;

If(x< 2) y=3; else y=5;

Результат.

y=3.

Пример 2.

x=0.2;

If(x< 2){ x++; y=3; }else y=5;

Результат.

y=3, x=1.2.

Пример 3.

x=0.2;

If(x> 2){ x++; y=3; }else y=5;

Результат.

y=5, x=0.2.

Пример 4.

x=0.2;

If(x> 2){ x++; y=3; } y=5;

Результат.

y=5, x=0.2.

Оператор переключатель switch

Оператор выбора имеет следующий синтаксис

switch выражение_целого_типа

{

case значение_1: оператор1; break;

...
case значение_n: оператор_n; break;

default: оператор_d;

}

Выполняется оператор следующим образом.

Вычисляется выражение, записанное как условие.

Если значение условия равно значение_i, то выполняется оператор_i и далее - выход из оператора switch.

Если значение условия не равно ни одному значение_i, то выполняется оператор_d.

Пример 1.

int x=2;

Switch x

{

case 1: cout< < 1< < endl; break;

case 2: cout< < 2< < endl; break;

default: cout< < ”x not equal 1 or 2”< < endl;

}

Результат. 2

Пример 2.

int x;

char c;

for(x=0; x< 5; x++)

switch (x%2)

{

case 0: cout< < x< < " - x even" < < endl; break;

case 1: cout< < x< < " - x not even" < < endl; break;

default: cout< < " not work in this program" < < endl;

}

for(c='a'; c< ='z'; c++)

switch (c)

{

case 'a': case 'o': cout< < c< < " - vowel" < < endl; break;

case 'b': case 'c': cout< < c< < " - not vowel" < < endl; break;

default: cout< < c< < " some letter" < < endl;

}

Порядок выполнения работы

1. Ознакомиться с теоретическими сведениями.

2. Получить вариант задания у преподавателя.

3. Выполнить задание.

4. Продемонстрировать выполнение работы преподавателю.

5. Оформить отчет.

6. Защитить лабораторную работу.

Задание на работу

1. Написать программу, выводящую на экран таблицу умножения, используя цикл for.

2. Написать программу вывода на экран элементов ряда Фибоначчи S[i] = S[i – 1] + S[i – 2]; i = [1…n]; S[1] = 1, S[2] = 1.

3. Написать программу, выводящую на экран таблицу умножения, используя цикл while.

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

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

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

6. Контрольные вопросы

1. Какой синтаксис имеет цикл while?.

2. Какой синтаксис имеет цикл do-while?.

3. Какой синтаксис имеет цикл for?

4. Для чего используется оператор break?

5. Каково назначение оператора continue?

Лабораторная работа № 3.
Массивы и указатели в программах на языке С++

Цель работы

Познакомиться с принципами использования массивов, указателей и адресной арифметикой в программах на языках C и C++.

Теоретические сведения

В языке C между указателями и массивами существует тесная связь. Например, когда объявляется массив в виде int array[25], то этим определяется не только выделение памяти для двадцати пяти элементов массива, но и для указателя с именем array. Значение array равно адресу первого по счету (нулевого) элемента массива, т.е. сам массив остается безымянным, а доступ к элементам массива осуществляется через указатель с именем array. С точки зрения синтаксиса языка указатель array является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя.

Поскольку имя массива является указателем, допустимо, например, такое присваивание:

int array[25];

int *ptr;

ptr = array;

Здесь указатель ptr устанавливается на адрес первого элемента масcива, причем присваивание ptr = array можно записать в эквивалентной форме ptr = & array[0].

Для доступа к элементам массива существует два способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, array[16] = 3 или array[i+2] = 7. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Одно из этих выражений должно быть указателем, а второе - выражением целого типа. Последовательность записи этих выражений может быть любой, но в квадратных скобках записывается выражение следующее вторым. Поэтому записи array[16] и 16[array] будут эквивалентными и обозначают элемент массива с номером шестнадцать. Указатель используемый в индексном выражении не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная. В частности после выполнения присваивания ptr=array доступ к шестнадцатому элементу массива можно получить с помощью указателя ptr в форме ptr[16] или 16[ptr].

Второй способ доступа к элементам массива связан с использованием адресных выражений и операции разадресации в форме *(array+16)=3 или *(array+i+2)=7. При таком способе доступа адресное выражение равное адресу шестнадцатого элемента массива тоже может быть записано разными способами *(array+16) или *(16+array).

При реализации на компьютере первый способ приводится ко второму, т.е. индексное выражение преобразуется к адресному. Для приведенных примеров array[16] и 16[array] преобразуются в *(array+16).

Для доступа к начальному элементу массива (т.е. к элементу с нулевым индексом) можно использовать просто значение указателя array или ptr. Любое из присваиваний

*array = 2;

array[0] = 2;

*(array+0) = 2;

*ptr = 2;

ptr[0] = 2;

*(ptr+0) = 2;

присваивает начальному элементу массива значение 2, но быстрее всего выполнятся присваивания *array=2 и *ptr=2, так как в них не требуется выполнять операции сложения.

Указатели на многомерные массивы в языке C - это массивы массивов, т.е. такие массивы, элементами которых являются массивы. При объявлении таких массивов в памяти компьютера создается несколько различных объектов. Например при выполнении объявления двумерного массива int arr2[4][3] в памяти выделяется участок для хранения значения переменной arr, которая является указателем на массив из четырех указателей. Для этого массива из четырех указателей тоже выделяется память. Каждый из этих четырех указателей содержит адрес массива из трех элементов типа int, и, следовательно, в памяти компьютера выделяется четыре участка для хранения четырех массивов чисел типа int, каждый из которых состоит из трех элементов. Такое выделение памяти показано на схеме на рис. 6.

Рис. 6. Распределение памяти для двумерного массива

Таким образом, объявление arr2[4][3] порождает в программе три разных объекта: указатель с идентификатором arr, безымянный массив из четырех указателей и безымянный массив из двенадцати чисел типа int. Для доступа к безымянным массивам используются адресные выражения с указателем arr. Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме arr2[2] или *(arr2+2). Для доступа к элементам двумерного массива чисел типа int должны быть использованы два индексных выражения в форме arr2[1][2] или эквивалентных ей *(*(arr2+1)+2) и (*(arr2+1))[2]. Следует учитывать, что с точки зрения синтаксиса языка C указатель arr и указатели arr[0], arr[1], arr[2], arr[3] являются константами и их значения нельзя изменять во время выполнения программы.

Размещение трехмерного массива происходит аналогично и объявление float arr3[3][4][5] порождает в программе кроме самого трехмерного массива из шестидесяти чисел типа float массив из четырех указателей на тип float, массив из трех указателей на массив указателей на float, и указатель на массив массивов указателей на float.

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

Например, обращение к элементу arr2[1][2] можно осуществить с помощью указателя ptr2, объявленного в форме int *ptr2=arr2[0] как обращение ptr2[1*4+2] (здесь 1 и 2 это индексы используемого элемента, а 4 это число элементов в строке) или как ptr2[6]. Заметим, что внешне похожее обращение arr2[6] выполнить невозможно так как указателя с индексом 6 не существует.

Для обращения к элементу arr3[2][3][4] из трехмерного массива тоже можнo использовать указатель, описанный как float *ptr3=arr3[0][0] с одним индексным выражением в форме ptr3[3*2+4*3+4] или ptr3[22].

Над указателями можно выполнять унарные операции: инкремент и декремент. При выполнении операций ++ и -- значение указателя увеличивается или уменьшается на длину типа, на который ссылается используемый указатель.

Пример:

int *ptr, a[10];

ptr=& a[5];

ptr++; /* равно адресу элемента a[6] */

ptr--; /* равно адресу элемента a[5] */

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

При динамическом распределении памяти для массивов следует описать соответствующий указатель и присваивать ему значение при помощи функции calloc. Одномерный массив a[10] из элементов типа float можно создать следующим образом

float *a;

a=(float*)(calloc(10, sizeof(float));

if(a == NULL)

// обработка ошибки выделения

Для создания двумерного массива нужно распределить память для массива указателей на одномерные массивы, а затем распределять память для одномерных массивов. Пусть, например, требуется создать массив a[n][m], это можно сделать при помощи следующего фрагмента программы:

main ()

{ double **a;

int n, m, i;

scanf(" %d %d", & n, & m);

a=(double **)calloc(m, sizeof(double *));

for (i=0; i< =m; i++)

a[i]=(double *)calloc(n, sizeof(double));

............

}


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-05-03; Просмотров: 698; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.052 с.)
Главная | Случайная страница | Обратная связь