Смекни!
smekni.com

Одномерные и двумерные массивы (стр. 1 из 3)

Кафедра: Автоматика и информационные технологии

ОДНОМЕРНЫЕ И ДВУМЕРНЫЕ МАССИВЫ


Содержание

1. Теоретическая часть

1.1 Определение массива

1.2 Расположение в памяти

1.3 Обращение к элементу массива

1.4 Инициализация массивов

1.4.1 Одномерные массивы

1.4.2 Двумерные массивы

1.5 Тип имени массива

1.6 Передача одномерных массивов в функцию

1.7 Передача двумерных массивов в функцию

1.8 Тип и базовый тип указателя

1.9 Правила определения типа указателей

1.10 Указатель на void

1.11 Константные указатели

1.12 Адресная арифметика

1.13 Одинарный указатель – это одномерный массив

1.14 Одномерный массив – это одинарный указатель

1.15 Двумерный массив – это двойной указатель.

1.16 Двойной указатель – это двумерный массив

1.17 Просмотр указателей в отладчике

1.18 Контрольные вопросы.

2. Лабораторные задания

2.1 Скалярное произведение

2.2 Минимакс

2.3 Массивы строк

2.4 Трехмерный массив

3. Дополнительные задания

Библиографический список

1. Теоретическая часть

1.1 Определение массива

Определение. Массивом называется множество элементов одного типа, расположенных в памяти последовательно друг за другом.

При первом упоминании о массиве в программе под него сразу выделяется память. Поэтому правильно говорить не об объявлении массива, а об определении массива.

Синтаксис определения массива имеет вид

Тип элемента имя массива [n1][n2]...[nk];

где имя массива - идентификатор, определяемый в качестве имени массива, а ni - размеры массива. Массив называется k-мерным массивом с элементами типа тип элемента. Элементы i-го измерения имеют индексы от 0 до ni-1. Тип элемента массива может быть одним из основных типов, типом указателя (pointer), типом структуры (struct) или типом объединения (union). Хотя элементы массива не могут быть функциями, они могут быть указателями на функции.

Ниже приведены некоторые примеры определений массива:

int page[10]; /* одномерный массив из 10 элементов типа int, пронумерованный с 0 до 9 */char line[81];/*массив символов или строка, в которую можно записать не более 80 символов */float big[10][10], sales[10][5][8];

1.2 Расположение в памяти

Массивы могут быть следующих видов:

1. Локальные. Располагаются в стеке. Например,

main(){

int A[10];

//…..

}

2. Статические. Располагаются в области данных, глобальных и статических переменных. Например,

main(){

static int A[10];

//…..

}

3. Глобальные. Располагаются в области данных, глобальных и статических переменных. Например,

int A[10];

main(){

//…..

}

4. Дальние глобальные. Располагаются в дальней области глобальных переменных. Например,

far int A[10];

main(){

//…..

}

Двумерные массивы располагаются в памяти по строкам. Начальную строку массива называют нулевой строкой.

В общем случае, многомерные массивы располагаются в памяти так, что при последовательном просмотре его элементов последние индексы меняются быстрее.

Например, трехмерный массив intA[3][4][5] располагается в памяти слоями A[0][…][…], …, A[2][…][…].

Каждый слой, как двумерный массив, располагается по строкам. Например, A[0][0][…], …, A[0][3][…].

Массивы могут размещаться только в пределах одного сегмента, то есть общий размер массива в байтах не превышает 64К.

1.3 Обращение к элементу массива

Элементы массива могут стоять в обеих частях операции присваивания, то есть являются объектами Lvalue.

Задание элемента k-мерного массива реализуется последовательным применением операций индексации:

x[i1][i2]...[ik],

где ij - целое выражение, при этом 0<=ij<=nj -1, где nj-1 - максимальное значение j-го индекса массива. Например:

page[5]

line[i+j-1]

big[i][j]

Язык Си не проверяет выход индекса массива за диапазон. Обращение к несуществующему элементу массива является не синтаксической, а “хорошо скрытой” логической ошибкой. Она может привести к непредсказуемым результатам.

Операция индексации является левоассоциативной операцией, то есть выполняется в выражении слева направо. Поэтому при обращении к элементу массива вначале выполняется левая операция индексации []. К полученному результату применяется вторая операция индексации [] и т.д.

1.4 Инициализация массивов

Инициализация массивов может быть полной и частичной.

1.4.1 Одномерные массивы

1. В случае полной инициализации указывается полный список значений в фигурных скобках.

int A[4] = {1, 4, 2, 6};

Размеры массивов при полной инициализации можно не указывать. Компилятор сам для себя определит эти размеры и выделит соответствующую память. Программист может найти размеры с помощью операции sizeof. Операция возвращает размер всего, что угодно в байтах. В частности, sizeof(A) возвращает размер массива в байтах. Например,

int A[] = {1, 4, 2, 6};

int Dim = sizeof(A)/ sizeof(int); // 8/2=4

Лучшеписать

int Dim = sizeof(A)/ sizeof(A[0]); // 8/2=4

