Двумерные массивы
В языке С++ предусмотрены многомерные массивы. Простейшим из них является двумерный. Объявление двумерного статического массива b, состоящего из 10 строк и 15 столбцов, выглядит следующим образом:
int b[10][15];
В памяти такой массив располагается в последовательных ячейках памяти построчно. Многомерные массивы размещаются так, что при переходе к следующему элементу быстрее всего меняется последний индекс. Для доступа к элементу многомерного массива указываются все его индексы, например, b[i][j] или *(b[i]+j), или *(*(b+i)+j). b[i] является адресом начала i-той строки массива.
При инициализации многомерного массива он представляется либо как массив из массивов, при этом каждый массив заключается в свои фигурные скобки (в этом случае размерности при описании можно не указывать), либо задается общий список элементов в том порядке, в котором элементы располагаются в памяти. Например:
int mas[][]={{1,1},{0,2},{1,0}};
int mas[3][2]={1,1,0,2,1,0};
Можно инициализировать элементы массива одинаковыми значениями, используя функцию memset (объявлена в файлах <memory.h>, <string.h>, <cstring>, <iostream> библиотеки языка):
|
|
void *memset(const void *p, int ch, size_t n);
Она заполняет начинающийся с адреса p блок памяти значением, находящимся в младшем байте аргумента ch. Размер заполняемого блока (в байтах) передаётся аргументом n. Этот способ удобен при необходимости обнулить все элементы массива:
int m1[2][5];
memset(m1, 0, 2*5*sizeof(int));
Можно копировать весь массив целиком, используя функцию memcpy (<memory.h>, <string.h>, <iostream>):
void *memcpy(void *dest, const void *src,
size_t count);
Она копирует начинающийся с адреса src блок памяти в область памяти, начинающуюся с адреса dest. Размер копируемого блока (в байтах) передаётся аргументом count. Скопировать все элементы массива mas1 в mas2 можно так:
int mas1[6] = {1,1,0,2,1,0};
int mas2[6];
memcpy(mas2, mas1, 6*sizeof(int));
Рассмотрим пример работы с двумерными массивами.
Задача 1. Для вещественной матрицы размером 3´4 определить среднее арифметическое её элементов и количество отрицательных элементов в каждой строке.
// Листинг 7.1
#include <fstream>
#include <iostream>
using namespace std;
int main() {
setlocale(LC_ALL, "Russian");
// Число строк и столбцов матрицы
const int n = 3, m = 4;
double a[n][m]; // Определение матрицы
int i, j, num;
// Заполнение матрицы (ввод с клавиатуры)
cout << "Введите матрицу с клавиатуры" << endl;
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
cin >> a[i][j];
// Вывод матрицы на экран
cout << "Матрица:" << endl;
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j)
cout << a[i][j] << "\t"; // Конец for j
cout << endl;
} // Конец for i
// Вычисление среднего арифметического и кол-ва
|
|
// отрицательных элементов в каждой строке
double average = 0;
for (i = 0; i < n; ++i) {
num = 0;
for (j = 0; j < m; ++j) {
average += a[i][j];
if(a[i][j] < 0)
++num;
}
cout << "В строке " << i <<
" отрицательных элементов " << num << endl;
}
average /= n*m;
cout <<"Среднее арифметическое "<<average<<endl;
return 0;
}
Результат выполнения программы:
Введите матрицу с клавиатуры
-1 2 3 -4
5 6 7 8
9 -10 11 12
Матрица:
-1 2 3 -4
5 6 7 8
9 -10 11 12
В строке 0 отрицательных элементов 2
В строке 1 отрицательных элементов 0
В строке 2 отрицательных элементов 1
Среднее арифметическое 4
Динамические массивы
Динамические массивы создают с помощью операции new языка С++ или с помощью функций динамического распределения памяти библиотеки С.
В случае, когда память для массива выделяется с помощью оператора new, он имеет следующий вид:
указатель = new тип_массива[размер];
Здесь размер задаёт количество элементов размещаемого массива. Например:
int n = 100;
double * k = new double[n];
Создаётся переменная k – указатель на double, в динамической памяти (heap-области) отводится непрерывный участок, достаточный для размещения 100 элементов вещественного типа, и адрес начала этого участка заносится в указатель k.
Если память выделить не удалось, по стандарту должно порождаться исключение std::bad_alloc.
Динамические массивы нельзя при создании инициализировать, и они не обнуляются.
Преимущество динамических массивов состоит в том, что размерность может быть задана переменной, поскольку выделение памяти осуществляется на этапе выполнения программы. Доступ к элементам динамического массива осуществляется точно так же, как к статическим. Например, к 10-му элементу массива k можно обратиться как k[10] или *(k + 10).
Память, зарезервированная для динамического массива с помощью оператора new [], должна освобождаться оператором delete [], который имеет следующий вид:
delete [] указатель;
Например: delete [] k;
Задача 2. Ввести с клавиатуры набор вещественных чисел, количество которых заранее не фиксировано, и найти среди них максимальное число.
// Листинг 7.2
#include <iostream>
using namespace std;
int main() {
double max;
int i, n;
cout << "Input n" << endl;
cin >> n; // n - число элементов в массиве
// Выделение динамической памяти
double * a = new double[n];
for (i = 0; i < n; ++i) // Цикл ввода чисел
cin >> a[i];
// Определение максимального элемента
max = a[0];
for (i = 1; i < n; ++i)
if (a[i] > max) max = a[i];
cout << "max = " << max << endl;
delete [] a; // Освобождение памяти
return 0;
}