Указатели и двумерные массивы
Двумерные массивы в языке С++ устроены значительно сложнее одномерных. И если одномерный массив – это область памяти с последовательно идущими элементами, то двумерный массив – это массив одномерных массивов.
Двумерные массивы в языке C++ – это массивы массивов, т.е. массивы, элементами которых, в свою очередь, являются одномерные массивы.
Для работы с двумерными массивамичасто применяются массивы указателей и указатели на указатели.
Массивы указателей
Как и любые другие переменные, указатели могут быть объединены в массивы. Массив указателей фиксированных размеров может быть задан следующим образом:
тип * имя_массива[размер];
Например, массив указателей на данные типа int объявляется следующим образом:
int * p[10];
Здесь каждый элемент массива p содержит указатель на целочисленное значение, т.е. элементы этого массива могут содержать только значения, которые представляют собой адреса переменных, массивов типа int.
По аналогии с обычными указателями, i-ый элемент объявленного таким образом массива указателей p[i] можно проинициализировать, например, одним из следующих способов:
· с помощью адреса переменной: int x; p[i] = &x;
· с помощью объявленного указателя: int * q = &x; p[i] = q;
· с помощью адреса массива: int a[5]; p[i] = a;
Указатели на указатели
В С++ можно создавать указатели на другие указатели, которые, в свою очередь, содержат адреса реальных переменных, т.е. можно создавать указатели на указатели.
Чтобы объявить в программе указатель, который будет хранить адрес другого указателя, нужно просто удвоить число звёздочек в объявлении:
тип ** имя_указателя;
Например: int ** p;
Объявленный таким образом указатель p может содержать адрес указателя на переменную типа int. Адрес указателя может быть получен с помощью унарной операции адреса (&). Например:
int x = 10;
int *p, **q;
p = &x; q = &p;
cout<<x<<" "<<*p<<" "<<**q<<endl; // 10 10 10
После выполнения этих операторов указатель qбудет содержать адрес указателя p, содержащего адрес переменной x со значением 10.
Указатель на указатель – это переменная, содержащая адрес другого указателя.
Язык С++ позволяет объявить указатель на указатель на указатель и так далее. Для этого при объявлении перед указателем следует поставить нужное количество звездочек.
Массивы указателей и двумерные массивы
При объявлении двумерных массивов,например, при выполнении объявления int matr[4][3]; происходит следующее:
· создаётся указатель matr, который определяет в памяти местоположение первого элемента массива (с индексами [0][0]) и, кроме того, является указателем на массив из четырех указателей matr[4];
· каждый из этих четырех указателей matr[i]содержит адрес одномерного массива, представляющего собой i-строку двумерного массива и состоящего из трёх элементов типа int;
· каждый указатель matr[i]позволяет обратиться к соответствующей i-ой строке матрицы.
Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме
matr[i] или эквивалентного ему *(matr+i).
Для доступа к элементам двумерного массива matr могут быть использовано индексное выражение в форме
matr[i][j]
или эквивалентных ему
*(matr[i]+j) и *(*(matr+i)+j)
Следует учитывать, что с точки зрения синтаксиса языка C++ указатель matr и указатели matr[0], matr[1], matr[2],matr[3] являются константами, и их значения нельзя изменять во время выполнения программы. Поэтому, например, переставить местами строки матрицы с помощью указателей matr[i]мы не сможем. Но сможем, например, передавать строки матрицы в функцию, используя массив указателей matr[4],что и продемонстрируем в следующем примере.
// Пример 8.5. В данной целочисленной матрице matr[n][m] найти
// сумму элементов в каждой строке, используя функцию нахождения
// суммы элементов в одномерном массиве.
#include <iostream>
using namespace std;
const int DIM1 = 20, DIM2 = 20;
int Summa(int *ar, int size){
int sum = 0;
for(int i = 0; i < size; i++)
sum = sum + ar[i];
return sum;
}
int main(){
int matr[DIM1][DIM2], s[DIM1];
int n, m, i, j;
cout<<"Vvedi n, m: "; cin>>n>>m;
srand(n+m);
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
matr[i][j] = rand() % 25 - 10;
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
cout.width(4); cout<<matr[i][j];
}
cout<<endl;
}
cout<<"\t\tSum elementov strok== "<<endl;
for(i = 0; i < n; i++)
s[i] = Summa(matr[i], m); // вызов функции Summa()
for(i = 0; i < n; i++)
cout<<'\t'<<s[i];
cout<<endl;
system("pause");
}
Если же мы хотим использовать массив указателей для перестановки строк матрицы matr, то следует вначале создать массив указателей p следующим образом:
…
int * p[4];
for(int i = 0; i < 4; i++)
p[i] = matr[i];
…
И затем для перестановки элементов строк матрицы достаточно поменять местами указатели на строки в массиве указателей p.
Доступ же к элементам двумерного массива может осуществляться как с помощью индексации его имени (как показано выше), так и с помощью указателей:
p[i][j] *(p[i] + j) *(*(p + i) +j)
// Пример 8.6. В данной целочисленной матрице a[n][m] переставить
// местами 1 и 2 строки, используя массив указателей на строки.
#include <iostream>
using namespace std;
const int DIM1 = 20, DIM2 = 20;
int main(){
int a[DIM1][DIM2];
int * p[DIM1]; // массив указателей p
int n, m;
cout<<"Vvedi n, m: "; cin>>n>>m;
srand(n+m);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
a[i][j] = rand() % 25 - 10;
for(int i = 0; i < n; i++) // инициализация массива указателей
p[i] = a[i]; // или p[i] = &a[i][0]; или p[i] = (int*)&a[i];
cout<<"Matrix isxodnaya=="<<endl;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cout.width(5);
cout<<p[i][j];
}
cout<<endl;
}
int * x;
x = p[0]; p[0] = p[1]; p[1] = x; // перестановка 1 и 2строк
/* x=a[0];
a[0]=a[1]; // ошибка!!!! Имя одном. массива – const-указатель.
a[1]= x;
*/
cout<<endl<<"Matrix posle perestanovki== "<<endl;
for(int i =0;i < n; i++){
for(int j = 0; j < m; j++){
cout.width(5);
cout<<*(p[i] + j);
}
cout<<endl;
}
cout<<endl<<"Matrix isxodnaya== "<<endl;
for(int i = 0;i < n; i++){
for(int j = 0; j < m; j++){
cout.width(5);
cout<<a[i][j];
}
cout<<endl;
}
system("pause");
}
Дата добавления: 2022-05-27; просмотров: 60;