Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебно-практическое пособие ПРОГ.doc
Скачиваний:
38
Добавлен:
20.11.2019
Размер:
5.63 Mб
Скачать

3.5.5.Матрицы и многомерные массивы

Матрицу можно рассматривать как массив элементов типа массив. Например, переменная a представляет матрицу размера 3×3 с вещественными элементами:

double a[3][3];

Для обращения к элементу матрицы надо записать его индексы в квадратных скобках, например, выражение a[i][j] представляет собой элемент матрицы a в строке с индексом i и столбце с индексом j. Элемент матрицы можно использовать в любом выражении как обычную переменную.

Элементы матрицы располагаются в памяти последовательно по строкам. Например, в рассматриваемой матрице сначала идут элементы строки с индексом 0, затем строки с индексом 1, в конце строки с индексом 2. Т.е. элементы матрицы располагаются следующим образом: a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[2][2], a[2][0], a[2][1], a[2][2].

Имя матрицы, как и имя массива, это указатель на первый элемент. Например, запись a эквивалентна &a[0][0], запись a+1 эквивалентна &a[0][1] и т.п.

При описании матрицы можно выполнить инициализацию ее элементов:

double a[3][3]={ {10.3, 1.1, 2.3},

{5.2, 6.7, 3.1},

{0.9, 2.3, 9.7}};

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

Реализация матриц, размер которых становится известным на стадии выполнения программы, будет рассмотрен в теме 5.

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

Трехмерный массив описывается следующим образом:

int a3[10][20][30];

Можно представить данный трехмерный массив в виде массива из десяти элементов. Каждый элемент является двумерным массивом размера 20 на 30.

3.6.Пользовательские функции

3.6.1.Определение функций

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

<тип возвращаемого значения> <имя функции> (<Список формальных параметров>)

Список формальных параметров позволяет описать параметры, передаваемые функции с указанием их типа. Синтаксис данного списка следующий:

<тип параметра 1><идентификатор параметра 1>,<тип параметра 2><идентификатор параметра 2> и т.д.

При вызове функции ей передаются значения фактических параметров. Фактические параметры должны точно соответствовать типу формальных параметров.

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

void f(int x) {

x = 0; // Изменение формального параметра не приводит к

// изменению фактического параметра в вызывающей программе

}

int main() {

int x = 5;

f(x);

// Значение x по-прежнему равно 5

. . .

}

Здесь в функции main вызывается функция f, которой передается значение переменной x, равное пяти. Несмотря на то, что в теле функции f формальному параметру x присваивается значение 0, значение переменной x в функции main не меняется.

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

void f(int *x) {

*x = 0;

}

int main() {

int x = 5;

f(&x);

// Значение x равно 0

. . .

}

Напомним, что в функцию scanf() требуется передавать адрес переменной, значение которой вводится с помощью этой функции.

Если функция должна возвращать некоторое значение, то следует использовать оператор return <возвращаемое значение>. Рассмотрим пример функции, вычисляющей сумму элементов массива состоящего из n элементов.

#define N 5

int a[N]={1,2,3,4,5}

int sum_array(int *x, int n) {

int i,s=0;

for(i=0;i<n;i++) s+=x[i];

return s;

}

int main() {

printf("Сумма элементов массива a=%d",sum_array(a,N));

}

Напомним, что имя массива это указатель на этот массив (указатель на первый элемент массива). Поэтому если в качестве аргумента функции используется имя массива, то функции передается указатель на этот массив. Затем функция использует этот указатель для выполнения изменений в переданном массиве.

В рассмотренном примере заголовок функции производящей суммирование элементов массива был определен следующим образом:

int sum_array(int *x, int n)

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

int sum_array(int x[], int n).

Записи int *x и int x[] эквивалентны.