Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема11_Указатели.doc
Скачиваний:
1
Добавлен:
03.09.2019
Размер:
113.15 Кб
Скачать

Матрицы и указатели

По аналогии с одномерными массивами посредством указателей можно работать и с многомерными массивами и, в частности, с двумерными или матрицами. Рассмотрим, как связаны матрицы и указатели на следующем примере:

float matrix[20][10];

Для определенности положим, что первый индекс отвечает за строки матрицы, а второй – за столбцы. Таким образом, в нашей матрице 20 строк и 10 столбцов.

Вспомним, что имя массива – это указатель на его первый элемент. Таким образом, matrix является указателем на первый элемент нашего массива. Однако поскольку двумерный массив – это массив, элементами которого являются массивы, то получаем, что *matrix – это массив из десяти элементов, обратиться к которому по-другому можно так: matrix[0]. По нашему соглашению – это первая строка матрицы.

Теперь, рассматривая этот одномерный массив, можно также заметить, что и его имя является указателем на его первый элемент, поэтому записи matrix[0][0], *matrix[0], (*matrix)[0]) и **matrix, эквивалентны и представляют собой обращение к элементу матрицы, имеющему индексы (0,0).

Продолжим рассуждения с целью понимания, как обратиться к элементу с произвольными индексами (i,j). По нашему соглашению – это элемент, расположенный в строке с индексом i и в столбце с индексом j. Стандартный способ, который был изучен в теме, посвященной массивам, – это matrix[i][j]. Взяв строку по индексу и указатель на элемент в ней, получим запись *(matrix[i]+j). Указатель на строку и индекс столбца даст (*(matrix+i))[j], а при обращении только указателями – *(*(matrix+i)+j).

#define N_ROWS 20

#define N_COLS 10

float matrix[N_ROWS][N_COLS];

void initArray() {

for (int i=0; i<N_ROWS; i++) {

for (int j=0; j<N_COLS; j++) {

*(*(matrix+i)+j) = 100*i + j;

}

}

}

void printArray() {

for (int i=0; i<N_ROWS; i++) {

for (int j=0; j<N_COLS; j++) {

printf("%7.1f", *(*(matrix+i)+j));

}

printf("\n");

}

}

int main() {

initArray();

printArray();

return 0;

}

Обработка матрицы при помощи указателей

Рассмотрим следующую задачу. Требуется написать функцию, которая принимает два аргумента: указатель на квадратную матрицу и ее размер. Функция должна вычислить сумму элементов, расположенных на побочной диагонали.

Указатели на функции

Рассмотрим функцию, которая вычисляет сумму элементов массива:

Эта функция принимает массив в качестве аргумента и, передавая в нее разные массивы, мы можем вычислить для них сумму. Массив в данном случае является переменной, а функция суммирования – постоянная. Рассмотрим теперь ситуацию с точностью до наоборот – массив является постоянным, а функция, которая вычисляется от каждого элемента – переменной. Задача заключается в следующем: для одного массива нужно вычислить

Сумму элементов (сумму первых степеней),

Сумму квадратов элементов (сумму вторых степеней)

Сумму кубов элементов (сумму третьих степеней).

int result = 0;

for (int i=0; i<N; i++) {

result += f(numbers[i]);

}

#define N 7

int numbers[N] = {1,2,3,4,5,6,7};

int calculate(int (*operation)(int)) {

int result = 0;

for (int i=0; i<N; i++) {

result += (*operation)(numbers[i]);

}

return result;

}

int linear(int x) {

return x;

}

int square(int x) {

return x*x;

}

int cube(int x) {

return x*x*x;

}

cout << calculate(linear) << endl;

cout << calculate(square) << endl;

cout << calculate(cube) << endl;

Рассмотрим функцию, которая принимает два аргумента и возвращает их сумму:

int getSum(int a, int b) {

return a+b;

}

В этой функции аргументы a и b являются переменными, а операция суммы – постоянная, другими словами, передавая различные аргументы, мы всегда вычисляем именно сумму. Теперь попробуем поменять их местами – зафиксируем значения a и b, а менять будем операцию. Например, если взять a=10 и b=5, то получив аргумент «сложение», функция вернет 15; получив аргумент «умножение», функция вернет 50; аргумент «деление» даст результат 2; аргумент «вычитание» приведет к результату 5. Вопрос заключается в том, как передать в функцию не переменную, а операцию. Сделать это можно при помощи указателей на функции. Давайте определим значения a и b как константы:

const int a = 10;

const int b = 5;

затем реализуем четыре функции, которые отвечают за операции сложения, деления, умножения и вычитания:

int summarize(int x, int y) {

return x+y;

}

int multiply(int x, int y) {

return x*y;

}

int divide(int x, int y) {

return x/y;

}

int subtract(int x, int y) {

return x-y;

}

Пока все понятно, и нет ничего нового. Теперь реализуем функцию, которая принимает один аргумент – операцию. В нашем примере операция – это одна из четырех функций:

int getResult(int (*operation)(int,int)) {

return (*operation)(A,B);

}

Для вызова этой функции нужно передать название функции, которое является указателем на функцию (аналогично массивам), и функция вернет нам результат этой операции над числами 10 и 5:

printf("Сумма=%d\n", getResult(summarize));

printf("Произведение=%d\n",getResult(multiply));

printf("Частное=%d\n", getResult(divide));

printf("Разность=%d\n", getResult(subtract));

Рассмотрим следующую задачу. Требуется реализовать меню, содержащее несколько пунктов:

  1. вычислить сумму элементов массива;

  2. вычислить сумму квадратов элементов массива;

  3. вычислить сумму кубов элементов массива;