Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Техн. прогр. - Конспект лекций.doc
Скачиваний:
31
Добавлен:
15.03.2016
Размер:
877.06 Кб
Скачать

Многомерные массивы

Возможны по крайней мере три варианта реализации многомерных массивов.

1. Использование специальных типов данных. В этом случае размер по каждому измерению указывается в отдельных квадратных скобках. Обращение к элементам происходит аналогично одномерному массиву.

Пример:

int x[4][4][3];

x[0][0][0] = 5;

Массивы могут инициализироваться значениями в фигурных скобках, при этом допустимо не указывать последнюю (самую левую) размерность. Если заданная размерность меньше инициализирующих аргументов, часть элементов останется неопределенна. Обратная ситуация вызовет ошибку.

Примеры:

int x[3][2]={{1,2},{3,4},{5,6}}; //заданы и размеры массива, и инициализирующие значения

long y[] = {1,2,3,4}; // размер массива определяется фактическому по количеству // значений (4)

char t[][4] = {{1,2,3,4},{5,6}}; // последняя размерность определяется по числу значений (2) и // элементы t[1][2] и t[1][3] не определены

При таком указании данные располагаются в памяти последовательно, порядок расположения соответствует порядку указания при инициализации.

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

Пример:

int **x;

x = new int*[3];

for(int i=0;i<3;i++) x[i] = new int[i];

x[0][0] = 0; x[1][0] = 1; x[1][1] = 2; x[2][0] = 3; x[2][1]=4; x[2][2] = 5;

Получаем массив вида

0

12

345

В этом случае в памяти отдельно хранится массив указателей на строки и отдельно сами строки.

3. Хранение многомерного массива в одномерном.

Например, переход от двух индексов (i,j) можно осуществить по формуле i*m+j, где m – максимальная размерность по j (количество столбцов).

Указатели в качестве параметров функций

В списке формальных параметров функций указатели могут указываться как с использованием символа *, так и с использованием квадратных скобок. Данные определения равнозначны.

void f(char *x, double []y) {…}

Для передачи многомерных массивов удобно использовать определение типа (служебное слово typedef).

Пример.

typedef int myarray[5][5];

void f(myarray t)

{

}

void main()

{

myarray x;

f(x);

}

Для передачи в функцию константного указателя используется служебное слово const. Данные, на которые указывают такие указатели не могут быть переопределены, а также нельзя освободить память, занимаемую ими.

void f2(const char *t)

{

t[0] = ‘x’; /недопустимо

free(t); //недопустимо, но можно выполнить free((char *)t)

}

Функции работы с указателями и памятью

(заголовочные файлы alloc.h, stdlib.h, mem.h; в Visual Studio – memory.h, stdlib.h)

void* malloc(unsigned s) – выделение памяти s байт.

void* calloc(unsigned n, unsigned m) – выделение n элементов по m байт.

void* realloc(void* ptr, unsigned ns) – перевыделение памяти.

void free(void* ptr) – освобождение памяти.

int memcmp(void* s1, void* s2, unsigned n) – сравнивает две области памяти.

void* memcpy(const void* dest, const void* src, unsigned n) – копирование области памяти n байт из src в dest.

void* memset(void *ptr, int c, unsigned n) – запись числа c в память начиная с ptr.

Пример организации простейшего массива указателей на произвольные объекты.

#include <stdio.h>

#include <conio.h>

#include <memory.h>

#include <stdlib.h>

struct voidarray

{

void **data;

int size, topsize, step;

};

int init(voidarray*array, int initsize)

{

array->topsize = array->step = initsize;

array->size=0;

array->data=(void**)malloc(initsize*sizeof(void*));

return array->data!=NULL;

}

int add(voidarray*array, void* element)

{

array->size++;

if (array->size>array->topsize)

{

void **data2=(void**)malloc((array->topsize+array->step)*sizeof(void*));

if (data2==NULL) return -1;

memcpy(data2,array->data,array->topsize*sizeof(void*));

array->topsize+=array->step;

free(array->data);

array->data=data2;

}

array->data[array->size-1] = element;

return 0;

}

void dispose(voidarray*array)

{

free(array->data);

array->size = array->topsize = 0;

}

void* getat(voidarray*array,int n) {return n<array->size?array->data[n]:0;}

int main()

{

voidarray array;

init(&array,10);

for(int i=0;i<100;i++)

{add(&array,new int(i));}

for(int i=0;i<100;i++)

printf("%d",*(int*)getat(&array,i));

dispose(&array);

_getch();

}