2. В случае частичной инициализации указывается размер массива и неполный список значений в фигурных скобках. Неинициализированные элементы получают нулевые значения. В случае

int A[4] = {1, 4};

элементы A[0] и A[1] получили значения, а в A[2] и A[3] записаны нули .

Если список инициализации больше размера массива, то возникнет ошибка компиляции.

// int A[4] = {1, 4, 4, 7, 2}; Ошибка

1.4.2 Двумерные массивы

1. В случае полной инициализации указывается полный список значений в фигурных скобках. Каждая строка инициализируется в своих фигурных скобках.

int A[3][4] ={ {1, 4, 2, 6},

{11, 1 4, 1 2, 1 6},

{1, 4, 2, 6}

};

Первый размер массива, то есть количество строк, при полной инициализации можно не указывать.

int A[][4] ={ {1, 4, 2, 6},

{11, 1 4, 1 2, 1 6},

{1, 4, 2, 6}

};

Компилятор сам для себя определит количество по списку инициализации. Программист может найти первый размер с помощью операции sizeof. В частности, sizeof(A) возвращает размер двумерного массива в байтах, а sizeof(A[0]) возвращает размер строки в байтах. Например,

int KolStrok = sizeof(A)/ sizeof(A[0]); // 24/82=3

2. В случае частичной инициализации указываются все размеры массива и неполные списки значений в фигурных скобках.

int A[4][4] ={ { 2, 6},

{ 1 4, 1 2, 1 6},

{6}

};

Если размер список инициализации больше хотя бы одного размера массива, то возникнет ошибка компиляции.

// int A[2][4] = {{1, 4, 4, 7, 2},

{1, 4, 4, 2}}; Ошибка

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

int A[2][4] = { 1, 4, 4, 7, 2, 1, 4, 4, 2};

Но такой способ чреват логической ошибкой в случае частичной инициализации.

Внимание. При определении массива без инициализации все размеры надо указывать явным образом.


1.5 Тип имени массива

Для одномерных массивов типом имени массива является тип_элемента_массива[]

Примеры.

Имя А массива charA[20]; имеет тип char[].

Имя В массива floatB[10] имеет тип float[].

Для двумерных массивов типом имени массива является тип_элемента_массива[][размер].

В типе имени массива нет информации о первом размере массива – о количестве строк.

Примеры.

Имя А массива charA[10][20]; имеет тип char[][20].

Имя B массива charB[100][20] тоже имеет тип char[][20].

Имя C массива charC[20][10] имеет тип char[][10], отличный от типов А и В.

1.6 Передача одномерных массивов в функцию

При передаче в функцию одномерного массива в списке фактических аргументов указываются имя массива и размер массива. В имени массива нет информации о размере массива. Компилятор по имени массива может определить только тип элементов массива и адрес начального элемента массива.

В списке формальных аргументов указываются только типы. Добавлять размер массива бесполезно.

Массивы передаются в функцию по адресу. Это означает, что функция работает с оригиналом массива и может изменять его элементы. Это факт используется для возвращения массивов из функции. С помощью оператора return массив вернуть нельзя.

Примеры прототипов

1. int max(int *A, int Dim);

Можно также писать

intmax(intA[], intDim);

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

// int max(int A[100]); ошибка

В списке формальных параметров записи int *A и intA[] равносильны.

2. float scal(float A[], float B[], int Dim);

Пример. Функция находит сумму элементов одномерного массива типа int и программу.

int sum( int *A, int Dim); // прототипфункции

int sum( int *A, int Dim)

{

int S =0;

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

S += A[i];

return S;

}

void main ()

{

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

int N = sizeof(B)/sizeof(B[0]);

printf (“&bsol;nСумма элементов равна %d”, sum(B, N) );

}

Пример. Функция находит все четные элементы в одномерном массиве.

intVseChot(intA[], intDimA, intChot[], intDimChot);

Функция находит четные элементы массива А и помещает их в массив Chot. При этом надо следить, чтобы количество четных элементов не превысило размер DimChot массива Chot. Возвращает количество найденных четных элементов. Если количество четных элементов превысило размер DimChot, то возвращается -1, а массив Chot полностью состоит из четных элементов массива А.

int VseChot(int A[], int DimA, int Chot[], int DimChot)

{

int count = 0;

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

if ( A[i] % 2 == 0) //четное число

if (count < DimChot)

Chot[count++] = A[i];

else

return -1;

}

void main()

{

int A[]={1, 2, 4, 6 ,7, 5};

int B[4];

int res = VseChot( A, 6, B, 4);

if(res = -1)

{

printf(“&bsol;n Найдены не все четные элементы массива:”);

for (int I = 0; I < 4; i++)

printf(“%d ”, B[i]);

}

else

{

printf(“&bsol;n Перечень четных элементов массива :”);

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

printf(“%d ”, B[i]);

}

}

1.7 Передача двумерных массивов в функцию

В случае двумерных массивов нужно точно соблюдать совпадение типов фактических и формальных параметров функции.

Примеры.

1. Функция находит максимальный элемент в массиве

int max(int A[][100], int KolStroc, int KolStolb);

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