К элементам двухмерных массивов
Рассмотрим объявление и связь указателей и элементов двухмерных массивов. Двухмерный массив в языке С++ рассматривается как совокупность одномерных массивов (его строк), а строка – совокупность элементов одномерного массива.
Объявление двухмерного массива с явным указанием количества элементов массива:
< тип_элементов_массива> < имя_массива> [< кол–во_строк> ][< кол–во_столбцов> ];
Для обращения к элементам двухмерного массива используется два индекса (индексных выражений):
< имя_массива> [< выражение1> ][< выражение2> ];
Индексные выражения вычисляются слева направо, полученные значения применяется после вычисления последнего индексного выражения. Элементы массивов располагаются в ОП таким образом, что быстрее изменяются самые правые индексы, т.е. элементы одномерного массива располагаются подряд, а двухмерного – по строкам.
Пример объявления двухмерного массива значений типа:
int a[m][n];
Этот массив состоит из m одномерных массивов (строк), каждый из которых содержит n элементов (столбцов). При работе с этим двухмерным массивом можно использовать одно или два индекса (индексных выражения), например, а[i][j] содержит 2 индекса. Такая запись используется для обращения к элементу, расположенному на пересечении i-й строки и j-го столбца массива. Для получения значения этого элемента вначале вычисляются индексные выражения, затем определяется адрес элемента массива в ОП и извлекается его значение.
a[i] содержит один индекс: подобная запись определяет адрес одномерного массива, т.е адрес начала i-й строки массива.
Имя массива а не содержит индекса и определяет адрес массива, т.е. адрес его нулевого элемента.
Таким образом, обращение к двухмерным массивам с помощью имени и только одного индекса определяет указатель на начало соответствующей строки массива (адрес ее нулевого элемента). Напомним, что в одномерном массиве адрес i-го элемента массива & a[i] формируется в виде а + i*sizeof(int). Используя это, определим соотношения:
a[0] & а[0][0] a + 0*n*sizeof(int);
a[1] & а[1][0] а + 1*n*sizeof(int);
a[i] & а[i][0] а + i*n*sizeof(int);
Обращение к элементам многомерного массива более детально рассмотрим на примере двухмерного массива:
int a[3][4]; //а – указатель-константа
int *р=& а[0][0]; // р – указатель-переменная
После этого указатель р можно использовать вместо указателя а для обращения к строкам или элементам массива. В ОП элементы массива а располагаются таким образом, что быстрее всех изменяется самый правый индекс, т.е. в последовательности: a[0][0] а[0][1] а[0][2] а[0][3] а[1][0]... а[2][0] а[2][1] а[2][2] а[2][3]
При этом для обращения к массиву а можно использовать имена:
& а а & а[0][0] *а – адрес элемента 0-й строки и 0-го столбца массива а;
*(& а[0][0]) а[0][0] – значение элемента 0-й строки 0-го столбца массива а;
a[i] (а+i) *(а+i) & a[i][0] – адрес начала i-й строки, т.е. адрес элемента i-й строки и 0-го столбца;
*a[i] *(& a[i][0]) a[i][0] – значение 0-го элемента i-й строки;
a[i][j] *(*(a+i)+j) *(a[i]+j) a[i][j] – значение элемента i-й строки j-го столбца массива а;
где (а+i) *(a+i) a[i] – адрес 0-го элемента i-й строки, т.е. & a[i][0];
(*(a+i)+j) – адрес j-го элемента i-й строки, т.е. & a[i][j];
*(*(a+i)+j) – значение j-го элемента i-й строки, т.е. a[i][j].
Значение адреса начала i-й строки (адреса 0-го элемента i-й строки) на машинном уровне формируется в виде:
a[i] а+i (a+i*n*sizeof(int))
где n — количество элементов в одной строке. Таким образом, адрес (i+1)-й строки смещен относительно i-й строки на (n*sizeof(int)) байт, т.е. на одну строку массива. Выражение a[i][j] компилятор С++ переводит в эквивалентное выражение *(*(а+i)+j).
К элементам двухмерного массива можно обратиться и с помощью скалярного указателя на массив.
Например, после объявления:
int a[m][n], *р = & а[0][0]; *(р+i*n+j) // значение j-го элемента в i-й строке;
где n – количество элементов в строке; i*n+j – смещение элемента a[i][j] относительно начала массива а.
Пример 1. Дан одномерный динамический массив. Вычислить среднее арифметическое модулей элементов массива.
Ход выполнения работы
1. Алгоритмы решения задач с использованием динамических массивов схожи с алгоритмами, использующими статические массивы.
2. Написать программу, соответствующую алгоритму:
| Алгоритм
| Программа
| | объявление вещ: *а, sum; цел: i, n
// ввод количества элементов массива
ввод n
выделить динамическую память под указатель a
// ввод элементов массива
для i=0 до n-1 шаг 1
ввод ai
все для i
//сначала сумма элементов равна нулю
sum=0
для i=0 до n-1 шаг 1
// в цикле изменяется номер i
// элемента массива
// нужный элемент добавляется к
// сумме
sum=sum+ai
все_для i
// находим среднее арифметическое
sum=sum/n
// печатаем полученное значение
печать sum
// вывод массива на экран
для i=0 до n-1 шаг 1
вывод ai
все_для i
освободить выделенную под указатель a динамическую память
| #include " stdio.h"
#include " stdlib.h"
int main ()
{
float *а, sum;
int i, n;
// ввод n
printf (" n=");
scanf (" %i", & n);
a=(float*)malloc(n*sizeof(float));
//ввод одномерного динамического //массива с клавиатуры
for (i=0; i< =n-1; i++)
{
printf(“a%i=”, i);
scanf(“%f”, a+i);
}
// сначала сумма элементов равна нулю
sum=0;
// вычисление суммы элементов
for (i=0; i< =n-1; i++)
sum=sum+*(a+i);
// находим среднее арифметическое
sum=sum/n;
// печатаем полученное значение
printf(" sred_arif=%f\n", sum);
// вывод одномерного динамического
// массива на экран
for (i=0; i< =n-1; i++)
printf (" %.3f ", *(а+i));
printf(" \n");
free(a);
return 1;
}
| Примечание. Для выделения динамической памяти под массив из n элементов использовалась библиотечная функция malloc():
Для ввода элементов массива как обычно использовалась функция scanf(). Вторым аргументов этой функции является адрес переменной, которая получает вводимое значение. В данном примере это адрес i-го элемента динамического массива a+i. При вычислении суммы значение i-го элемента получали с помощью записи
Вывод элементов массива осуществляется при помощи функции printf(), где для вывода элементов применялась та же форма записи.
3. Создать проект и реализовать данную задачу в среде Visual C++ 6.0.
Пример 2. Сформировать двухмерный динамический массив по закону .
Ход выполнения работы
1. Алгоритмы решения задач с использованием динамических массивов схожи с алгоритмами, использующими статические массивы.
2. Написать программу, соответствующую алгоритму:
| Алгоритм
| Программа
| | объявление вещ: *а; цел: i, n
// ввод количества строк массива
ввод n
// ввод количества столбцов массива
ввод m
выделить динамическую память под указатель a
// формирование массива построчно
для i=0 до n-1 шаг 1
для j=0 до m-1 шаг 1
aij=i+j
все для j
все для i
// вывод массива построчно
для i=0 до n-1 шаг 1
для j=0 до m-1 шаг 1
вывод aij
все для j
все_для i
освободить выделенную под указатель a динамическую память
| #include " stdio.h"
#include " stdlib.h"
int main ()
{
int *a;
int i, j, m, n;
//ввод n
printf (" n=");
scanf (" %i", & n);
//ввод m
printf (" m=");
scanf (" %i", & m);
//выделение динамической памяти под
//целочисленный массив из n строк и
//m столбцов
a=(int*)malloc(n*m*sizeof(int));
//формирование динамического массива
//построчно
for (i=0; i< =n-1; i++)
for (j=0; j< =m-1; j++)
{
*(a+i*m+j)=i+j;
}
//вывод динамического массива //построчно
for (i=0; i< =n-1; i++)
{
for (j=0; j< =m-1; j++)
printf (" %i ", *(a+i*m+j));
printf(" \n");
}
//освобождение выделенной
// динамической памяти
free(a);
return 1;
}
| 3. Создать проект и реализовать данную задачу в среде Visual C++ 6.0.
Пример 3. Дан двухмерный динамический массив размера . Сформировать одномерный динамический массив, каждый элемент которого – произведение нечетных элементов соответствующего столбца двухмерного массива. Указать номер столбца с наименьшим произведением элементов.
Ход выполнения работы
1. Решение этой задачи было подробно рассмотрено в разделе «Двухмерные массивы».
2. Написать программу, соответствующую алгоритму:
| Алгоритм
| Программа
| | объявление вещ: *а, p, *b, цел: i, j, pmin, n, m
// ввод количества строк массива
ввод n
// ввод количества столбцов массива
ввод m
выделить динамическую память под указатель a
выделить динамическую память под указатель b
// ввод массива построчно
для i=0 до 6-1 шаг 1
// в цикле изменяется номер i строки
// массива
для j=0 до 4-1 шаг 1
// в цикле изменяется номер
// столбца массива j
// затем элемент вводится
ввод аij
все_для j
все_для i
// вычисление произведений
для j=0 до 4-1 шаг 1
// в цикле изменяется номер j столбца
// массива
//находим произведение j-го столбца
p=1
для i=0 до 6-1 шаг 1
// в цикле изменяется номер строки
// массива i
// находим нечетный элемент
если остаток от дел aij на 2 =1
//изменяем произведение
p=p*aij
все_если
все_для j
b[j]=p
все_для i
//находим минимальный элемент
//массива b
p=b0
//номер минимального элемента
pmin=0
для i=1 до 4-1 шаг 1
если p< bi
p=bi
pmin=i
все_если
все_для i
// вывод массива a построчно
для i=0 до 6-1 шаг 1
// в цикле изменяется номер i строки
// массива
для j=0 до 4-1 шаг 1
// в цикле изменяется номер j
// столбца массива
// затем этот элемент выводится на
// экран
вывод аij
все_для j
все_для i
// вывод массива b
для i=0 до 4-1 шаг 1
вывод bi
все_для i
печать pmin
| #include " stdio.h"
#include " stdlib.h"
#include " math.h"
int main()
{
float *a, p, *b;
int i, j, pmin, n, m;
//ввод n
printf (" n=");
scanf (" %i", & n);
//ввод m
printf (" m=");
scanf (" %i", & m);
//выделение динамической памяти под
//целочисленный массив из n строк и
//m столбцов
a=(float *)malloc(n*m*sizeof(float));
b=(float *)malloc(m*sizeof(float));
// ввод динамического массива a
// построчно
for(i=0; i< =n-1; i++)
{
for (j=0; j< =m-1; j++)
{
printf (" a[%i][%i]=", i, j);
scanf (" %f", a+i*m+j);
}
}
// вычисление произведений
for(j=0; j< =m-1; j++)
{
p=1;
for (i=0; i< =n-1; i++)
{
if(fmod(*(a+i*m+j), 2)==1)
p=p*(*(a+i*m+j));
}
*(b+j)=p;
}
//находим минимальный элемент массива //b
p=*b; //нулевой элемент массива b
pmin=0;
for (i=0; i< =m-1; i++)
{
if(p> *(b+i))
{
p=*(b+i);
pmin=i;
}
}
// вывод массива a построчно
for (i=0; i< =n-1; i++)
{
for (j=0; j< =m-1; j++)
printf (" %.2f ", *(a+i*m+j));
printf (" \n");
}
printf (" \n");
// вывод массива b
for (i=0; i< =m-1; i++)
{
printf (" %.2f ", *(b+i));
}
printf (" \n");
printf (" №min=%i\n", pmin);
free(a);
free(b);
return 1;
}
| 3. Создать проект и реализовать данную задачу в среде Visual C++ 6.0.
|