Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Visual_C_console.pdf
Скачиваний:
34
Добавлен:
16.05.2015
Размер:
954.14 Кб
Скачать

60

В операторе цикла при проверке окончания цикла использовано строгое неравенство (i < SIZE), поэтому последнее значение переменной цикла i, как это и требуется, будет на 1 меньше заявленного количества элементов массива.

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

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

for (i = SIZE -1;i >= 0; i--)

Практически не отличается обработка элементов массива с шагом, отличным от 1, но при этом появляются две возможности:

1.Шаг обработки указывается в операторе цикла, например: for (i = 0; i < SIZE; i = i + 2)

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

a[2 * i + 1]

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

Примеры обработки одномерных массивов

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

61

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

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

Пример 1. Задан одномерный массив, состоящий из SIZE элементов. Требуется подсчитать сумму этих элементов.

Эта задача решается следующим образом. Обозначим переменную для накопления суммы как sum, а исходный массив обозначим а. Естественно, в начале программы этот массив, переменная sum и переменная, которая будет использоваться в качестве индекса элементов массива, должны быть описаны.

Для ввода элементов массива оформим цикл, который обеспечит последовательное изменение индекса от 0 до SIZE - 1. Тогда на каждом шаге цикла в массив a будет вводиться одно число, которое будет набрано с клавиатуры. Индекс элемента, в который будет записываться вводимое число, совпадает с текущим значением переменной цикла.

После ввода массива приравняем к нулю переменную sum, затем откроем цикл с переменной i, которая последовательно изменяется от 0 до SIZE - 1, и, прибавляя по очереди каждый последующий элемент массива к накапливаемой в переменной sum величине, получим требуемую сумму. После окончания цикла выведем полученный результат.

Ниже приведен текст программы, решающей поставленную задачу.

62

// Программа для вычисления суммы элементов массива

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std;

#define SIZE 5 // Указание размерности массива void _tmain ()

{

double a[SIZE], sum; // Объявление переменных cout <<"Введите " << SIZE << " чисел";

for (int i = 0; i < SIZE; i++) // Ввод элементов массива cin >> a[i];

// Суммирование элементов массива sum = 0;

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

sum = sum + a[i]; // Можно записать и так sum += a[i]; cout << "Сумма = " << sum; // Вывод результата

_getch();

}

Программа работает следующим образом. Оператор double a[SIZE]; резервирует память для размещения SIZE чисел с плавающей точкой (в данном случае 5). Этот оператор может только резервировать память, но никаких значений элементам не присваивает (точнее на выделенном участке памяти хранится информация, которая осталась от предыдущей программы и обычно совершенно бессмысленна).

Выполним статическое тестирование программы. Введем для массива а значения, например, такие: 1.7; 2.91; -0.8; 9.64; 3.4. Массив a вводится, как было отмечено выше. После присвоения переменной sum значения нуль открывается цикл, т.е. переменной цикла i присваивается начальное значение 0 и выполняется собственно цикл. В данном случае тело цикла содержит один оператор, который к начальному значению переменной sum (равное 0) прибавляет значение первого элемента массива а, которое равно 1.7, и эту сумму

63

присваивает переменной sum. На этом операторе проверяется условие выхода из цикла. Поскольку i меньше SIZE, то цикл повторяется, но i принимает значение 1. Снова к предыдущему значению sum (=1.7) прибавляется значение элемента а[1], равное 2.91. Результат (4.61) присваивается переменной sum. Поскольку i не достигло значения SIZE - 1, то процесс повторяется, и переменная sum далее последовательно получает значения

4.61 + (-0.8) = 3.81

3.81 + 9.64 = 13.45

13.45 + 3.4 = 16.85 .

При суммировании последнего элемента массива переменная цикла i имеет значение 4 (т.е. SIZE - 1). В языке С++ во время выполнения операторов цикла типа for значение переменной цикла как бы "запаздывает" на один шаг. Например, в операторе цикла переменной цикла было присвоено значение 0, но там же было записано и приращение этой переменной. Поэтому следовало бы ожидать, что выполнение цикла начнется со значения i = 1, но первый раз цикл выполняется при значении i = 0. Таким образом, хотя приращение переменной цикла и записано в заголовке операторов цикла после присвоения начального значения, но фактически это приращение выполняется после реализации всех операторов цикла непосредственно перед повторением цикла. Поэтому при попытке последующего повторения цикла переменная i принимает значение SIZE (равное 5), условие продолжения цикла оказывается ложным (теперь i не меньше SIZE), следовательно, цикл закончен, и выполнение программы продолжается с оператора, записанного сразу после "тела" цикла. Этим оператором осуществляется вывод значения переменной sum (равное 16.85), и выполнение программы заканчивается.

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

64

Пример 2. Подсчитать количество положительных элементов в массиве из SIZE элементов.

Эта задача отличается от предыдущей тем, что суммируются не сами элементы, а подсчитывается их количество, причем не всех элементов (количество всех элементов известно заранее, оно равно SIZE), а только тех, которые больше нуля.

Для решения этой задачи некоторая переменная (целочисленная), скажем count, выделяется для подсчета количества элементов. После объявления переменных и ввода значений элементов массива этой переменной присваивается значение нуль. После этого в цикле последовательно просматриваются элементы массива.

