Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 6.1
#include < iostream.h> #include < iomanip.h> void main() { const int nrow = 10, ncol = 20; int a[nrow][ncol]; int i, j; setlocale(LC_ALL, " Russian");
cout < < “Введите элементы массива: ” < < endl;
for (i = 0; i < nrow; i++) for (j = 0; j < ncol; j++) cin > > a[i][j];
for (i = 0; i < nrow; i++) { for (j= 0; j < ncol; j++) cout < < setw(4) < < a[i][j] < < “ ” cout < < endl; }
int n_pos_el; float s = 0;
for (i = 0; i < nrow; i++) { n_pos_el = 0;
for (j = 0; j < ncol; j++) { s += a[i][j]; if (a[i][j] > 0) n_pos_el++; } cout < < “Строка: ”< < i < < “количество: ” < < n_pos_el < < endl; }
s /= nrow * ncol; cout < < “Среднее арифметическое: ” < < s < < endl; } Размерности массива заданы именованными константами, что позволяет легко их изменять. Для упрощения отладки рекомендуется задать небольшие значения этих величин или приготовить тестовый массив в текстовом файле и изменить программу так, чтобы она читала значения из файла. Следует составлять тестовые примеры таким образом, чтобы строки массива содержали разное количество отрицательных элементов (ни одного элемента, один и более элементов, все элементы). При вычислении количества положительных элементов для каждой строки выполняются однотипные действия: обнуление счетчика, просмотр каждого элемента строки и сравнение его с нулем, при необходимости увеличение счетчика на единицу, а после окончания вычислений - вывод результирующего значения счетчика. Здесь следует обратить внимание на два момента. Во-первых, требуется еще до написания алгоритма решить, каким образом будут храниться результаты. Для хранения среднего арифметического необходима одна простая переменная вещественного типа. Количество же положительных элементов для каждой строки свое, и в результате получается столько значений, сколько строк в матрице. В данном примере мы можно отвести для хранения этих значений одну-единственную переменную целого типа, поскольку они вычисляются последовательно, после чего выводятся на экран. Однако в других задачах эти значения могут впоследствии потребоваться одновременно. В этом случае для их хранения придется описать целочисленный массив с количеством элементов, равным количеству строк матрицы. Второй важный момент - место инициализации суммы и количества. Сумма обнуляется перед циклом просмотра всей матрицы, а количество положительных элементов - перед циклом просмотра очередной строки, поскольку для каждой строки его вычисление начинается заново. Следует записывать операторы инициализации накапливаемых в цикле величин непосредственно перед циклом, в котором они вычисляются. При написании вложенных циклов необходимо следить за отступами. Все операторы одного уровня вложенности должны начинаться в одной и той же колонке. Это облегчает чтение программы и, следовательно, поиск ошибок. По вопросу расстановки фигурных скобок существуют разные мнения специалистов. В настоящее время наиболее распространенными являются два стиля: стиль 1TBS (One True Bracing Style), которого придерживались основоположники языка С - Б. Керниган (Brian Kerni-ghan) и Д. Ритчи (Dennis Ritchie), и стиль Алмена (Eric Allman). Динамические массивы. В динамической области памяти можно создавать двумерные массивы с помощью операции new или функции malloc. Остановимся на первом варианте, поскольку он более безопасен и прост в использовании. При выделении памяти сразу под весь массив количество строк (самую левую размерность) можно задавать с помощью переменной или выражения, а количество столбцов должно быть константным выражением, то есть явно определено до выполнения программы. После слова new записывается тип создаваемого массива, а затем - его размерности в квадратных скобках (аналогично описанию «обычных», нединамических массивов), например: int n; const int m = 5; cin > > n; int (*a)[m] = new int [n][m]; //1 int ** b = (int **) new int [n][m]; //2 В этом фрагменте показано два способа создания динамического массива. В операторе 1 адрес начала выделенного с помощью new участка памяти присваивается переменной а, определенной как указатель на массив из m элементов типа int. Именно такой тип значения возвращает в данном случае операция new. Скобки необходимы, поскольку без них конструкция интерпретировалась бы как массив указателей. Всего выделяется n элементов. В операторе 2 адрес начала выделенного участка памяти присваивается переменной b которая описана как «указатель на указатель на int, поэтому перед присваиванием требуется выполнить преобразование типа. По стандарту в этом случае рекомендуется применять другую операцию преобразования типа, но старые компиляторы могут ее не поддерживать: int ** b = reinterpret_cast < int-**> (new int [n][m]); Обращение к элементам динамических массивов производится точно так же, как к элементам «обычных», с помощью конструкции вида a[i ][ j]. Поскольку для доступа к элементу массива применяется две операции разадресации, то переменная, в которой хранится адрес начала массива, должна быть указателем на указатель. Более универсальный и безопасный способ выделения памяти под двумерный массив, когда обе его размерности задаются на этапе выполнения программы, приведен ниже: int nrow, ncol; setlocale(LC_ALL, " Russian"); cout < < “Введите количество строк и столбцов: ”; cin > > nrow > > ncol; int **a = new int *[nrow]; //1 for(int i = 0; i < nrow; i++) //2 a[i] = new int [ncol]; //3
В операторе 1 объявляется переменная типа «указатель на указатель на i nt» и выделяется память под массив указателей на строки массива (количество строк - nrow). В операторе 2 организуется цикл для выделения памяти под каждую строку массива. В операторе 3 каждому элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива. Каждая строка состоит из ncol элементов типа int (рисунок 6.2). int **a int *a[nrow] int a[nrow][ncol]
nstb Рисунок 6.2 - Схема динамической области памяти, выделяемой под массивы
Освобождение памяти из-под массива с любым количеством измерений выполняется с помощью операции delete [].
|