Автор: Пользователь скрыл имя, 17 Января 2011 в 18:57, курс лекций
6 тем.
for ( int i =0; i <10; ++ i )
a [ i ]= new int [5];
В этом случае мы получим двумерный массив целых чисел, который содержит 10 строк и 5 столбцов. В общем случае вместо констант 10 и 5можно поставить переменные и тогда получим массив необходимой размерности для данной задачи. Кроме того, для каждого значения i мы можем создавать одномерные массивы различной размерности. В результате у нас получится не прямоугольный массив, а свободный (количество элементов в каждой строке различно).
Обратиться к элементам динамического массива можно с помощью индексации, например, a[i][ j ] , или с помощью указателей *(*(a+i)+ j ) .
Рассмотрим более
подробно второе выражение. Указатель а хранит
адрес указателя на нулевую строку. Операция a+i обратится
к указателю на i-тую строку массива. Выражение *(a+i) позволит
обратиться к значению, хранящемуся по
адресу a+i – фактически к адресу нулевого
столбца i-той строки двумерного массива.
И, соответственно, выражение *(*(a+i)+ j ) позвол
Оба выражения эквивалентны друг другу, однако первое более понятно, а второе более быстродейственно при выполнении программы, потомучто компилятор всегда переводит индексный способ обращения к массиву к обращению через указатели.
Ввод и вывод массивов также как и в случае со статическими массивами производится поэлементно. В следующем фрагменте программы производится потоковой ввод и вывод целочисленного массива,который содержит 4 строки и 5 столбцов:
int **b=new int *[4]; //объявили двумерный динамический массив
for (int i=0; i<2; ++i) b[i]=new int [5];
for (int i=0;i<4; ++i) // ввод элементов массива
for (int j=0;j<5; ++j)
{
cout <<" b ["<< i <<"]["<< j <<"]=";
cin >>*(*( b + i )+j);//введенное значение записываем в b [i][ j ]
}
…
for (int i=0;i<4; ++i, cout<<endl) // вывод
for (int j=0;j<5; ++j)
cout<<"b["<<i<<"]["<<j<<"]="<<
Освободить память,
выделенную под динамический массив
можно с помощью операции delet
//освобождаем память, выделенную под i -тую строку двумерного массива
for (int i=0;i<4; ++i) delete[] b[i];
delete [] b ; // освобождаем память, выделенную под массив указателей.
Замечание. Данный
фрагмент программы освобождает память,
выделенную в куче под двумерный массив,
сам указатель b при этом сохраняется и
может повторно использоваться для определения
другого массива.
Передача
двумерных массивов
в качестве параметров
При использовании в качестве параметра двумерного массива в функцию передается указатель на элемент, стоящий в нулевой строке и нулевом столбце. Этим указателем является имя массива. Также как и в случае с одномерными массивами операцию разадресации внутри функции при обращении к элементам массива выполнять не надо, т.к. запись вида a[i][ j ] автоматически заменяется компилятором на выражение *(*(a+i)+ j ).
При передаче двумерного массива в качестве параметра функции информация о количестве строк и столбцов теряется, поэтому размерности массива следует передавать в качестве отдельных параметров. Рассмотрим несколько примеров:
1. Передача статического массива:
#include <iostream>
using namespace std;
/*в функцию в качестве параметров передаются статический массив mas и его размерности: n – количество строк, m- количество столбцов*/
void print (int mas[3][2], int n, int m)
{
for (int i=0; i<n; ++i, cout<<endl)
for (int j=0; j<m; ++j)
cout<<mas[i][j]<<"\t";
}
int main()
{
int a[3][2]={{1, -2}, {-3, 4}, {-5,6} };
print(a,3,2); cout<<endl;
print (a, 2,2)
return 0;
}
Результат работы программы:
1 -2
-3 4
-5 6
1 -2
-3 4
Замечание. При втором вызове функции print в качестве параметра n мы передали значение меньше реального количества строк в массиве,поэтому мы смогли распечатать не весь массив, а его часть. Подумайте, что произойдет, если в качестве n или m передать значение большее реальной размерности массива.
2. Передача динамического массива:
#include <iostream>
using namespace std;
/*в функцию в качестве параметров передаются динамический массив mas и его размерности: n – количество строк, m- количество столбцов*/
void print (int **mas, int n,int m)
{
for (int i=0; i<n; ++i, cout<<endl)
for (int j=0; j<m; ++j)
cout<<mas[i][j]<<"\t";
}
int main()
{
int n=3, m=4;
int **a=new int *[n];
for (int i=0; i<n; ++i)
a[i]=new int [m];
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j)
a[i][j]=i+j;
print(a,3,4);
for (int i=0;i<n; ++ i)
delete [] a[i]; // освобождение памяти
delete [] a;
return 0;
}
Результат работы программы:
0 1 2 3
1 2 3 4
2 3 4 5
Поскольку массив всегда передается в функцию поадресу, то все изменения, внесенные в формальный параметр массив, отразятся на фактическом параметре массиве. Если необходимо запретить изменение массива в функции, то его нужно передавать как параметр константу. Например:
int sum ( const int ** mas , const int n )
{ … }
Напомним, что двумерный
массив – это одномерный массив
указателей, каждый из который в
свою очередь ссылается на одномерный
массив.Поэтому двумерный
#include <iostream>
using namespace std;
/*в функцию в качестве параметров передаются одномерный массив mas и его размерность n */
void print (int *mas, int n)
{
for (int i=0; i<n; ++i)
cout<<mas[i]<<"\t";
cout<<endl;
}
int main()
{
int n=3, m=4;
int **a=new int *[n];
for (int i=0; i<n; ++i)
a[i]=new int [m];
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j) a[i][j]=i+j;
for ( int i =0; i < n ; ++ i ) // обработка двумерного массива построчно: в качестве аргумента
print ( a[i], m ); / функции print передаем указатель на i-тую строку
for (int i=0;i<n; ++ i)
delete [] a[i]; // освобождение памяти
delete [] a ;
return 0;
}
Замечание. Результат
работы программы будет соответствовать
предыдущему примеру.
Двумерный
массив как возвращаемое
значение функции
Двумерный массив может возвращаться в качестве значения функции только как указатель:
#include <iostream>
using namespace std;
int ** create(int n, int m);
{
int **mas=new int *[n];
for (int i=0; i<n; ++i)
mas[i]=new int [m];
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j)
mas[i][j]=i+j;
return mas;
}
int main()
{
int n=5, m=5; int **a=create(n,m);
print(a,n,m);
for (int i=0;i<n; ++ i)
delete [] a[i]; // освобождение памяти
delete [] a;
return 0;
}
Результат работы программы:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
6.6. Примеры использования двумерных массивов
Двумерные массивы
находят свое применение тогда, когда
исходные данные представлены в виде
таблицы, или когда для хранения
данных удобно использовать табличное
представление. В данном разделе мы рассмотрим
примеры использования двумерных массивов.
При решении задач мы будем использовать
динамические массивы, но обращаться к
элементам через индексы.Однако вы можете
обращаться к элементам массива и через
указатели. Для этого нужно будет заменить
выражение a[i][ j ] на *(*(a+
1. Дана прямоугольная
матрица, элементами которой
Указания по решению задачи. Массив результатов будет одномерный, а его размерность будет совпадать с количеством столбцов исходной матрицы.
#include <iostream>
using namespace std;
int ** create(int &n, int &m)
{
cout <<"n="; cin >>n; cout <<"m=";cin >>m;
int **mas=new int *[n];
for (int i=0; i<n; ++i)
mas[i]=new int [m];
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j)
{
cout<<"mas["<<i<<"]["<<j<<"]="
cin>>mas[i][j];
}
return mas;
}
int main()
{
int n, m;
int **a=create(n,m);
float * b = new float [ m ]; //создание массива результатов
for ( int j =0; j < m ; ++ j ) // для каждого j -го столбца
{
b [ j ]=0;
int k =0; //обнуляем сумму и количество нечетных элементов столбца
for ( int i =0; i < n ; i ++) // перебираем все элементы j-того столбца и находим
if ( a [ i ][ j ]%2)
{
b [ j ]+= a [ i ][ j ];//сумму
k ++; //и количество нечетных элементов
}
if ( k ) //если количество нечетных элементов положительное, то
b [ j ]/= k ; //то вычисляем среднее арифметическое
}
for ( int i =0; i < m ; i ++) //вывод массива результатов
cout<<b[i]<<"\t";
for (int i=0;i<n; i++)
delete [] a[i];//удаление массива а
delete [] a;
delete [] b; //удаление массива b
return 0;
}
Результат работы программы
n=2
m=3
Массив Аn´m | Ответ |
2 1 3
4 3 6 |
Вывод результата:0.002.003.00 |