Файл: Особенности и примеры использования массивов при разработке программ.pdf
Добавлен: 29.03.2023
Просмотров: 69
Скачиваний: 2
СОДЕРЖАНИЕ
Основные понятия о циклических алгоритмах
1.2. Базовые структуры алгоритмов. Циклические структуры алгоритмов
Использование циклических алгоритмов при обработке массивов
2.1.Циклические алгоритмы в С++
2.2. Особенности обработки одномерных массивов
2.3. Особенности обработки двумерных массивов
Рисунок 3 – Циклическая структура с предусловием
Рисунок 4 – Циклическая структура с постусловием
Цикл с предусловием можно прочитать следующим образом:
пока проверка условия дает результат «да», выполнять действие.
Если при очередной проверке условия будет получено результат «нет», повторное выполнение действия будет прекращено и произойдет выход из цикла.
Например, для подсчета остатка от деления целого числа t на целое число n с помощью вычитания можно воспользоваться циклом:
пока t> n, уменьшить t на n.
В цикле с постусловием (рисунок 4) условие цикла формулируется противоположным образом: если очередная проверка условия дает результат "да", происходит выход из цикла. Цикл с постусловием можно сокращенно прочитать так:
повторять действие до получения результата «да» при проверке условия.
Например, подсчет остатка от деления целого числа t на целое число n (t> n) можно реализовать с помощью цикла:[9]
повторять уменьшить t на n до t <n.
Стоит обратить внимание на то, что является общим для обоих типов цикла:
– обе базовые структуры цикла являются замкнутыми;
– количество повторений цикла определяется его условием;
– выход из цикла происходит только через проверку условия цикла.
Наиболее существенная разница между типами циклов заключается в том, что тело цикла с постусловием обязательно выполняется хотя бы один раз – до первой проверки условия, а цикл с предусловием может не выполнятся ни разу, если при первой же проверке условия имеем результат «нет». Поэтому рассмотренные типы циклов не являются взаимозаменяемыми: цикл с постусловием можно заменить циклом с предусловием, а наоборот – нет.
Использование циклических алгоритмов при обработке массивов
2.1.Циклические алгоритмы в С++
Рассмотрим реализацию циклических алгоритмов на языке С++, в котором существую три разновидности операторов цикла:
– оператор цикла for;
– оператор цикла с предусловием while;
– оператор цикла с постусловием do ... while.
Все операторы цикла непременно содержат следующие составные части:
– присваивания исходных значений (инициализация);
– условие продолжения цикла;
– тело цикла;
– изменение параметра (счетчика) цикла.
Оператор for обычно используется, когда есть заранее известное количество повторений или когда условие продолжения выполнения цикла записывается кратким выражением. Примерами использования данного оператора являются вычисления сумм заданного количества слагаемых, поиск минимального (максимального) элемента последовательности чисел, сортировки элементов массива по возрастанию (убыванию) и т.д.[7]
Синтаксис оператора следующий:
for (<инициализация>; <условие>; <модификации>)
{
<тело цикла>;
}
Конструкция этого оператора состоит из трех основных блоков, размещенных в круглых скобках и отделенных друг от друга точкой с запятой (;) и команд (тела цикла), которые могут многократно повторятся. В начале выполнения оператора цикла, однократно, в блоке инициализации задаются начальные значения переменных, которые управляют циклом. Затем проверяется условие и, если оно выполняется, то управление переходит к выполнению тела цикла. Блок модификации меняет параметры цикла и, в случае истинности условия, выполнение цикла продолжается. Если условие не выполняется (false или равно нулю), то цикл прерывается и управление передается на оператор, следующий за оператором for. Существенным является то, что проверка условия выполняется в начале цикла. Это значит, что тело цикла может не выполниться ни разу, если условие сначала ошибочное. Каждое повторение (шаг) цикла называется итерацией.
Простой пример для вычисления суммы проиллюстрирует использования оператора for:
int s = 0;
for (int i = 1; i <= 10; i ++)
s + = i;
Этот оператор цикла можно прочитать так: "выполнить команду s + = i 10 раз (для значений i от 1 до 10 включительно, где i при каждой итерации увеличивается на 1)". В этом примере есть два присваивания начальных значений: s = 0 и i = 1, условие продолжения цикла: (i <= 10) и изменение параметра: i ++. Телом цикла является команда s + = i.
Порядок выполнения этого цикла компьютером такой:
1) присваиваются начальные значения (s = 0, i = 1);
2) проверяется условие (i <= 10);
3) если условие истинное (true), выполняется команда (или команды) тела цикла: к сумме, полученной на предыдущей итерации, добавляется новое число;
4) параметр цикла увеличивается на 1.
Далее возвращаемся к пункту 2. Если условие в пункте 2 не будет выполнено (false), произойдет выход из цикла.[5]
В операторе возможные конструкции, когда отсутствует тот или иной блок: инициализация может отсутствовать, если начальное значение задать предварительно; условие – если предполагается, что условие всегда истинно, то есть следует непременно выполнять тело цикла, пока не встретится оператор break; а модификации – если прирост параметра осуществлять в теле цикла. В этих случаях само выражение блока упускается, но точку с запятой (;) обязательно нужно оставить.
Стоит отметить, что оператор for допускает запись тела цикла непосредственно в своих параметрах. Например, сумму чисел можно вычислить следующим образом:
for (int s = 0, i = 1; i <= 10; s + = i ++)
В этом примере отсутствует тело цикла, а в блоке инициализации находится два оператора, которые разделены операцией "запятая" и задают начальные значения переменных s и i.
Рассмотрим простые примеры использования оператора цикла for. [6]
1) Вывод на экран чисел от 1 до 10 с их квадратами:
for (int i = 1; i <11; i ++)
cout << i <<" " << i * i;
Цикл выполняется при значениях i = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. После этого i примет значение 11 и условие (11 <11) не выполнится (false) – произойдет выход из цикла.
2) Вывод положительных нечетных целых от 1 до 100 с их квадратами. Цикл записывается аналогично предыдущему, но параметр будет увеличиваться на 2, то есть цикл будет выполняться для значений i = 1, 3, 5, 7, ..., 97, 99.
for (int i = 1; i <100; i + = 2)
cout << i <<" " << i * i;
3) Вычисление факториала F = n! (напомним, что факториал вычисляется по формуле n! = 1 * 2 * 3 * ... * (n-2) * (n-1) * n, например: 4! = 1 * 2 * 3 * 4 = 24) . Приведем три аналогичных по действию формы записи оператора for:
1) int F = 1, n = 5,
for (int i = 1; i <= n; i ++)
F * = i;
2) int F, i, n = 5,
for (F = 1, i = 1; i <= n; F * = i ++)
3) int F = 1, i = 1, n = 5,
for (; i <= n;)
F * = i ++;
Для досрочного начала очередной итерации цикла можно использовать оператор перехода к следующей итерации continue, например:
for (i = 0; i <20; i ++)
{
if (array [i] == 0) continue;
array [i] = 1 / array [i];
}
Для заблаговременного выхода из цикла применяют операторы break (выход из конструкции) или return (выход из текущей функции). [19]
Некоторые варианты применения оператора for повышают его гибкость за счет возможности использования нескольких переменных-параметров цикла.
Например:
int top, bot;
char string [100], temp;
for (top = 0, bot = 98; top <bot; top++, bot– –)
{
temp = string [top];
string [top] = string [bot];
string [bot] = temp;
}
В этом примере для реализации записи строки символов в обратном порядке параметрами цикла являются две переменные top и bot, значение которых движутся навстречу друг другу. Заметим, что в блоке инициализации оператора for через запятую задаются начальные значения сразу двух переменных. Так же через запятую записаны модификации этих переменных после условного выражения.
Еще одним интересным вариантом применения оператора for является бесконечный цикл. Для организации такого цикла можно записать пустое условное выражение, а для выхода из цикла воспользоваться условным оператором if вместе с оператором break. [20]
Например:
for ( ; ; )
{
if (<некоторое условие>) break;
}
Циклы могут быть вложены друг в друга. При использовании вложенных циклов надо составлять программу таким образом, чтобы внутренний цикл полностью укладывался в тело внешнего цикла, то есть циклы не должны пересекаться. В свою очередь, внутренний цикл может содержать собственные вложенные циклы. Имена параметров внешнего и внутреннего циклов должны быть разными. Допускаются следующие конструкции:
fог(k = 1; k <= 10; k ++)
{
fог (i = 1; i <= 10; i ++)
{
fог (t = 1; t <= 10; t ++)
{
...
}
}
}
Вложенные циклы используются, например, для вывода на экран треугольника "звездочек":
*
**
***
****
Для вывода одной строки следует сформировать отдельный цикл, а для вывода нескольких таких строк необходимо вложить первый цикл в цикл, который будет формировать переход к следующей строке. В первой строке должна быть только одна "звездочка", во второй – две, в третьей – три и т.д. То есть строка с номером і должна состоять из і "звездочек", поэтому внутренний цикл будет выполняться і раз. [18]
int i, j, m;
cout << "Ввести количество строк m:";
cin >> m;
for (i = 1; i <= m; i ++)
{
for (j = 1; j <= i; j ++) cout << "*";
cout << endl;
}
Операторы с предусловием и постусловием используются для организации циклов и являются альтернативными к оператору for. Обычно цикл с предусловием используется, если количество повторений заранее неизвестно, а для многократного повторения тела цикла известно условие, при истинности которого цикл продолжает выполнение. Это условие следует проверять каждый раз перед очередной итерацией. Например, при считывании данных из файла условием цикла является наличие данных непосредственно в файле, то есть повторять чтение данных следует до тех пор, пока указатель не будет указывать на конец файла.
Синтаксис цикла с предусловием следующий:
while (<условие>)
{
<тело цикла>
};
Последовательность операторов (тело цикла) выполняется пока условие является истинным, а выход из цикла осуществляется, когда условие станет ложным. Если условие является ошибочным при вхождении в цикл, то последовательность операторов ни разу не выполнится, а управление будет передаваться к следующему оператору программы.
Цикл с постусловием используется, если есть необходимость проверять истинность условия каждый раз после очередной итерации. Как отмечалось выше, отличие цикла с предусловием от цикла с постусловием заключается в первой итерации: цикл с постусловием всегда выполняется по крайней мере один раз независимо от условия.[17]
Синтаксис цикла с постусловием следующий:
do
{
<тело цикла>
}
while (<условие>);
Последовательность операторов (тело цикла) выполняется один или несколько раз, пока условие станет ложным. Оператор цикла do ... while используется в тех случаях, когда есть необходимость выполнить тело цикла хотя бы один раз, поскольку проверка условия осуществляется после выполнения операторов.
Если тело цикла состоит из одного оператора, то операторные скобки {} не является обязательны.
Операторы while и do ... while могут преждевременного завершиться при выполнении операторов break и return внутри тела цикла.
Рассмотрим отличие работы разных операторов цикла на примере вычисления суммы всех нечетных чисел в диапазоне от 10 до 100:
1) с использованием оператора for:
int i, s = 0;
for (i = 11; i <100; i + = 2)
s + = i;
2) с использованием оператора while:
int s = 0, i = 11;
while (i <100)
{
s + = i;
i + = 2;
}
3) с использованием оператора do ... while:
int s = 0, i = 11;
do
{
s + = i;
i + = 2;
}
while (i <100);
2.2. Особенности обработки одномерных массивов
Часто, в процессе разработки программы, возникает потребность хранить большое количество однотипных значений, которые должны поддаваться одинаковым методам обработки. Например, экзаменационные оценки студентов, следует вводить, выводить, анализировать (сравнение с "2" или "5"), изменять при необходимости и тому подобное. Такие однотипные значения имеет смысл хранить в одной переменной, перенумеровать их внутри этой переменной, предоставить доступ к этим значениям по индексу и обрабатывать эти значения в цикле (номер индекса должен совпадать с значением параметра цикла).
Массив – это упорядоченная совокупность однотипных элементов. Массивы широко применяются для хранения и обработки однородной информации, например таблиц, векторов, матриц, коэффициентов уравнений и т.д. [16]
Каждый элемент массива однозначно можно определить по имени массива и индексе. Имя массива (идентификатор) подбирают по тем же правилам, что и для переменных. Индексы определяют местонахождение элемента в массиве. К примеру, элементы вектора имеют один индекс – номер по порядку; элементы матриц или таблиц имеют по два индекса: первый означает номер строки, второй – номер столбца. Количество индексов определяет размерность массива. Например, векторы в программах – это одномерные массивы, матрицы – двумерные.