Если очередной элемент массива больше нуля, то к предыдущему значению переменной count прибавляется единица, если же очередной элемент равен или меньше нуля, то добавление 1 пропускается. Когда все элементы будут просмотрены (т.е. цикл будет "закрыт"), переменная count будет содержать количество положительных элементов.

Ниже приведен текст программы, решающей поставленную задачу.

// Программа для подсчета количества положительных элементов

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std;

#define SIZE 5 // Указание размерности массива void _tmain ()

{

double a[SIZE]; // Объявление массива cout <<"Введите " << SIZE << " чисел";

for (int i = 0; i < SIZE; i++) cin >> a[i];

int count = 0;// Счетчик желательно объявить как целое число

65

// Подсчет количества положительных элементов for (i = 0; i < SIZE; i++)

if (a[i] > 0) count++;

cout << "Количество элементов > 0 = " << count; _getch();

}

Пример 3. Задан одномерный массив, состоящий из SIZE элементов. Найти максимальный элемент.

Для решения выберем "кандидата" на максимальный элемент и назовем его аmах. Теперь будем последовательно сравнивать amax c элементами массива. Если очередной элемент массива больше amax, то заменим "кандидата" на максимальный элемент текущим элементом массива и запомним его индекс. Если же очередной элемент массива меньше amax, то никаких действий выполнять не будем, а перейдем к следующему элементу. Когда таким способом будут обработаны все элементы массива, amax будет содержать значение максимального из элементов массива.

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

Но задача поиска максимального (или минимального) элемента может быть решена и при одновременном формировании элементов массива и поиска среди них максимального (или минимального) элемента. В этом случае в качестве "кандидата" на максимальный элемент можно выбрать минимально возможное в данном компьютере число (при поиске минимума соответственно выбирают максимально возможное число), например, для чисел типа double таким значением является -1.7Е+308 (но можно выбрать число и меньшее по абсолютному значению, например -1.0E100, поскольку при решении реальных задач не может быть таких чисел).

66

Во-вторых, как поступать, если "кандидат" на максимальный элемент и очередной элемент массива равны друг другу. В принципе это зависит от решаемой задачи. Если при равенстве мы будем пропускать обработку для текущего элемента (при сравнении текущего элемента с «кандидатом» на максимальный элемент применяется проверка (‘<’) на строгое неравенство), то обеспечим выбор первого из нескольких равных максимальных элементов. Если же при равенстве мы будем выполнять замену "кандидата" значением текущего элемента массива и запоминать его индекс, то само значение при равенстве, естественно, одинаково, но индексы этих элементов разные. В этом случае будет обеспечен выбор последнего из нескольких равных максимальных элементов.

Для поиска минимального элемента в алгоритме требуется изменить на обратное условие проверки, и желательно изменить имя amax, например, на amin. И последнее, для "кандидата" на максимальный элемент в программе использовано специальное имя (amaх), что удобно для анализа работы программы. Иногда в программу не вводят такую дополнительную переменную, а вместо этого используют значение индекса текущего максимального элемента (в примере этот индекс имеет имя num). Принципиально, это также правильное решение, но менее наглядное. Кроме того, на реализацию алгоритма в этом случае будет затрачено чуть больше времени, поскольку время обращения к индексированной переменной больше времени обращения к обычной переменной на время вычисления адреса элемента по индексу.

Ниже приведен текст программы, решающей эту задачу.

// Программа поиска максимального элемента массива.

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std; #define SIZE 5

 

 

67

void _tmain ()

 

 

{

 

 

double a[SIZE], amax;

// Объявление переменных

int num;

 

// Индекс максимального элемента

cout <<"Введите " << SIZE << " чисел";

for (int i = 0; i < SIZE; i++)

 

cin >> a[i];

 

 

amax = a[0];

// Кандидат на максимальный элемент

num = 0;

// Индекс кандидата на максимальный

элемент

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

if (a[i] > amax) // Текущий элемент больше «кандидата»

{

amax = a[i]; // Замена кандидата на больший a[i] num = i; // Запомнить индекс кандидата

}

cout <<"Максимальный элемент = " << amax << " его индекс " << num;

_getch();

}

Во всех рассмотренных выше программах операция ввода элементов массива выполнялась отдельно от операций по их обработке, но в этих примерах последовательность ввода элементов совпадает с порядком их обработки, поэтому эти операции можно совместить. Для этого достаточно операцию ввода элементов массива (cout <<) записать перед операцией обработки, а цикл ввода исключить. Перед началом цикла в этом случае значение элемента a[0] неизвестно (поскольку этот элемент еще не введен), поэтому для назначения "кандидата" на максимальный элемент следует использовать минимально возможное число, т.е. для переменной amax присвоить значение, например, -1е100. Другими словами, вместо оператора

amax = a[0];

записать:

68

amax = -1e100;

Пример 4. В массиве имеются положительные и отрицательные элементы. Заменить нулем элементы, находящиеся между отрицательными элементами.

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

Ниже приведен текст программы, решающей эту задачу

// Программа замены нулями элементов между отрицательными числами.

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std; #define SIZE 5

int _tmain ()

{

double a[SIZE];

int flag = 0; // Сначала флаг в состоянии «ложно» cout <<"Введите " << SIZE << " чисел";

for (int i = 0; i < SIZE; i++) cin >> a[i];

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

{

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]