Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Многомерные массивы, динамическое распределение памяти






 

Кроме одномерных массивов возможна работа с многомерными массивами. Объявление многомерного массива:

< тип> < имя> [< размер 1 > ][< размер 2 > ]…[< размер N> ]={{список начальных значений}, {список начальных значений}, …};

Наиболее быстро изменяется последний индекс элементов массива, поскольку многомерные массивы размещаются в памяти компьютера в последователь­ности столбцов.

Например, элементы двухмерного массива b[2][1] размещаются в памяти в следующем порядке:

b[0][0], b[0][1], b[1][0], b[1][1], b[2][0], b[2][1].

Следующий пример иллюстрирует определение массива целого типа, состоящего из трех строк и четырех столбцов, с инициализацией начальных значений:

int a[3][4] = {{0, 1, 2, 0}, {9, -2, 0, 0}, {-7, 1, 6, 8}};

Если в какой-то группе {…} отсутствует значение, то соответствующему элементу присваивается 0. Предыдущий оператор будет эквивалентен следующему определению:

int a[3][4] = {{0, 1, 2}, {9, -2}, {-7, 1, 6, 8}};

 

Создать двумерный массив целых чисел NxM (N и M не более 50), используя функцию rand и вывести на экран в форме матрицы, N, M ввести с клавиатуры:

#include< stdio.h>

#include< stdlib.h>

#include< conio.h>

#define rnd (rand()/ 32768.0) // rand - генератор случайных чисел от 0 до int, rnd – от 0 до 1

void main(void)

{ int i, j, n, m, a[50][50];

puts(“\n Input n, m: ”); scanf(“%d %d”, & n, & m);

printf(“\n Array a \n”);

for(i=0; i< n; i++)

for(j=0; j< m; j++) {

a[i][j]=rnd*10-5; // диапазон от –5 до 5

printf(“%d%c“, a[i][j], (j= =m-1)? ’\n’: ’ ‘);

}

getch();

}

В языке С/C++ можно использовать массивы указателей, элементы которых содержат, как правило, указатели на строковые данные. Объявляется такой массив например так: char *m[5]. Здесь массив m[5] – массив, который может содержать пять адресов данных типа char.

Массив указателей можно при объявлении инициализировать, т.е. назначать его элементам конкретные адреса заданных строк.

В качестве примера приведена программа, формирующая массив указателей с одновременной инициализацией его элементов. Программа распечатывает номер строки, ее адрес и значение.

#include < stdio.h>

#include < conio.h>

void main(void)

{

int i, k;

char *m[]={" Winter", " Spring", " Summer", " Automn" };

k=sizeof(m)/sizeof(*m);

printf(" \n Количество строк = %d", k);

for(i=0; i< k; i++)

printf(" \n Номер - %d; Адрес - %p; Строка: %s", i+1, m[i], m[i]);

getch();

}

В результате получим:

Количество строк = 4

Номер - 1; Адрес - 0042007C; Строка: Winter

Номер - 2; Адрес - 00420074; Строка: Spring

Номер - 3; Адрес - 0042006C; Строка: Summer

Номер - 4; Адрес - 00420064; Строка: Automn

Конкретные значения адресов зависят от ряда причин: архитектура компьютера, тип и размер оперативной памяти и т.д.

Связь указателей и массивов с одним измерением справедливо и для массивов с большим числом измерений. Например, рассмотрим двумерный массив

float m[5][10];

Если рассматривать его как массив пяти массивов размерностью по десять элементов каждый, то очевидна схема его размещения в памяти - последовательное размещение «строк» элементов. Обращению к элементам m[i][j] соответствует эквива­лентное выражение *(*(m+i)+j), а объявление этого массива указателем будет:

float **m;

Таким образом, имя двумерного массива - имя указателя на указатель.

Например, двухмерный массив m(3х4) компилятор рассматривает как массив трех указателей, каждый из которых указывает на начало массива со значениями размером по четыре элемента каждый (рис. 1).

 

  m   значения  
Ука- m[0] m[0][0] m[0][1] m[0][2] m[0][3] *(*(m+i)+j)
за- m[1]   m[1][0] m[1][1] m[1][2] m[1][3]  
тели m[2]   m[2][0] m[2][1] m[2][2] m[2][3]  

 

рис. 1

 

Cхема размещения такого массива в памяти - последова­тельное (друг за другом) размещение строк - одномерных массивов со значениями.

Аналогичным образом можно установить соответствие между указателями и массивами с произвольным числом измерений. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:

int a=5;

int *p1=& a;

int **pp1=& p1;

int ***ppp1=& pp1;

Теперь присвоим целочисленной переменной а новое значение, например 10. Одинаковое присваивание произведут следующие операции:

a=10;

*p1=10;

**pp1=10;

***ppp1=10;

Для доступа к области памяти, отведенной под переменную а можно использовать и индексы. Справедливы следующие аналоги:

*p1 равносильно p1[0]

**pp1 равносильно pp1[0][0]

***ppp1 равносильно ppp1[0][0][0]

Таким образом, указатели на указатели – это имена многомерных массивов.

Очевидна эквивалентность выражений:

& name[0][0] < -> & (**name) < -> name // адрес нулевого элемента матрицы

**name < -> name[0][0] // значение нулевого элемента матрицы

Пример программы:

#include < stdio.h>

int x0[4]={ 1, 2, 3, 4};

int x1[4]={11, 12, 13, 14}; // Декларация и инициализация

int x2[4]={21, 22, 23, 24}; // массивов целых чисел

int *y[3]={x0, x1, x2}; // Создание массива указателей

void main(void)

{

int i, j;

for (i=0; i< 3; i++)

{

printf(" \n %2d)", i);

for (j=0; j< 4; j++) printf(" %2d", y[i][j]);

}

}

Результаты работы программы:

0) 1 2 3 4

1) 11 12 13 14

2) 21 22 23 24

 

Такие же результаты получим и при следующем объявлении массива:

int y[3][4]={{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}}; // Декларация и инициализация матрицы целых чисел

В последнем случае массив указателей на массивы создается компилятором. Здесь собственно данные массива располагаются в памяти последовательно по строкам, что является основанием для объявления y в виде

z[3][4]={ 1, 2, 3, 4, 11, 12, 13, 14, 21, 22, 23, 24}; // Декларация и инициализация матрицы целых чисел

скобочного выражения z[3][4] на z[12] здесь не допускается, так массив указателей в данном случае создан не будет.

 

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.