Урок 9.4.6. Массивы в качестве аргументов
9.4.3. Массивы в качестве аргументов
При описании формальных параметров границы одномерных массивов можно опускать. Например,
int lengthfw(char buffer[], int size) { int i=0; while (i<size&&(buffer[i]!=' ')) { i++; } return(i); } |
Функция lengthfw считает длину последовательности символов до первого пробела. При вызове функции для самого параметра-массива память не отводится, передаваемым значением является указатель на первый элемент массива. Правильный вызов для функции length: length(array, n);
Если функции нужно передавать двумерный массив, то описание аргумента в этой функции должно обязательно включать в себя размер строки массива, а размер столбцов не важен, т.к. массив передается с помощью ссылки (указателя). Например,
void print_m(int a[][3], int n, int m);
Такое описание сообщает компилятору, что массив следует разбить на строки по три столбца, дополнительно передаются размерности массива.
Рассмотрим пример программы в которой вызывается функция print_m и её вариант функция print_s . Ей передается матрица и количество строк и столбцов на усмотрение программиста.
#include <conio.h> #include <stdio.h> #include <iostream.h> void main() { void print_m(int a[][3], int n, int m); void print_s(int(*a)[3], int n, int m); int a[4][3]={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, }; //во всех вызовах функции print_m ей передается //матрица a[4][3] print_m(a,4,3); print_m(a,2,2); print_m(a,5,4); //в данном случае функция выйдет // за пределы матрицы print_s(a,4,3); getch(); }//End of main /*функция print_m – вывод элементов массива * параметры: * a – двумерный массив со строками из трех чисел * n – количество строк * m – количество столбцов. * можно указать и такой заголовок функции: * void print_m(int a[4][3], int n, int m) * первая размерность значения не имеет */ void print_m(int a[][3], int n, int m) { printf("Matrix\n"); for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) cout << a[i][j] << " "; cout << endl; } } //End of print_m /*функция print_s – вывод элементов массива * параметры: * а - указатель на массив из 3 целых чисел * n – количество строк * m – количество столбцов. */ void print_s(int (*a)[3], int n, int m){ printf("Matrix\n"); for(int i = 0; i<n; i++) { for(int j=0; j<m; j++) cout << a[i][j]<< " "; cout << endl; } //другой вариант того же самого printf("Matrix thru pointer\n"); for(int i = 0; i<n; i++) { for(int j=0; j<m; j++) cout << *(a[i]+j)<< " "; cout << endl; } }//end of print_s |
Если в заголовке функции объявить размерность другую, чем у передаваемого массива, например:
void print_m(int a[][13],int n, int m);
то получим сообщение, говорящее о несоответствии формального и фактического параметров:
Cannot convert 'int ( *)[3]' to 'int ( *)[13]'
Type mismatch in parameter 'a' in call to 'print_m (int(*) [13], int)'
Напоминаем, что количество строк может варьировать.
Как написать функцию, обрабатывающую двумерный массив с заранее не определенной длиной строки? В следующем примере рассмотрим фукции nummax1 и nummax2 , которые ищут максимальное число в любом двумерном массиве.
Фунции nummax1 передается указатель на первую строку массива (указатель на данные типа int) и далее функция работает с одномерным массивом. В этом случае все элементы массива должны располагаться в памяти друг за другом, из-за этого функция не сможет обработать динамический двумерный массив.
Фунции nummax2 передается указатель на на указатель на данные типа int, т.е. указатели на строки массива, поэтому для передачи массива в функцию формируется вспомогательный массив x. Эта функция может обработать как динамический, так и статический массив. Сформировать вспомогательный массив можно и в цикле. Делать это в этом примере мы не будем, но рассмотрим этот способ далее.
#include <stdio.h> #include <conio.h> #include <iostream.h> #include <iomanip.h> int nummax1(int *a, int n, int m); int nummax2(int **a, int n, int m); //int nummax2(int *a[], int n, int m); //как вариант объявления void main(){ int c[3][3]={ {-2, -54, 609}, {-4, 555, -89}, {14, 1, 657} }; /* Массив можно объявить и так: int c[][3]={ {-2, -54, 609}, {-4, 555, -89}, {14, 1, 657} }; */ //создадим x – статический массив указателей на строки, чтобы //в функции можно было работать с двумерным массивом int* x[] = {c[0], c[1], c[2]}; int n = 3, m =3; clrscr(); cout<<"Matrix: "<<endl; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++) cout << setw(4) << c[i][j]; //(*(*(i+i)+j))) cout<<endl; } cout << endl << "max number: " << nummax1(c[0], n, m) << endl; cout << endl << "max number: " << nummax2(x, n, m) << endl; getchar(); } int nummax1(int *a, int n, int m){ // обрабатывается как одномерный массив, работает только // для статического массива int max; max = a[0]; //ili tak max = *a; for(int i = 0; i < n*m; i++) if( max < a[i]) max = a[i]; // фрагмент аналогичный предыдущему for(int i = 0; i < n*m; i++) if( max < *(a+i)) max = *(a+i); return max; }//end of nummax1 int nummax2(int **a, int n, int m){//a ¬– массив n на m int max; max = a[0][0]; //можно и так: max = **a; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if( max < a[i][j]) max = a[i][j]; return max; }//end of nummax2 |
Рассмотрим пример, в котором функцией createArray создается динамический массив, указатель на который возвращается в основную программу и передается затем в функцию randmass(), которая инициализирует его случайными значениями при помощи стандартной функции rand. Функция printArray выводит массив на экран.
Прочитать как инициализируются указатели и массивы можно в разделах 7.1.5. Инициализация указателей и 7.2.2. Инициализация массивов, там же есть и примеры освобождения памяти, занимаемой указателями и массивами.
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <iostream> #include <iomanip> using namespace std; void randmass(int **, int, int); int nummax(int **, int, int ); int ** createArray(int n, int m);//создать двумерный массив void printArray(int **, int n, int m);//печать массива void freeArray(int **, int n);//освободить память,занимаемую массивом, n - количество строк void main(){ int **matrix; int n = 5; // число строк int m = 4; // число столбцов //создаем динамический массив размерности n на m matrix = createArray(n,m); //инициализация массива в функции randmass(matrix, n, m); //вывод массива на экран printArray(matrix, n, m); //освободить память занимаемую массивом из n строк freeArray(matrix, n); getchar(); } //функция создания массива int ** createArray(int n, int m) { //динамический массив с заранее не определенной размерностью int **a = new int* [n]; for (int i = 0; i < n; i++) a[i]= new int[m]; return a; //возвращаем указательна на массив } //функция инициализации массива void randmass(int ** a, int rows, int cols) { for (int i=0; i<rows; i++){ for (int j=0; j<cols; j++){ a[i][j] = rand() %100 - 5; //stdlib.h } } } //функция вывода массива void printArray(int **a, int n, int m) { cout<<"Matrix: "<<endl; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++) cout << setw(4) << a[i][j]; cout<<endl; } } //функция освобождения памяти, занимаемой массивом void freeArray(int **a, int n) { for(int i = 0; i < n; i++) delete [] a[i];//вначале освободим память, отведённую собственно под матрицу delete [] a;//теперь освобождаем память, занятую массивом указателей } |
Оставить комментарий