Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции по С++.doc
Скачиваний:
34
Добавлен:
15.12.2018
Размер:
2.31 Mб
Скачать

1.2. Способы объявления и обращения к элементам двухмерных массивов

Рассмотрим объявление и связь указателей и элементов двухмерных массивов. Двухмерный массив в языке С++ рассматривается как совокупность одномерных масси­вов (его строк), а строка – совокупность элементов одно­мерного массива.

Объявление двухмерного массива с явным указанием количества элементов массива:

<тип_элементов_массива> <имя_массива>[<кол–во_строк>][<кол–во_столбцов>];

Для обращения к элементам двухмерного массива используется два индекса (индексных выражений):

<имя_массива>[<выражение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(), где для вывода элементов применялась та же форма записи.

  1. Создать проект и реализовать данную задачу в среде 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.