С++ автоматически передаёт массивы функциям, используя моделируемую передачу параметров по ссылке – вызываемые функции могут изменять значения элементов в исходных массивах источника вызова. Значение имени массива является адресом нулевого элемента массива.
Для функций С++, обрабатывающих одномерные массивы, необходима информация о типе данных массива, адресе начала массива и количестве элементов в нём. При этом функции могут изменять значения элементов в исходных массивах.
Традиционный для языков С/С++ подход заключается в передаче указателя на начало массива (первый параметр) и размера массива (второй параметр). Указатель сообщает функции местонахождение массива в памяти и тип его данных. Можно также в первом параметре использовать не указатель, а тип с квадратными скобками. Если в квадратных скобках указан размер массива, то компилятор его проигнорирует.
Чтобы передать массив в качестве фактического параметра в функцию, необходимо указать имя массива без квадратных скобок.
|
|
Рассмотрим программу с функцией, изменяющей значения элементов переданного ей одномерного массива (увеличивающей каждый элемент массива в 2 раза).
// Листинг 9.3
#include <iostream>
using namespace std;
void modifyArray(int [], int); // Прототип функции
// Эквивалентный вид прототипа:
// void modifyArray(int *, int);
int main() {
const int n = 5; // Число элементов в массиве
int a[n] = {0, 1, 2, 3, 4};
// Вывод на экран значений исходного массива
for (int i = 0; i < n; ++i)
cout << a[i] << '\t';
cout << endl;
// Массив передаётся по указателю
modifyArray(a, n);
// Вывод значений модифицированного массива
for (int i = 0; i < n; ++i)
cout << a[i] << '\t';
cout << endl;
return 0;
}
void modifyArray(int b[], int n)
// Эквивалентный вид заголовка:
// void modifyArray(int *b, int n)
{
for (int j = 0; j < n; ++j)
b[j] *= 2;
}
Результат выполнения программы:
0 1 2 3 4
0 2 4 6 8
Существует ещё один метод предоставления функции необходимой информации – указание диапазона участка памяти с элементами. Это осуществляется путём передачи двух указате лей: один идентифицирует начало диапазона, а второй – конец. В стандартной библиотеке шаблонов (STL) в основном реализовано использование диапазонов. В случае массива аргумент, указыва ющий конец диапазона, представляет собой указатель на ячейку памяти, следующую за последним элементом из диапазона (так называемое «запредельное значение»). Аргументы, обозначаю щие диапазон, указывают функции, какие элементы следует обрабатывать.
Рассмотрим программу с функцией, суммирующей элементы массива из заданного дипазона.
// Листинг 9.4
#include <iostream>
using namespace std;
int sum(int * begin, int* end) { // Указатели
|
|
int * p; // на начало и конец диапазона
int s = 0;
for (p = begin; p!= end; ++p)
s += *p;
return s;
}
int main() {
setlocale(LC_CTYPE, "Russian");
const int n = 7;
int mas[n] = {1, 2, 3, 4, 5, 6, 7};
cout << "Сумма всех элементов массива "
<< sum(mas, mas + n) << endl;
cout << "Сумма трёх первых элементов массива "
<< sum(mas, mas + 3) << endl;
cout << "Сумма 4-х последних элементов массива "
<< sum(mas + n - 4, mas + n) << endl;
return 0;
}
Результат выполнения программы:
Сумма всех элементов массива 28
Сумма трёх первых элементов массива 6
Сумма 4-х последних элементов массива 22
При передаче в качестве параметров многомерных массивов все размерности должны передаваться в качестве параметров.
Если статический (или динамический в виде непрерывного участка памяти) многомерный массив передан с помощью указателя на его нулевой элемент, внутри функции массив интерпретируется как занимающий непрерывный участок памяти одномерный (с размерностью, равной произведению всех размерностей многомерного массива), а индексы элемента массива должны пересчитываться в функции в один индекс.
Рассмотрим программу, в которой в функцию передаются в качестве параметров матрицы (представляющие собой статический массив и динамический в виде непрерывного участка памяти) и их размерности. Функция возвращает сумму элементов матрицы.
// Листинг 9.5
#include <stdlib.h>
#include <iostream>
using namespace std;
int sum(int *, int, int); // Прототип функции
int main() {
int i, j, m, n, *b;
// Статический массив a имеет тип int[][]
int a[2][3] = {{1,2,3},{4,5,6}};
// Вывод элементов массива a
cout << "Массив a:" << endl;
for (i = 0; i < 2; ++i) {
for (j = 0; j < 3; ++j)
cout << a[i][j] << "\t";
cout << endl;
}
cout << "Сумма элементов a = "
<< sum(&a[0][0], 2, 3) << endl;
// Имя массива a в функцию sum передавать нельзя
// из-за несоответствия типов int* и int[][]
cout << "Введите количество строк и столбцов "
"матрицы b";
cin >> m >> n;
// Динамический массив в виде непрерывного
// участка памяти, b имеет тип int *
b = (int*)malloc(m*n*sizeof(int));
for (i = 0; i < m; ++i)
for (j = 0; j < n; ++j)
// Пересчёт двух индексов в один
cin >> b[i * n + j];
// Вывод элементов массива b
cout << "Массив b:" << endl;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
cout << b[i * n + j] << "\t";
cout << endl;
}
cout <<"Сумма элементов b = "<<sum(b,m,n)<<endl;
free(b); // Освобождение памяти
return 0;
}
// Функция возвращает сумму всех элементов матрицы
int sum(int * matr, int nr, int nc) {
int i, j, s = 0;
for (i = 0; i < nr; ++i)
for (j = 0; j < nc; ++j)
// Пересчёт двух индексов в один
s += matr[i * nc + j];
return s;
}
Для использования в функции двух индексов память для двумерного динамического массива необходимо выделять в два этапа (см. рис. 7.1 Практического занятия 7):
1) для одномерного вспомогательного массива указателей на одномерные массивы-строки;
2) для одномерных массивов – строк матрицы.
Рассмотрим программу, в которой в функцию передаётся в качестве параметров матрица (созданная в виде динамического массива) и её размерности.
Задача: сформировать массив, представляющий прямоугольную целочисленную матрицу, размеры (n – число строк, m – число столбцов) матрицы вводить с клавиатуры в процессе работы программы. Заполнить матрицу путём считывания данных из текстового файла (matrix.txt), вывести её на экран, вычислить сумму элементов матрицы, увеличить каждый элемент матрицы в два раза, записать измененную матрицу в новый файл (matrix1.txt), очистить динамическую память. Оформить вычисление суммы в виде функции.
// Листинг 9.6
#include <iostream>
#include <fstream>
using namespace std;
int sum(int **, int, int); // Прототип функции
void main() {
int n, m, i, j;
cin >> n >> m; // Число строк и столбцов
// Выделение динамической памяти для матрицы.
//matr - указатель на массив указателей на строки
|
|
int ** matr = new int * [n];
for (i = 0; i < n; ++i)
matr[i] = new int [m];
// Открытие файла для ввода данных
ifstream infile("matrix.txt");
if (!infile) {
cout << "File cannot be opened" << endl;
return; // Выход из программы
}
// Заполнение матрицы считыванием из файла
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
infile >> matr[i][j];
cout << matr[i][j] << "\t";
} // for j
cout << endl;
} // for i
infile.close(); // Закрытие файла
// Вычисление суммы
cout << "sum = " << sum(matr, n, m) << endl;
// Открытие файла для вывода
ofstream outfile("matrix1.txt");
if (!outfile) {
cout << "File cannot be opened" << endl;
return; // Выход из программы
}
// Изменение матрицы и запись в файл
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
matr[i][j] *= 2;
outfile << matr[i][j] << "\t";
} // for j
outfile << endl;
} // for i
outfile.close(); // Закрытие файла
// Освобождение динамической памяти
for (i = 0; i < n; i++)
delete [] matr[i];
delete [] matr;
}
// Вычисление суммы всех элементов матрицы
int sum(int ** mass, int n, int m) {
int i, j, s = 0;
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
s += mass[i][j];
return s;
}
Задание. Реализовать на языке С++ программу, решающую задачу согласно варианту. Использовать динамическое выделение памяти для двумерных массивов. Размеры матрицы вводить с клавиатуры. Элементы матрицы вводить из заранее созданного текстового файла. Каждый пункт задания должен быть оформлен в виде отдельной функции, вычисляющей и возвращающей необходимое значение.
Для выделения памяти для динамического двумерного массива предусмотреть функцию, получающую в качестве параметров размеры матрицы и возвращающую указатель на созданный вспомогательный динамический массив указателей на строки.
Результаты вывести на экран и в файл, выводы матрицы оформить в виде отдельных функций. Для вывода матрицы на экран построчно использовать рекурсивную функцию вывода на экран одномерного массива заданного размера.
Вариант 1
Дана целочисленная прямоугольная матрица. Переставляя строки заданной матрицы, расположить их в соответствии с ростом характеристик. Характеристикой строки целочисленной матрицы назовем сумму её положительных чётных элементов.
|
|
Вариант 2
Дана целочисленная прямоугольная матрица. Определить номера строк и столбцов всех седловых точек матрицы. Матрица A имеет седловую точку Aij, если Aij является минимальным элементом в i-й строке и максимальным в j-м столбце.
Вариант 3
Дана вещественная квадратная матрица. Построить результат сглаживания заданной матрицы. Соседями элемента Aij в матрице назовём элементы Akl с i-1≤k≤i+1, j-1≤l≤j+1, (k,l)≠(i,j). Операция сглаживания матрицы формирует новую матрицу того же размера, каждый элемент которой получается как среднее арифметическое имеющихся соседей соответствующего элемента исходной матрицы.
Вариант 4
Дана целочисленная прямоугольная матрица. Определить номер строки, в которой находится самая длинная серия одинаковых элементов.
Вариант 5
Дана целочисленная квадратная матрица. Определить минимум среди сумм модулей элементов диагоналей, параллельных побочной диагонали матрицы.
Вариант 6
Коэффициенты системы линейных уравнений заданы в виде прямоугольной матрицы. С помощью допустимых преобразований привести систему к треугольному виду.
Вариант 7
Дана целочисленная матрица. Определить максимальное из чисел, встречающихся в заданной матрице более одного раза.
Вариант 8
Дана целочисленная прямоугольная матрица. Переставляя столбцы заданной матрицы, расположить их в соответствии с ростом характеристик. Характеристикой столбца целочисленной матрицы назовём сумму модулей его отрицательных нечётных элементов.
Вариант 9
Дана вещественная квадратная матрица. Найти такие m, что реверс m-ой строки матрицы совпадает с m-м столбцом.
Вариант 10
Путём перестановки элементов квадратной вещественной матрицы добиться того, чтобы её максимальный элемент находился в левом верхнем углу, следующий по величине – в позиции (1,1), следующий по величине – в позиции (2,2) и т.д., заполнив таким образом всю главную диагональ.
Вариант 11
Дана целочисленная прямоугольная матрица. Упорядочить строки матрицы по возрастанию максимального количества одинаковых элементов в каждой строке.
Вариант 12
Дана целочисленная прямоугольная матрица. Осуществить циклический сдвиг элементов каждой строки матрицы на k элементов вправо или сдвиг элементов каждого столбца вниз (в зависимости от введённого режима); k может быть больше количества элементов в строке или столбце.
Вариант 13
Дана целочисленная прямоугольная матрица. Уплотнить заданную матрицу, удаляя из неё строки и столбцы, заполненные нулями.
Вариант 14
Дана вещественная квадратная матрица. Осуществить циклический сдвиг элементов матрицы вправо на k элементов таким образом: элементы 1-й строки сдвигаются в последний столбец сверху вниз, из него – в последнюю строку справа налево, из неё – в первый столбец снизу вверх, из него – в первую строку; для остальных элементов – аналогично.
Вариант 15
Дана целочисленная квадратная матрица. Определить максимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.
Вариант 16
Дана целочисленная прямоугольная матрица. Переставляя строки заданной матрицы, расположить их в соответствии с убыванием характеристик. Характеристикой строки матрицы назовём сумму её отрицательных чётных элементов.
Вариант 17
Дана целочисленная прямоугольная матрица. Определить номера строк и столбцов всех седловых точек матрицы. Матрица М имеет седловую точку Мij, если Мij является максимальным элементом в i-й строке и минимальным в j-м столбце.
Вариант 18
Дана целочисленная прямоугольная матрица. Определить номер столбца, в котором находится самая длинная серия одинаковых элементов.
Вариант 19
Дана целочисленная квадратная матрица. Подсчитать количество локальных минимумов заданной матрицы. Элемент матрицы называется локальным минимумом, если он строго меньше всех имеющихся у него соседей.
Вариант 20
Дана целочисленная квадратная матрица. Определить минимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.